4c292ea2b023a331dcf1af5644487f2272d24a4d

Author
Sebastian Gniazdowski <sgniazdowski@gmail.com>
Committer
Sebastian Gniazdowski <sgniazdowski@gmail.com>
Date

Message

Initial commit of Zsh Navigation Tools

Diff

This diff is truncated to protect this page.

   1diff --git a/plugins/zsh-navigation-tools/.config/znt/README.txt b/plugins/zsh-navigation-tools/.config/znt/README.txt
   2new file mode 100644
   3index 0000000000000000000000000000000000000000..c3d6c821a4d3ce187da67b942c0fc8ae91963f80
   4--- /dev/null
   5+++ b/plugins/zsh-navigation-tools/.config/znt/README.txt
   6@@ -0,0 +1 @@
   7+These are skeletons, configuration is read from ~/.config/znt/*
   8diff --git a/plugins/zsh-navigation-tools/.config/znt/n-aliases.conf b/plugins/zsh-navigation-tools/.config/znt/n-aliases.conf
   9new file mode 100644
  10index 0000000000000000000000000000000000000000..98f4625f128fdba477edc7176f7c9c3b04309d69
  11--- /dev/null
  12+++ b/plugins/zsh-navigation-tools/.config/znt/n-aliases.conf
  13@@ -0,0 +1,5 @@
  14+# How should be current element of the list drawn. Possible values: reverse,
  15+# underline. Default (without option set) is reverse
  16+# On Linux virtual terminal this will be enforced to reverse (because of poor
  17+# underline support on that terminal)
  18+# local active_text=underline
  19diff --git a/plugins/zsh-navigation-tools/.config/znt/n-cd.conf b/plugins/zsh-navigation-tools/.config/znt/n-cd.conf
  20new file mode 100644
  21index 0000000000000000000000000000000000000000..5fcfe64fa36058b0f64dc2ced46fb4568c290c08
  22--- /dev/null
  23+++ b/plugins/zsh-navigation-tools/.config/znt/n-cd.conf
  24@@ -0,0 +1,25 @@
  25+# Hotlist
  26+local hotlist
  27+hotlist=(
  28+    /usr/share/zsh/site-functions
  29+    /usr/share/zsh
  30+    /usr/local/share/zsh/site-functions
  31+    /usr/local/share/zsh
  32+    /usr/local/bin
  33+    /usr/lib
  34+)
  35+
  36+# Suppress adding (to directory stack) directories visited by n-cd
  37+# Value 0 is the default (directories will be added to dirstack)
  38+local NCD_DONT_PUSHD=0
  39+
  40+# How should be current element of the list drawn. Possible values: reverse,
  41+# underline. Default (without option set) is reverse
  42+# On Linux virtual terminal this will be enforced to reverse (because of poor
  43+# underline support on that terminal)
  44+# local active_text=underline
  45+
  46+# Colorize last segments of the paths
  47+# (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
  48+local NLIST_COLORING_PATTERN="[a-zA-Z0-9 ._-]##/#(#e)"
  49+local NLIST_COLORING_COLOR=$'\x1b[00;33m'
  50diff --git a/plugins/zsh-navigation-tools/.config/znt/n-env.conf b/plugins/zsh-navigation-tools/.config/znt/n-env.conf
  51new file mode 100644
  52index 0000000000000000000000000000000000000000..0c4bdce64938fbd29c86763acc07935c572fe933
  53--- /dev/null
  54+++ b/plugins/zsh-navigation-tools/.config/znt/n-env.conf
  55@@ -0,0 +1,9 @@
  56+# How should be current element of the list drawn. Possible values: reverse,
  57+# underline. Default (without option set) is reverse
  58+# On Linux virtual terminal this will be enforced to reverse (because of poor
  59+# underline support on that terminal)
  60+# local active_text=underline
  61+
  62+# (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
  63+local NLIST_COLORING_PATTERN="[a-zA-Z0-9_]##"
  64+local NLIST_COLORING_MATCH_MULTIPLE=0
  65diff --git a/plugins/zsh-navigation-tools/.config/znt/n-functions.conf b/plugins/zsh-navigation-tools/.config/znt/n-functions.conf
  66new file mode 100644
  67index 0000000000000000000000000000000000000000..93d31e8fd956dc832450c87ab195b46b94039180
  68--- /dev/null
  69+++ b/plugins/zsh-navigation-tools/.config/znt/n-functions.conf
  70@@ -0,0 +1,10 @@
  71+# Which editor to use, zed or vared
  72+# vared is the default
  73+local feditor="zed"
  74+# local feditor="vared"
  75+
  76+# How should be current element of the list drawn. Possible values: reverse,
  77+# underline. Default (without option set) is reverse
  78+# On Linux virtual terminal this will be enforced to reverse (because of poor
  79+# underline support on that terminal)
  80+# local active_text=underline
  81diff --git a/plugins/zsh-navigation-tools/.config/znt/n-history.conf b/plugins/zsh-navigation-tools/.config/znt/n-history.conf
  82new file mode 100644
  83index 0000000000000000000000000000000000000000..f798f71216df901dc2f22c701210e622fabeb85e
  84--- /dev/null
  85+++ b/plugins/zsh-navigation-tools/.config/znt/n-history.conf
  86@@ -0,0 +1,5 @@
  87+# How should be current element of the list drawn. Possible values: reverse,
  88+# underline. Default (without option set) is reverse
  89+# On Linux virtual terminal this will be enforced to reverse (because of poor
  90+# underline support on that terminal)
  91+local active_text=underline
  92diff --git a/plugins/zsh-navigation-tools/.config/znt/n-kill.conf b/plugins/zsh-navigation-tools/.config/znt/n-kill.conf
  93new file mode 100644
  94index 0000000000000000000000000000000000000000..f1c4f02dad87f92dac066f21563fc07076268442
  95--- /dev/null
  96+++ b/plugins/zsh-navigation-tools/.config/znt/n-kill.conf
  97@@ -0,0 +1,13 @@
  98+# How should be current element of the list drawn. Possible values: reverse,
  99+# underline. Default (without option set) is reverse
 100+# On Linux virtual terminal this will be enforced to reverse (because of poor
 101+# underline support on that terminal)
 102+# local active_text=underline
 103+
 104+# Colorize first number column and last path segment
 105+# This doesn't cover scripts named "[0-9]## *", which should be very rare
 106+# (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
 107+# | is alternative, but only in ()
 108+local NLIST_COLORING_PATTERN="((#s) #[0-9]## |[[][^]]#](#e)|[^ 0-9/?\\\\][^/\\\\]#(#e)|[^ /\\\\]##[^0-9/\\\\ ]##[^/\\\\]#(#e))"
 109+local NLIST_COLORING_COLOR=$'\x1b[00;33m'
 110+local NLIST_COLORING_MATCH_MULTIPLE=1
 111diff --git a/plugins/zsh-navigation-tools/.config/znt/n-list.conf b/plugins/zsh-navigation-tools/.config/znt/n-list.conf
 112new file mode 100644
 113index 0000000000000000000000000000000000000000..cf9d2a3be95de2d002789e8a8a82672eb076f39d
 114--- /dev/null
 115+++ b/plugins/zsh-navigation-tools/.config/znt/n-list.conf
 116@@ -0,0 +1,3 @@
 117+# Should the list (text, borders) be drawn in bold
 118+# Value 1 is the default
 119+local bold=1
 120diff --git a/plugins/zsh-navigation-tools/.config/znt/n-options.conf b/plugins/zsh-navigation-tools/.config/znt/n-options.conf
 121new file mode 100644
 122index 0000000000000000000000000000000000000000..98f4625f128fdba477edc7176f7c9c3b04309d69
 123--- /dev/null
 124+++ b/plugins/zsh-navigation-tools/.config/znt/n-options.conf
 125@@ -0,0 +1,5 @@
 126+# How should be current element of the list drawn. Possible values: reverse,
 127+# underline. Default (without option set) is reverse
 128+# On Linux virtual terminal this will be enforced to reverse (because of poor
 129+# underline support on that terminal)
 130+# local active_text=underline
 131diff --git a/plugins/zsh-navigation-tools/.config/znt/n-panelize.conf b/plugins/zsh-navigation-tools/.config/znt/n-panelize.conf
 132new file mode 100644
 133index 0000000000000000000000000000000000000000..98f4625f128fdba477edc7176f7c9c3b04309d69
 134--- /dev/null
 135+++ b/plugins/zsh-navigation-tools/.config/znt/n-panelize.conf
 136@@ -0,0 +1,5 @@
 137+# How should be current element of the list drawn. Possible values: reverse,
 138+# underline. Default (without option set) is reverse
 139+# On Linux virtual terminal this will be enforced to reverse (because of poor
 140+# underline support on that terminal)
 141+# local active_text=underline
 142diff --git a/plugins/zsh-navigation-tools/LICENSE b/plugins/zsh-navigation-tools/LICENSE
 143new file mode 100644
 144index 0000000000000000000000000000000000000000..075c80ccd2b537cbcc16186fc0fdd491c000557b
 145--- /dev/null
 146+++ b/plugins/zsh-navigation-tools/LICENSE
 147@@ -0,0 +1,700 @@
 148+This software is dual-licensed under MIT and GPLv3.
 149+
 150+MIT License
 151+-----------
 152+
 153+Permission is hereby granted, free of charge, to any person obtaining a copy
 154+of this software and associated documentation files (the "Software"), to deal
 155+in the Software without restriction, including without limitation the rights
 156+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 157+copies of the Software, and to permit persons to whom the Software is
 158+furnished to do so, subject to the following conditions:
 159+
 160+The above copyright notice and this permission notice shall be included in
 161+all copies or substantial portions of the Software.
 162+
 163+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 164+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 165+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 166+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 167+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 168+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 169+THE SOFTWARE.
 170+
 171+GPLv3  License
 172+--------------
 173+
 174+                    GNU GENERAL PUBLIC LICENSE
 175+                       Version 3, 29 June 2007
 176+
 177+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 178+ Everyone is permitted to copy and distribute verbatim copies
 179+ of this license document, but changing it is not allowed.
 180+
 181+                            Preamble
 182+
 183+  The GNU General Public License is a free, copyleft license for
 184+software and other kinds of works.
 185+
 186+  The licenses for most software and other practical works are designed
 187+to take away your freedom to share and change the works.  By contrast,
 188+the GNU General Public License is intended to guarantee your freedom to
 189+share and change all versions of a program--to make sure it remains free
 190+software for all its users.  We, the Free Software Foundation, use the
 191+GNU General Public License for most of our software; it applies also to
 192+any other work released this way by its authors.  You can apply it to
 193+your programs, too.
 194+
 195+  When we speak of free software, we are referring to freedom, not
 196+price.  Our General Public Licenses are designed to make sure that you
 197+have the freedom to distribute copies of free software (and charge for
 198+them if you wish), that you receive source code or can get it if you
 199+want it, that you can change the software or use pieces of it in new
 200+free programs, and that you know you can do these things.
 201+
 202+  To protect your rights, we need to prevent others from denying you
 203+these rights or asking you to surrender the rights.  Therefore, you have
 204+certain responsibilities if you distribute copies of the software, or if
 205+you modify it: responsibilities to respect the freedom of others.
 206+
 207+  For example, if you distribute copies of such a program, whether
 208+gratis or for a fee, you must pass on to the recipients the same
 209+freedoms that you received.  You must make sure that they, too, receive
 210+or can get the source code.  And you must show them these terms so they
 211+know their rights.
 212+
 213+  Developers that use the GNU GPL protect your rights with two steps:
 214+(1) assert copyright on the software, and (2) offer you this License
 215+giving you legal permission to copy, distribute and/or modify it.
 216+
 217+  For the developers' and authors' protection, the GPL clearly explains
 218+that there is no warranty for this free software.  For both users' and
 219+authors' sake, the GPL requires that modified versions be marked as
 220+changed, so that their problems will not be attributed erroneously to
 221+authors of previous versions.
 222+
 223+  Some devices are designed to deny users access to install or run
 224+modified versions of the software inside them, although the manufacturer
 225+can do so.  This is fundamentally incompatible with the aim of
 226+protecting users' freedom to change the software.  The systematic
 227+pattern of such abuse occurs in the area of products for individuals to
 228+use, which is precisely where it is most unacceptable.  Therefore, we
 229+have designed this version of the GPL to prohibit the practice for those
 230+products.  If such problems arise substantially in other domains, we
 231+stand ready to extend this provision to those domains in future versions
 232+of the GPL, as needed to protect the freedom of users.
 233+
 234+  Finally, every program is threatened constantly by software patents.
 235+States should not allow patents to restrict development and use of
 236+software on general-purpose computers, but in those that do, we wish to
 237+avoid the special danger that patents applied to a free program could
 238+make it effectively proprietary.  To prevent this, the GPL assures that
 239+patents cannot be used to render the program non-free.
 240+
 241+  The precise terms and conditions for copying, distribution and
 242+modification follow.
 243+
 244+                       TERMS AND CONDITIONS
 245+
 246+  0. Definitions.
 247diff --git a/plugins/zsh-navigation-tools/README.txt b/plugins/zsh-navigation-tools/README.txt
 248new file mode 100644
 249index 0000000000000000000000000000000000000000..4771742db58854bf04e1e06f0bd7a8a4a57689ec
 250--- /dev/null
 251+++ b/plugins/zsh-navigation-tools/README.txt
 252@@ -0,0 +1,101 @@
 253+# Zsh Navigation Tools
 254+
 255+http://imageshack.com/a/img633/7967/ps6rKR.png
 256+
 257+A tool generating a selectable curses-based list of elements that has access to
 258+current Zsh session, i.e. has broad capabilities to work together with it.
 259+That's n-list. The files n-cd, n-env, n-kill, etc. are applications of
 260+the tool. Feature highlights include incremental multi-word searching, ANSI
 261+coloring, unique mode, horizontal scroll, non-selectable elements, grepping and
 262+various integrations with Zsh.
 263+
 264+## History Widget
 265+
 266+To have n-history as the incremental searcher bound to Ctrl-R copy znt-*
 267+files into the */site-functions dir (unless you use Oh My Zsh) and
 268+add:
 269+
 270+    autoload znt-history-widget
 271+    zle -N znt-history-widget
 272+    bindkey "^R" znt-history-widget
 273+
 274+to .zshrc. This is done automatically when using Oh My Zsh. Two other
 275+widgets exist, znt-cd-widget and znt-kill-widget, they can be too assigned
 276+to key combinations:
 277+
 278+    zle -N znt-cd-widget
 279+    bindkey "^T" znt-cd-widget
 280+    zle -N znt-kill-widget
 281+    bindkey "^Y" znt-kill-widget
 282+
 283+## Introduction
 284+
 285+The tools are:
 286+
 287+- n-aliases - browses aliases, relegates editing to vared
 288+- n-cd - browses dirstack and bookmarked directories, allows to enter selected directory
 289+- n-functions - browses functions, relegates editing to zed or vared
 290+- n-history - browses history, allows to edit and run commands from it
 291+- n-kill - browses processes list, allows to send signal to selected process
 292+- n-env - browses environment, relegates editing to vared
 293+- n-options - browses options, allows to toggle their state
 294+- n-panelize - loads output of given command into the list for browsing
 295+
 296+All tools support horizontal scroll with <,>, {,}, h,l or left and right
 297+cursors. Other keys are:
 298+
 299+- [,] - jump directory bookmarks in n-cd and typical signals in n-kill
 300+- Ctrl-d, Ctrl-u - half page up or down
 301+- Ctrl-p, Ctrl-n - previous and next (also done with vim's j,k)
 302+- Ctrl-l - redraw of whole display
 303+- g, G - beginning and end of the list
 304+- Ctrl-o, o - enter uniq mode (no duplicate lines)
 305+- / - start incremental search
 306+- Enter - finish incremental search, retaining filter
 307+- Esc - exit incremental search, clearing filter
 308+- Ctrl-w (in incremental search) - delete whole word
 309+- Ctrl-k (in incremental search) - delete whole line
 310+
 311+## Programming
 312+
 313+The function n-list is used as follows:
 314+
 315+    n-list {element1} [element2] ... [elementN]
 316+
 317+This is all that is needed to be done to have the features like ANSI coloring,
 318+incremental multi-word search, unique mode, horizontal scroll, non-selectable
 319+elements (grepping is done outside n-list, see the tools for how it can be
 320+done). To set up non-selectable entries add their indices into array
 321+NLIST_NONSELECTABLE_ELEMENTS:
 322+
 323+    typeset -a NLIST_NONSELECTABLE_ELEMENTS
 324+    NLIST_NONSELECTABLE_ELEMENTS=( 1 )
 325+
 326+Result is stored as $reply[REPLY] ($ isn't needed before REPLY because
 327+of arithmetic context inside []). The returned array might be different from
 328+input arguments as n-list can process them via incremental search or uniq
 329+mode. $REPLY is the index in that possibly processed array. If $REPLY
 330+equals -1 it means that no selection have been made (user quitted via q
 331+key).
 332+
 333+To set up entries that can be jumped to with [,] keys add their indices to
 334+NLIST_HOP_INDEXES array:
 335+
 336+    typeset -a NLIST_HOP_INDEXES
 337+    NLIST_HOP_INDEXES=( 1 10 )
 338+
 339+n-list can automatically colorize entries according to a Zsh pattern.
 340+Following example will colorize all numbers with blue:
 341+
 342+    local NLIST_COLORING_PATTERN="[0-9]##"
 343+    local NLIST_COLORING_COLOR=$'\x1b[00;34m'
 344+    local NLIST_COLORING_END_COLOR=$'\x1b[0m'
 345+    local NLIST_COLORING_MATCH_MULTIPLE=1
 346+    n-list "This is a number 123" "This line too has a number: 456"
 347+
 348+Blue is the default color, it doesn't have to be set. See zshexpn man page
 349+for more information on Zsh patterns. Briefly, comparing to regular
 350+expressions, (#s) is ^, (#e) is $, # is *, ## is +. Alternative
 351+will work when in parenthesis, i.e. (a|b). BTW by using this method you can
 352diff --git a/plugins/zsh-navigation-tools/n-aliases b/plugins/zsh-navigation-tools/n-aliases
 353new file mode 100644
 354index 0000000000000000000000000000000000000000..d81db9253277ab36c2b12e733f51230d8dc9edd3
 355--- /dev/null
 356+++ b/plugins/zsh-navigation-tools/n-aliases
 357@@ -0,0 +1,47 @@
 358+# Copy this file into /usr/share/zsh/site-functions/
 359+# and add 'autoload n-aliases` to .zshrc
 360+#
 361+# This function allows to choose an alias for edition with vared
 362+#
 363+# Uses n-list
 364+
 365+emulate -L zsh
 366+
 367+setopt extendedglob
 368+zmodload zsh/curses
 369+zmodload zsh/parameter
 370+
 371+local IFS="
 372+"
 373+
 374+unset NLIST_COLORING_PATTERN
 375+
 376+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
 377+[ -f ~/.config/znt/n-aliases.conf ] && . ~/.config/znt/n-aliases.conf
 378+
 379+local list
 380+local selected
 381+
 382+NLIST_REMEMBER_STATE=0
 383+
 384+list=( "${(@k)aliases}" )
 385+list=( "${(@M)list:#(#i)*$1*}" )
 386+
 387+local NLIST_GREP_STRING="$1"
 388+
 389+if [ "$#list" -eq 0 ]; then
 390+    echo "No matching aliases"
 391+    return 1
 392+fi
 393+
 394+list=( "${(@i)list}" )
 395+n-list "$list[@]"
 396+
 397+if [ "$REPLY" -gt 0 ]; then
 398+    selected="$reply[REPLY]"
 399+    echo "Editing \`$selected':"
 400+    print -rs "vared aliases\\[$selected\\]"
 401+    vared aliases\[$selected\]
 402+fi
 403+
 404+# vim: set filetype=zsh:
 405diff --git a/plugins/zsh-navigation-tools/n-cd b/plugins/zsh-navigation-tools/n-cd
 406new file mode 100644
 407index 0000000000000000000000000000000000000000..b1ac5b1592599da160974fd6b2aecf65d5607cb6
 408--- /dev/null
 409+++ b/plugins/zsh-navigation-tools/n-cd
 410@@ -0,0 +1,68 @@
 411+# Copy this file into /usr/share/zsh/site-functions/
 412+# and add 'autoload n-cd` to .zshrc
 413+#
 414+# This function allows to choose a directory from pushd stack
 415+#
 416+# Uses n-list
 417+
 418+emulate -L zsh
 419+
 420+setopt extendedglob pushdignoredups
 421+
 422+zmodload zsh/curses
 423+local IFS="
 424+"
 425+
 426+# Unset before configuration is read
 427+unset NLIST_COLORING_PATTERN
 428+
 429+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
 430+[ -f ~/.config/znt/n-cd.conf ] && . ~/.config/znt/n-cd.conf
 431+
 432+local list
 433+local selected
 434+
 435+NLIST_REMEMBER_STATE=0
 436+
 437+list=( `dirs -p` )
 438+list=( "${(@M)list:#(#i)*$1*}" )
 439+
 440+local NLIST_GREP_STRING="$1"
 441+
 442+[ "$#list" -eq 0 ] && echo "No matching directories"
 443+
 444+if [ "$#hotlist" -ge 1 ]; then
 445+    typeset -a NLIST_NONSELECTABLE_ELEMENTS NLIST_HOP_INDEXES
 446+    local tmp_list_size="$#list"
 447+    NLIST_NONSELECTABLE_ELEMENTS=( $(( tmp_list_size+1 )) $(( tmp_list_size+2 )) )
 448+    list=( "$list[@]" "" $'\x1b[00;31m'"Hotlist"$'\x1b[00;00m': "$hotlist[@]" )
 449+    (( tmp_list_size+=3 ))
 450+    local middle_hop=$(( (tmp_list_size+$#list) / 2 ))
 451+    [[ "$middle_hop" -eq $tmp_list_size || "$middle_hop" -eq $#list ]] && middle_hop=""
 452+    [ "$tmp_list_size" -eq $#list ] && tmp_list_size=""
 453+    NLIST_HOP_INDEXES=( 1 $tmp_list_size $middle_hop $#list )
 454+else
 455+    [ "$#list" -eq 0 ] && return 1
 456+fi
 457+
 458+n-list "${list[@]}"
 459+
 460+if [ "$REPLY" -gt 0 ]; then
 461+    selected="$reply[REPLY]"
 462+    selected="${selected/#\~/$HOME}"
 463+
 464+    (( NCD_DONT_PUSHD )) && setopt NO_AUTO_PUSHD
 465+    cd "$selected"
 466+    (( NCD_DONT_PUSHD )) && setopt AUTO_PUSHD
 467+
 468+    # ZLE?
 469+    if [ "${(t)CURSOR}" = "integer-local-special" ]; then
 470+        zle -M "You have selected $selected"
 471+    else
 472+        echo "You have selected $selected"
 473+    fi
 474+else
 475+    [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
 476+fi
 477+
 478+# vim: set filetype=zsh:
 479diff --git a/plugins/zsh-navigation-tools/n-env b/plugins/zsh-navigation-tools/n-env
 480new file mode 100644
 481index 0000000000000000000000000000000000000000..612796c0062178dfac82173bb26c40e623dcb8b0
 482--- /dev/null
 483+++ b/plugins/zsh-navigation-tools/n-env
 484@@ -0,0 +1,47 @@
 485+# Copy this file into /usr/share/zsh/site-functions/
 486+# and add 'autoload n-env` to .zshrc
 487+#
 488+# This function allows to choose an environment variable
 489+# for edition with vared
 490+#
 491+# Uses n-list
 492+
 493+emulate -L zsh
 494+
 495+setopt extendedglob
 496+unsetopt equals
 497+zmodload zsh/curses
 498+
 499+local IFS="
 500+"
 501+
 502+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
 503+[ -f ~/.config/znt/n-env.conf ] && . ~/.config/znt/n-env.conf
 504+
 505+local list
 506+local selected
 507+
 508+NLIST_REMEMBER_STATE=0
 509+
 510+list=( `env` )
 511+list=( "${(@M)list:#(#i)*$1*}" )
 512+
 513+local NLIST_GREP_STRING="$1"
 514+
 515+if [ "$#list" -eq 0 ]; then
 516+    echo "No matching variables"
 517+    return 1
 518+fi
 519+
 520+list=( "${(@i)list}" )
 521+n-list "$list[@]"
 522+
 523+if [ "$REPLY" -gt 0 ]; then
 524+    selected="$reply[REPLY]"
 525+    selected="${selected%%=*}"
 526+    echo "Editing \`$selected':"
 527+    print -rs "vared \"$selected\""
 528+    vared "$selected"
 529+fi
 530+
 531+# vim: set filetype=zsh:
 532diff --git a/plugins/zsh-navigation-tools/n-functions b/plugins/zsh-navigation-tools/n-functions
 533new file mode 100644
 534index 0000000000000000000000000000000000000000..6f10a3dece90372c34578bfce3304409aeecb424
 535--- /dev/null
 536+++ b/plugins/zsh-navigation-tools/n-functions
 537@@ -0,0 +1,54 @@
 538+# Copy this file into /usr/share/zsh/site-functions/
 539+# and add 'autoload n-functions` to .zshrc
 540+#
 541+# This function allows to choose a function for edition with vared
 542+#
 543+# Uses n-list
 544+
 545+emulate -L zsh
 546+
 547+setopt extendedglob
 548+zmodload zsh/curses
 549+zmodload zsh/parameter
 550+
 551+local IFS="
 552+"
 553+
 554+unset NLIST_COLORING_PATTERN
 555+
 556+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
 557+[ -f ~/.config/znt/n-functions.conf ] && . ~/.config/znt/n-functions.conf
 558+
 559+local list
 560+local selected
 561+
 562+NLIST_REMEMBER_STATE=0
 563+
 564+list=( "${(@k)functions}" )
 565+list=( "${(@M)list:#(#i)*$1*}" )
 566+
 567+local NLIST_GREP_STRING="$1"
 568+
 569+if [ "$#list" -eq 0 ]; then
 570+    echo "No matching functions"
 571+    return 1
 572+fi
 573+
 574+list=( "${(@i)list}" )
 575+n-list "$list[@]"
 576+
 577+if [ "$REPLY" -gt 0 ]; then
 578+    selected="$reply[REPLY]"
 579+    if [ "$feditor" = "zed" ]; then
 580+        echo "Editing \`$selected' (ESC ZZ or Ctrl-x-w to finish):"
 581+        autoload zed
 582+        print -rs "zed -f -- \"$selected\""
 583+        zed -f -- "$selected"
 584+    else
 585+        echo "Editing \`$selected':"
 586+        print -rs "vared functions\\[$selected\\]"
 587+        vared functions\[$selected\]
 588+    fi
 589+fi
 590+
 591+# vim: set filetype=zsh:
 592diff --git a/plugins/zsh-navigation-tools/n-history b/plugins/zsh-navigation-tools/n-history
 593new file mode 100644
 594index 0000000000000000000000000000000000000000..e66f2a50a1801cacf265768c01d25b3a442ec73a
 595--- /dev/null
 596+++ b/plugins/zsh-navigation-tools/n-history
 597@@ -0,0 +1,53 @@
 598+# Copy this file into /usr/share/zsh/site-functions/
 599+# and add 'autoload n-history` to .zshrc
 600+#
 601+# This function allows to browse Z shell's history and use the
 602+# entries
 603+#
 604+# Uses n-list
 605+
 606+emulate -L zsh
 607+
 608+setopt extendedglob
 609+zmodload zsh/curses
 610+
 611+local IFS="
 612+"
 613+
 614+unset NLIST_COLORING_PATTERN
 615+
 616+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
 617+[ -f ~/.config/znt/n-history.conf ] && . ~/.config/znt/n-history.conf
 618+
 619+local list
 620+local selected
 621+
 622+NLIST_REMEMBER_STATE=0
 623+
 624+list=( `builtin history -rn 1` )
 625+list=( "${(@M)list:#(#i)*$1*}" )
 626+
 627+local NLIST_GREP_STRING="$1"
 628+
 629+if [ "$#list" -eq 0 ]; then
 630+    echo "No matching history entries"
 631+    return 1
 632+fi
 633+
 634+n-list "${list[@]}"
 635+
 636+if [ "$REPLY" -gt 0 ]; then
 637+    selected="$reply[REPLY]"
 638+    # ZLE?
 639+    if [ "${(t)CURSOR}" = "integer-local-special" ]; then
 640+        zle redisplay
 641+        zle kill-whole-line
 642+        zle -U "$selected"
 643+    else
 644+        print -zr "$selected"
 645+    fi
 646+else
 647+    [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
 648+fi
 649+
 650+# vim: set filetype=zsh:
 651diff --git a/plugins/zsh-navigation-tools/n-kill b/plugins/zsh-navigation-tools/n-kill
 652new file mode 100644
 653index 0000000000000000000000000000000000000000..e520822825450229a1e7400a77345119865c4a8c
 654--- /dev/null
 655+++ b/plugins/zsh-navigation-tools/n-kill
 656@@ -0,0 +1,96 @@
 657+# Copy this file into /usr/share/zsh/site-functions/
 658+# and add 'autoload n-kill` to .zshrc
 659+#
 660+# This function allows to choose a process and a signal to send to it
 661+#
 662+# Uses n-list
 663+
 664+emulate -L zsh
 665+
 666+setopt extendedglob
 667+zmodload zsh/curses
 668+
 669+local IFS="
 670+"
 671+
 672+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
 673+[ -f ~/.config/znt/n-kill.conf ] && . ~/.config/znt/n-kill.conf
 674+
 675+typeset -A signals
 676+signals=(
 677+     1       "1  - HUP"
 678+     2       "2  - INT"
 679+     3       "3  - QUIT"
 680+     6       "6  - ABRT"
 681+     9       "9  - KILL"
 682+     14      "14 - ALRM"
 683+     15      "15 - TERM"
 684+     17      "17 - STOP"
 685+     19      "19 - CONT"
 686+)
 687+
 688+local list
 689+local selected
 690+local signal
 691+local -a signal_names
 692+local title
 693+
 694+NLIST_REMEMBER_STATE=0
 695+
 696+typeset -a NLIST_NONSELECTABLE_ELEMENTS
 697+NLIST_NONSELECTABLE_ELEMENTS=( 1 )
 698+
 699+type ps 2>/dev/null 1>&2 || { echo >&2 "Error: \`ps' not found"; return 1 }
 700+
 701+case "$(uname)" in
 702+    CYGWIN*) list=( `command ps -Wa` )  ;;
 703+    *) list=( `command ps -o pid,uid,command -A` ) ;;
 704+esac
 705+
 706+# Ask of PID
 707+title=$'\x1b[00;31m'"${list[1]}"$'\x1b[00;00m\0'
 708+shift list
 709+list=( "$title" "${(@M)list:#(#i)*$1*}" )
 710+
 711+local NLIST_GREP_STRING="$1"
 712+
 713+if [ "$#list" -eq 1 ]; then
 714+    echo "No matching processes"
 715+    return 1
 716+fi
 717+
 718+n-list "$list[@]"
 719+
 720+# Got answer? (could be Ctrl-C or 'q')
 721+if [ "$REPLY" -gt 0 ]; then
 722+    selected="$reply[REPLY]"
 723+    selected="${selected## #}"
 724+    pid="${selected%% *}"
 725+
 726+    # Now ask of signal
 727+    signal_names=( ${(vin)signals} )
 728+    typeset -a NLIST_HOP_INDEXES
 729+    NLIST_HOP_INDEXES=( 3 6 8 )
 730+    unset NLIST_COLORING_PATTERN
 731+    n-list $'\x1b[00;31mSelect signal:\x1b[00;00m' "$signal_names[@]"
 732+
 733+    if [ "$REPLY" -gt 0 ]; then
 734+        selected="$reply[REPLY]"
 735+        signal="${(k)signals[(r)$selected]}"
 736+
 737+        # ZLE?
 738+        if [ "${(t)CURSOR}" = "integer-local-special" ]; then
 739+            zle redisplay
 740+            zle kill-whole-line
 741+            zle -U "kill -$signal $pid"
 742+        else
 743+            print -zr "kill -$signal $pid"
 744+        fi
 745+    else
 746+        [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
 747+    fi
 748+else
 749+    [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
 750+fi
 751+
 752+# vim: set filetype=zsh:
 753diff --git a/plugins/zsh-navigation-tools/n-list b/plugins/zsh-navigation-tools/n-list
 754new file mode 100644
 755index 0000000000000000000000000000000000000000..3b326515e0a0ec9bbfbbb5de588e8475cfb01760
 756--- /dev/null
 757+++ b/plugins/zsh-navigation-tools/n-list
 758@@ -0,0 +1,410 @@
 759+# $1, $2, ... - elements of the list
 760+# $NLIST_NONSELECTABLE_ELEMENTS - array of indexes (1-based) that cannot be selected
 761+# $REPLY is the output variable - contains index (1-based) or -1 when no selection
 762+#
 763+# Copy this file into /usr/share/zsh/site-functions/
 764+# and add 'autoload n-list` to .zshrc
 765+#
 766+# This function outputs a list of elements that can be
 767+# navigated with keyboard. Uses curses library
 768+
 769+emulate -LR zsh
 770+
 771+setopt typesetsilent extendedglob noshortloops
 772+
 773+_nlist_has_terminfo=0
 774+
 775+zmodload zsh/curses
 776+zmodload zsh/terminfo 2>/dev/null && _nlist_has_terminfo=1
 777+
 778+trap "REPLY=-2; reply=(); return" TERM INT QUIT
 779+trap "_nlist_exit" EXIT
 780+
 781+# Drawing and input
 782+autoload n-list-draw n-list-input
 783+
 784+# Cleanup before any exit
 785+_nlist_exit() {
 786+    setopt localoptions
 787+    setopt extendedglob
 788+
 789+    [[ "$REPLY" = -(#c0,1)[0-9]## ]] || REPLY="-1"
 790+    zcurses 2>/dev/null delwin inner
 791+    zcurses 2>/dev/null delwin main
 792+    zcurses 2>/dev/null refresh
 793+    zcurses end
 794+    _nlist_alternate_screen 0
 795+    _nlist_cursor_visibility 1
 796+    unset _nlist_has_terminfo
 797+}
 798+
 799+# Outputs a message in the bottom of the screen
 800+_nlist_status_msg() {
 801+    # -1 for border, -1 for 0-based indexing
 802+    zcurses move main $(( term_height - 1 - 1 )) 2
 803+    zcurses clear main eol
 804+    zcurses string main "$1"
 805+    #status_msg_strlen is localized in caller
 806+    status_msg_strlen=$#1
 807+}
 808+
 809+# Prefer tput, then module terminfo
 810+_nlist_cursor_visibility() {
 811+    if type tput 2>/dev/null 1>&2; then
 812+        [ "$1" = "1" ] && { tput cvvis; tput cnorm }
 813+        [ "$1" = "0" ] && tput civis
 814+    elif [ "$_nlist_has_terminfo" = "1" ]; then
 815+        [ "$1" = "1" ] && { [ -n $terminfo[cvvis] ] && echo -n $terminfo[cvvis];
 816+                           [ -n $terminfo[cnorm] ] && echo -n $terminfo[cnorm] }
 817+        [ "$1" = "0" ] && [ -n $terminfo[civis] ] && echo -n $terminfo[civis]
 818+    fi 
 819+}
 820+
 821+# Reason for this function is that on some systems
 822+# smcup and rmcup are not knowing why left empty
 823+_nlist_alternate_screen() {
 824+    [ "$_nlist_has_terminfo" -ne "1" ] && return
 825+    [[ "$1" = "1" && -n "$terminfo[smcup]" ]] && return
 826+    [[ "$1" = "0" && -n "$terminfo[rmcup]" ]] && return
 827+
 828+    case "$TERM" in
 829+        *rxvt*)
 830+            [ "$1" = "1" ] && echo -n $'\x1b7\x1b[?47h'
 831+            [ "$1" = "0" ] && echo -n $'\x1b[2J\x1b[?47l\x1b8'
 832+            ;;
 833+        *)
 834+            [ "$1" = "1" ] && echo -n $'\x1b[?1049h'
 835+            [ "$1" = "0" ] && echo -n $'\x1b[?1049l'
 836+            # just to remember two other that work: $'\x1b7\x1b[r\x1b[?47h', $'\x1b[?47l\x1b8'
 837+            ;;
 838+    esac
 839+}
 840+
 841+_nlist_compute_user_vars_difference() {
 842+        if [[ "${(t)NLIST_NONSELECTABLE_ELEMENTS}" != "array" &&
 843+                "${(t)NLIST_NONSELECTABLE_ELEMENTS}" != "array-local" ]]
 844+        then
 845+            last_element_difference=0
 846+            current_difference=0
 847+        else
 848+            last_element_difference=$#NLIST_NONSELECTABLE_ELEMENTS
 849+            current_difference=0
 850+            local idx
 851+            for idx in "${(n)NLIST_NONSELECTABLE_ELEMENTS[@]}"; do
 852+                [ "$idx" -le "$NLIST_CURRENT_IDX" ] && current_difference+=1 || break
 853+            done
 854+        fi
 855+}
 856+
 857+# List was processed, check if variables aren't off range
 858diff --git a/plugins/zsh-navigation-tools/n-list-draw b/plugins/zsh-navigation-tools/n-list-draw
 859new file mode 100644
 860index 0000000000000000000000000000000000000000..1b2571fbd42f0930f47717138bc9a21c14781cd5
 861--- /dev/null
 862+++ b/plugins/zsh-navigation-tools/n-list-draw
 863@@ -0,0 +1,131 @@
 864+# Copy this file into /usr/share/zsh/site-functions/
 865+# and add 'autoload n-list-draw` to .zshrc
 866+#
 867+# This is an internal function not for direct use
 868+
 869+emulate -L zsh
 870+
 871+zmodload zsh/curses
 872+
 873+setopt typesetsilent extendedglob
 874+
 875+_nlist_print_with_ansi() {
 876+    local win="$1" text="$2" out col chunk Xout
 877+    integer text_offset="$3" max_text_len="$4" text_len=0 no_match=0 nochunk_text_len to_skip_from_chunk to_chop_off_from_chunk before_len
 878+
 879+    # 1 - non-escaped text, 2 - first number in the escaped text, with ;
 880+    # 3 - second number, 4 - text after whole escape text
 881+
 882+    typeset -a c
 883+    c=( black red green yellow blue magenta cyan white )
 884+
 885+    while [[ -n "$text" && "$no_match" -eq 0 ]]; do
 886+        if [[ "$text" = (#b)([^$'\x1b']#)$'\x1b'\[([0-9](#c0,2))(#B)(\;|)(#b)([0-9](#c0,2))m(*) ]]; then
 887+            # Text for further processing
 888+            text="$match[4]"
 889+            # Text chunk to output now
 890+            out="$match[1]"
 891+            # Save color
 892+            col="$match[2]"
 893+            (( match[3] >= 30 && match[3] <= 37 )) && col="$match[3]"
 894+        else
 895+            out="$text"
 896+            no_match=1
 897+        fi
 898+
 899+        if [ -n "$out" ]; then
 900+################ Expand tabs ################
 901+            chunk="$out"
 902+            before_len="$text_len"
 903+            Xout=""
 904+
 905+            while [ -n "$chunk" ]; do
 906+                [[ "$chunk" = (#b)([^$'\t']#)$'\t'(*) ]] && {
 907+                    (( all_text_len=((before_len+${#match[1]})/8+1)*8 ))
 908+
 909+                    Xout+="${(r:all_text_len-before_len:: :)match[1]}"
 910+
 911+                    before_len+=all_text_len-before_len
 912+                    chunk="$match[2]"
 913+                } || {
 914+                    Xout+="$chunk"
 915+                    break
 916+                }
 917+            done
 918+#############################################
 919+
 920+            # Input text length without the current chunk
 921+            nochunk_text_len=text_len
 922+            # Input text length up to current chunk
 923+            text_len+="$#Xout"
 924+
 925+            # Should start displaying with this chunk?
 926+            # I.e. stop skipping left part of the input text?
 927+            if (( text_len > text_offset )); then
 928+                to_skip_from_chunk=text_offset-nochunk_text_len
 929+
 930+                # LEFT - is chunk off the left skip boundary? +1 for 1-based index in string
 931+                (( to_skip_from_chunk > 0 )) && Xout="${Xout[to_skip_from_chunk+1,-1]}"
 932+
 933+                # RIGHT - is text off the screen?
 934+                if (( text_len-text_offset > max_text_len )); then
 935+                    to_chop_off_from_chunk=0+(text_len-text_offset)-max_text_len
 936+                    Xout="${Xout[1,-to_chop_off_from_chunk-1]}"
 937+                fi
 938+                
 939+                [ -n "$Xout" ] && zcurses string "$win" "$Xout"
 940+            fi
 941+        fi
 942+
 943+        if (( no_match == 0 )); then
 944+            if (( col >= 30 && col <= 37 )); then
 945+                zcurses attr "$win" $c[col-29]/black
 946+            elif [[ "$col" -eq 0 ]]; then
 947+                zcurses attr "$win" white/black
 948+            fi
 949+        fi
 950+    done
 951+}
 952+
 953+integer highlight="$1"
 954+integer page_height="$2"
 955+integer page_width="$3"
 956+local y_offset="$4"
 957+local x_offset="$5"
 958+local text_offset="$6"
 959+local win="$7"
 960+shift 7
 961+integer max_text_len=page_width-x_offset
 962+
 963diff --git a/plugins/zsh-navigation-tools/n-list-input b/plugins/zsh-navigation-tools/n-list-input
 964new file mode 100644
 965index 0000000000000000000000000000000000000000..380acdc00aeedcf3b14b4a67e7bb2dae7a116ad6
 966--- /dev/null
 967+++ b/plugins/zsh-navigation-tools/n-list-input
 968@@ -0,0 +1,238 @@
 969+# Copy this file into /usr/share/zsh/site-functions/
 970+# and add 'autoload n-list-input` to .zshrc
 971+#
 972+# This is an internal function not for direct use
 973+
 974+emulate -L zsh
 975+
 976+zmodload zsh/curses
 977+
 978+setopt typesetsilent
 979+
 980+# Compute first to show index
 981+_nlist_compute_first_to_show_idx() {
 982+    from_what_idx_list_is_shown=0+((current_idx-1)/page_height)*page_height+1
 983+}
 984+
 985+typeset -ga reply
 986+reply=( -1 '' )
 987+integer current_idx="$1"
 988+integer from_what_idx_list_is_shown="$2"
 989+integer page_height="$3"
 990+integer page_width="$4"
 991+integer last_element="$5"
 992+integer hscroll="$6"
 993+local key="$7"
 994+integer search="$8"
 995+local buffer="$9"
 996+integer uniq_mode="$10"
 997+
 998+#
 999+# Listening for input
1000+#
1001+
1002+if [ "$search" = "0" ]; then
1003+
1004+case "$key" in
1005+    (UP|k|$'\C-P')
1006+        # Are there any elements before the current one?
1007+        [ "$current_idx" -gt 1 ] && current_idx=current_idx-1;
1008+        _nlist_compute_first_to_show_idx
1009+        ;;
1010+    (DOWN|j|$'\C-N')
1011+        # Are there any elements after the current one?
1012+        [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1;
1013+        _nlist_compute_first_to_show_idx
1014+        ;;
1015+    (PPAGE)
1016+        current_idx=current_idx-page_height
1017+        [ "$current_idx" -lt 1 ] && current_idx=1;
1018+        _nlist_compute_first_to_show_idx
1019+        ;;
1020+    (NPAGE|" ")
1021+        current_idx=current_idx+page_height
1022+        [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
1023+        _nlist_compute_first_to_show_idx
1024+        ;;
1025+    ($'\C-U')
1026+        current_idx=current_idx-page_height/2
1027+        [ "$current_idx" -lt 1 ] && current_idx=1;
1028+        _nlist_compute_first_to_show_idx
1029+        ;;
1030+    ($'\C-D')
1031+        current_idx=current_idx+page_height/2
1032+        [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
1033+        _nlist_compute_first_to_show_idx
1034+        ;;
1035+    (HOME|g)
1036+        current_idx=1
1037+        _nlist_compute_first_to_show_idx
1038+        ;;
1039+    (END|G)
1040+        current_idx=last_element
1041+        _nlist_compute_first_to_show_idx
1042+        ;;
1043+    ($'\n')
1044+        # Is that element selectable?
1045+        # Check for this only when there is no search
1046+        if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 ||
1047+            ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
1048+        then
1049+            # Save current element in the result variable
1050+            reply=( $current_idx SELECT )
1051+        fi
1052+        ;;
1053+    (q)
1054+        reply=( -1 QUIT )
1055+        ;;
1056+    (/)
1057+        search=1
1058+        _nlist_cursor_visibility 1
1059+        ;;
1060+    ($'\t')
1061+        reply=( $current_idx LEAVE )
1062+        ;;
1063+    ($'\C-L')
1064+        reply=( -1 REDRAW )
1065+        ;;
1066+    (\])
1067+        [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
1068diff --git a/plugins/zsh-navigation-tools/n-options b/plugins/zsh-navigation-tools/n-options
1069new file mode 100644
1070index 0000000000000000000000000000000000000000..91589bd455d4270bcb10631632f28b21dbf76327
1071--- /dev/null
1072+++ b/plugins/zsh-navigation-tools/n-options
1073@@ -0,0 +1,84 @@
1074+# Copy this file into /usr/share/zsh/site-functions/
1075+# and add 'autoload n-options` to .zshrc
1076+#
1077+# This function allows to browse and toggle shell's options
1078+#
1079+# Uses n-list
1080+
1081+#emulate -L zsh
1082+
1083+zmodload zsh/curses
1084+
1085+local IFS="
1086+"
1087+
1088+unset NLIST_COLORING_PATTERN
1089+
1090+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
1091+[ -f ~/.config/znt/n-options.conf ] && . ~/.config/znt/n-options.conf
1092+
1093+# TODO restore options
1094+unsetopt localoptions
1095+
1096+integer kshoptionprint=0
1097+[[ -o kshoptionprint ]] && kshoptionprint=1
1098+setopt kshoptionprint
1099+
1100+local list
1101+local selected
1102+local option
1103+local state
1104+
1105+# 0 - don't remember, 1 - remember, 2 - init once, then remember
1106+NLIST_REMEMBER_STATE=2
1107+
1108+local NLIST_GREP_STRING="${1:=}"
1109+
1110+while (( 1 )); do
1111+    list=( `setopt` )
1112+    list=( "${(M)list[@]:#*${1:=}*}" )
1113+    list=( "${list[@]:#kshoptionprint*}" )
1114+
1115+    if [ "$#list" -eq 0 ]; then
1116+        echo "No matching options"
1117+        break
1118+    fi
1119+
1120+    local red=$'\x1b[00;31m' green=$'\x1b[00;32m' reset=$'\x1b[00;00m'
1121+    list=( "${list[@]/ off/${red} off$reset}" )
1122+    #list=( "${list[@]/ on/${green} on$reset}" )
1123+    list=( "${(i)list[@]}" )
1124+
1125+    n-list "${list[@]}"
1126+
1127+    if [ "$REPLY" -gt 0 ]; then
1128+        [[ -o ksharrays ]] && selected="${reply[$(( REPLY - 1 ))]}" || selected="${reply[$REPLY]}"
1129+        option="${selected%% *}"
1130+        state="${selected##* }"
1131+
1132+        if [[ -o globsubst ]]; then
1133+            unsetopt globsubst
1134+            state="${state%$reset}"
1135+            setopt globsubst
1136+        else
1137+            state="${state%$reset}"
1138+        fi
1139+
1140+        # Toggle the option
1141+        if [ "$state" = "on" ]; then
1142+            echo "Setting |$option| to off"
1143+            unsetopt "$option"
1144+        else
1145+            echo "Setting |$option| to on"
1146+            setopt "$option"
1147+        fi
1148+    else
1149+        break
1150+    fi
1151+done
1152+
1153+NLIST_REMEMBER_STATE=0
1154+
1155+[[ "$kshoptionprint" -eq 0 ]] && unsetopt kshoptionprint
1156+
1157+# vim: set filetype=zsh:
1158diff --git a/plugins/zsh-navigation-tools/n-panelize b/plugins/zsh-navigation-tools/n-panelize
1159new file mode 100644
1160index 0000000000000000000000000000000000000000..a70565c79b03e32c616a78d0d4138fb72557e975
1161--- /dev/null
1162+++ b/plugins/zsh-navigation-tools/n-panelize
1163@@ -0,0 +1,61 @@
1164+# Copy this file into /usr/share/zsh/site-functions/
1165+# and add 'autoload n-panelize` to .zshrc
1166+#
1167+# This function somewhat reminds the panelize feature from Midnight Commander
1168+# It allows browsing output of arbitrary command. Example usage:
1169+# v-panelize ls /usr/local/bin
1170+#
1171+# Uses n-list
1172+
1173+emulate -L zsh
1174+
1175+setopt extendedglob
1176+zmodload zsh/curses
1177+
1178+local IFS="
1179+"
1180+
1181+unset NLIST_COLORING_PATTERN
1182+
1183+[ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
1184+[ -f ~/.config/znt/n-panelize.conf ] && . ~/.config/znt/n-panelize.conf
1185+
1186+local list
1187+local selected
1188+
1189+NLIST_REMEMBER_STATE=0
1190+
1191+if [ -t 0 ]; then
1192+    # Check if there is proper input
1193+    if [ "$#" -lt 1 ]; then
1194+        echo "Usage: n-panelize {command} [option|argument] ... or command | n-panelize"
1195+        return 1
1196+    fi
1197+
1198+    list=( `"$@"` )
1199+    # TODO: $? doesn't reach user
1200+    [ "$?" -eq 127 ] && return $?
1201+else
1202+    # Check if can reattach to terminal
1203+    if [[ ! -c /dev/tty && ! -t 2 ]]; then
1204+        echo "No terminal available (no /dev/tty)"
1205+        return 1
1206+    fi
1207+
1208+    list=( "${(@f)"$(<&0)"}" )
1209+
1210+    if [[ ! -c /dev/tty ]]; then
1211+        exec <&2
1212+    else
1213+        exec </dev/tty
1214+    fi
1215+fi
1216+
1217+n-list "${list[@]}"
1218+
1219+if [ "$REPLY" -gt 0 ]; then
1220+    selected="$reply[REPLY]"
1221+    print -zr "# $selected"
1222+fi
1223+
1224+# vim: set filetype=zsh:
1225diff --git a/plugins/zsh-navigation-tools/znt-cd-widget b/plugins/zsh-navigation-tools/znt-cd-widget
1226new file mode 100644
1227index 0000000000000000000000000000000000000000..6d1be6bffa76482a092efa146ba8465aef4ef79d
1228--- /dev/null
1229+++ b/plugins/zsh-navigation-tools/znt-cd-widget
1230@@ -0,0 +1,8 @@
1231+autoload znt-usetty-wrapper n-cd
1232+local NLIST_START_IN_SEARCH_MODE=0
1233+local NLIST_START_IN_UNIQ_MODE=0
1234+
1235+znt-usetty-wrapper n-cd "$@"
1236+
1237+unset NLIST_START_IN_SEARCH_MODE
1238+unset NLIST_START_IN_UNIQ_MODE
1239diff --git a/plugins/zsh-navigation-tools/znt-history-widget b/plugins/zsh-navigation-tools/znt-history-widget
1240new file mode 100644
1241index 0000000000000000000000000000000000000000..097de8233ea51a15d80ffae6807a53a379ebc370
1242--- /dev/null
1243+++ b/plugins/zsh-navigation-tools/znt-history-widget
1244@@ -0,0 +1,8 @@
1245+autoload znt-usetty-wrapper n-history
1246+local NLIST_START_IN_SEARCH_MODE=1
1247+local NLIST_START_IN_UNIQ_MODE=1
1248+
1249+znt-usetty-wrapper n-history "$@"
1250+
1251+unset NLIST_START_IN_SEARCH_MODE
1252+unset NLIST_START_IN_UNIQ_MODE
1253diff --git a/plugins/zsh-navigation-tools/znt-kill-widget b/plugins/zsh-navigation-tools/znt-kill-widget
1254new file mode 100644
1255index 0000000000000000000000000000000000000000..1aff7bb5090541fcf4dca7256251550c1b0bf4c8
1256--- /dev/null
1257+++ b/plugins/zsh-navigation-tools/znt-kill-widget
1258@@ -0,0 +1,8 @@
1259+autoload znt-usetty-wrapper n-kill
1260+local NLIST_START_IN_SEARCH_MODE=0
1261+local NLIST_START_IN_UNIQ_MODE=0
1262+
1263+znt-usetty-wrapper n-kill "$@"
1264+
1265+unset NLIST_START_IN_SEARCH_MODE
1266+unset NLIST_START_IN_UNIQ_MODE
1267diff --git a/plugins/zsh-navigation-tools/znt-usetty-wrapper b/plugins/zsh-navigation-tools/znt-usetty-wrapper
1268new file mode 100644
1269index 0000000000000000000000000000000000000000..19c5ac8b6364441581ac039fff667c7c2b4773a6
1270--- /dev/null
1271+++ b/plugins/zsh-navigation-tools/znt-usetty-wrapper
1272@@ -0,0 +1,40 @@
1273+emulate -L zsh
1274+
1275+zmodload zsh/curses
1276+
1277+test_fd0() {
1278+    true <&0
1279+}
1280+
1281+local restore=0 FD
1282+
1283+# Reattach to terminal
1284+if [ ! -t 0 ]; then
1285+    # Check if can reattach to terminal in any way
1286+    if [[ ! -c /dev/tty && ! -t 2 ]]; then
1287+        echo "No terminal available (no /dev/tty and no terminal at stderr)"
1288+        return 1
1289+    fi
1290+
1291+    if test_fd0 2>/dev/null; then
1292+        exec {FD}<&0
1293+        restore=2
1294+    else
1295+        restore=1
1296+    fi
1297+
1298+    if [[ ! -c /dev/tty ]]; then
1299+        exec <&2
1300+    else
1301+        exec </dev/tty
1302+    fi
1303+fi
1304+
1305+# Run the command
1306+"$@"
1307+
1308+# Restore FD state
1309+(( restore == 1 )) && exec <&-
1310+(( restore == 2 )) && exec <&$FD && exec {FD}<&-
1311+
1312+# vim: set filetype=zsh:
1313diff --git a/plugins/zsh-navigation-tools/zsh-navigation-tools.plugin.zsh b/plugins/zsh-navigation-tools/zsh-navigation-tools.plugin.zsh
1314new file mode 100755
1315index 0000000000000000000000000000000000000000..16247b8dbe13dcc3141adaad6c76e2af2e9ce0c0
1316--- /dev/null
1317+++ b/plugins/zsh-navigation-tools/zsh-navigation-tools.plugin.zsh
1318@@ -0,0 +1,38 @@
1319+#!/usr/bin/env zsh
1320+
1321+REPO_DIR="${0%/*}"
1322+CONFIG_DIR="$HOME/.config/znt"
1323+
1324+#
1325+# Copy configs
1326+#
1327+
1328+if ! test -d "$HOME/.config"; then
1329+    mkdir "$HOME/.config"
1330+fi
1331+
1332+if ! test -d "$CONFIG_DIR"; then
1333+    mkdir "$CONFIG_DIR"
1334+fi
1335+
1336+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
1337+
1338+for i; do
1339+    if ! test -f "$CONFIG_DIR/$i"; then
1340+        cp "$REPO_DIR/.config/znt/$i" "$CONFIG_DIR"
1341+    fi
1342+done
1343+
1344+#
1345+# Load functions
1346+#
1347+
1348+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
1349+autoload znt-usetty-wrapper znt-history-widget znt-cd-widget znt-kill-widget
1350+alias naliases=n-aliases ncd=n-cd nenv=n-env nfunctions=n-functions nhistory=n-history
1351+alias nkill=n-kill noptions=n-options npanelize=n-panelize
1352+
1353+zle -N znt-history-widget
1354+bindkey '^R' znt-history-widget
1355+setopt AUTO_PUSHD HIST_IGNORE_DUPS PUSHD_IGNORE_DUPS
1356+