Add zsh anything.el plugin
authorJoerg Jaspert <joerg@debian.org>
Thu, 3 Nov 2016 16:14:08 +0000 (17:14 +0100)
committerJoerg Jaspert <joerg@debian.org>
Thu, 3 Nov 2016 16:14:08 +0000 (17:14 +0100)
35 files changed:
.zsh/70_Plugins.zsh
.zsh/80_KeyBindings.zsh
.zsh/zaw/LICENSE [new file with mode: 0644]
.zsh/zaw/README.rst [new file with mode: 0644]
.zsh/zaw/functions/fill-vars-or-accept [new file with mode: 0644]
.zsh/zaw/functions/filter-select [new file with mode: 0644]
.zsh/zaw/sources/aliases.zsh [new file with mode: 0644]
.zsh/zaw/sources/applications.zsh [new file with mode: 0644]
.zsh/zaw/sources/bookmark.zsh [new file with mode: 0644]
.zsh/zaw/sources/cdr.zsh [new file with mode: 0644]
.zsh/zaw/sources/command-output.zsh [new file with mode: 0644]
.zsh/zaw/sources/commands.zsh [new file with mode: 0644]
.zsh/zaw/sources/fasd.zsh [new file with mode: 0644]
.zsh/zaw/sources/functions.zsh [new file with mode: 0644]
.zsh/zaw/sources/git-branches.zsh [new file with mode: 0644]
.zsh/zaw/sources/git-files.zsh [new file with mode: 0644]
.zsh/zaw/sources/git-log.zsh [new file with mode: 0644]
.zsh/zaw/sources/git-recent-branches.zsh [new file with mode: 0644]
.zsh/zaw/sources/git-reflog.zsh [new file with mode: 0644]
.zsh/zaw/sources/git-status.zsh [new file with mode: 0644]
.zsh/zaw/sources/history.zsh [new file with mode: 0644]
.zsh/zaw/sources/locate.zsh [new file with mode: 0644]
.zsh/zaw/sources/open-file.zsh [new file with mode: 0644]
.zsh/zaw/sources/perldoc.zsh [new file with mode: 0644]
.zsh/zaw/sources/process.zsh [new file with mode: 0644]
.zsh/zaw/sources/programs.zsh [new file with mode: 0644]
.zsh/zaw/sources/screens.zsh [new file with mode: 0644]
.zsh/zaw/sources/searcher.zsh [new file with mode: 0644]
.zsh/zaw/sources/ssh-hosts.zsh [new file with mode: 0644]
.zsh/zaw/sources/tmux.zsh [new file with mode: 0644]
.zsh/zaw/sources/widgets.zsh [new file with mode: 0644]
.zsh/zaw/zaw-launcher.zsh [new file with mode: 0755]
.zsh/zaw/zaw.plugin.zsh [new symlink]
.zsh/zaw/zaw.zsh [new file with mode: 0644]
.zsh/zshenv.local.sample

index 813b97d..72a03f6 100644 (file)
@@ -28,6 +28,7 @@ __ () {
             git-extras.plugin.zsh
             history-substring-search.zsh
             per-directory-history.plugin.zsh
+            zaw.zsh
         )
         for file in $plugins; do
             debug "PLUGIN: Trying to load ${file}"...
index 46f2743..0d42c5f 100644 (file)
@@ -181,6 +181,11 @@ bind2maps             vicmd -- -s "j"                   history-substring-search
 #k# search history and present a menu
 bind2maps emacs       vicmd -- -s "$key_info[Control]X$key_info[Control]X" history-beginning-search-menu
 
+#k# Trigger zsh anything.el
+if which zaw >/dev/null; then
+    bind2maps emacs viins       -- -s "$key_info[Control]X;"              zaw
+fi
+
 #k# Insert files and test globbing
 is4 && bind2maps emacs viins -- -s "$key_info[Control]Xf"              insert-files
 #k# Edit the current line in \kbd{\$EDITOR}
diff --git a/.zsh/zaw/LICENSE b/.zsh/zaw/LICENSE
new file mode 100644 (file)
index 0000000..96ddabd
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2011, NAKAMURA Yoshitaka
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the author nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/.zsh/zaw/README.rst b/.zsh/zaw/README.rst
new file mode 100644 (file)
index 0000000..d9a1158
--- /dev/null
@@ -0,0 +1,206 @@
+=================================
+zaw - zsh anything.el-like widget
+=================================
+
+install
+=======
+
+::
+
+  $ git clone git://github.com/zsh-users/zaw.git
+  remote: Counting objects: 136, done.
+  remote: Compressing objects: 100% (86/86), done.
+  remote: Total 136 (delta 43), reused 136 (delta 43)
+  Receiving objects: 100% (136/136), 23.68 KiB, done.
+  Resolving deltas: 100% (43/43), done.
+  $ echo "source ${PWD}/zaw/zaw.zsh" >> ~/.zshrc
+
+and restart zsh or manualy source ``zaw.zsh``.
+
+
+usage
+=====
+
+1. Trigger `zaw` by pressing ``Ctrl-x ;`` (``^x;``).
+2. select `source` and press ``enter``.
+3. filter items with zsh patterns separated by spaces, use ``^N``, ``^P`` and select one.
+4. execute action by pressing enter key or press ``Meta-enter`` for alternative action.
+
+   instead, press tab key and select action you want to execute.
+
+
+sources
+=======
+
+currently these sources are available:
+
+- aliases
+- applications
+- bookmark
+- cdr (needs cdr enabled.  Google it or use `this packaged version <https://github.com/willghatch/zsh-cdr>`_)
+- commands
+- command-output
+- fasd
+- fasd-directories
+- fasd-files
+- functions
+- git-branches
+- git-recent-all-branches
+- git-recent-branches
+- git-files
+- git-files-legacy
+- git-log
+- git-reflog
+- git-status
+- history
+- locate
+- open-file
+- perldoc
+- process
+- programs
+- screens
+- searcher (ag/ack)
+- ssh-hosts
+- tmux
+- widgets
+
+(Note: git-files-legacy is an alternative for git-files.
+git-files classifies modified files, git-files-legacy doesn't do it for
+performance reason.)
+
+Additional sources can be installed as third-party plugins.  Here is a list of all
+the ones we know about.  Please let us know about any more you find or make!
+Installation is easiest with a plugin manager such as 
+`zgen <https://github.com/tarjoilija/zgen>`_.  Otherwise you can just source the
+.zsh file that contains the source.
+
+- calibre source: https://github.com/junkblocker/calibre-zaw-source
+- MPD source: https://github.com/willghatch/zsh-zaw-mpd
+- `pass <http://www.passwordstore.org>`_ source: https://gist.github.com/f440/9992963
+- systemd source: https://github.com/termoshtt/zaw-systemd
+- `todoman <https://github.com/hobarrera/todoman>`_ source: https://github.com/willghatch/zsh-zaw-todoman
+
+shortcut widgets
+================
+
+zaw automaticaly create shortcut widgets for each sources
+that directly access to the source.
+
+for example, execute ``bindkey '^R' zaw-history`` and
+press ``^R`` to access history source.
+
+you can get all available shortcut widgets' name using ``zaw-print-src``::
+
+  $ zaw-print-src
+  source name      shortcut widget name
+  ----------------------------------------
+  ack              zaw-ack
+  applications     zaw-applications
+  bookmark         zaw-bookmark
+  git-branches     zaw-git-branches
+  git-recent-all-branches     zaw-git-recent-all-branches
+  git-recent-branches     zaw-git-recent-branches
+  git-files        zaw-git-files
+  git-files-legacy zaw-git-files-legacy
+  git-status       zaw-git-status
+  history          zaw-history
+  open-file        zaw-open-file
+  perldoc          zaw-perldoc
+  process          zaw-process
+  screens          zaw-screens
+  ssh-hosts        zaw-ssh-hosts
+  tmux             zaw-tmux
+  fasd             zaw-fasd
+  fasd-directories zaw-directories
+  fasd-files       zaw-files
+
+
+key binds and styles
+====================
+
+zaw use ``filter-select`` to filter and select items.
+
+you can use these key binds::
+
+  enter:              accept-line (execute default action)
+  meta + enter:       accept-search (execute alternative action)
+  Tab:                select-action
+  ^G:                 send-break
+  ^H, backspace:      backward-delete-char
+  ^F, right key:      forward-char
+  ^B, left key:       backward-char
+  ^A:                 beginning-of-line
+  ^E:                 end-of-line
+  ^W:                 backward-kill-word
+  ^K:                 kill-line
+  ^U:                 kill-whole-line
+  ^N, down key:       down-line-or-history (select next item)
+  ^P, up key:         up-line-or-history (select previous item)
+  ^V, page up key:    forward-word (page down)
+  ^[V, page down key: backward-word (page up)
+  ^[<, home key:      beginning-of-history (select first item)
+  ^[>, end key:       end-of-history (select last item)
+
+and these zstyles to customize styles::
+
+  ':filter-select:highlight' selected
+  ':filter-select:highlight' matched
+  ':filter-select:highlight' marked
+  ':filter-select:highlight' title
+  ':filter-select:highlight' error
+  ':filter-select' max-lines
+  ':filter-select' rotate-list
+  ':filter-select' case-insensitive
+  ':filter-select' extended-search
+  ':filter-select' hist-find-no-dups
+  ':filter-select' escape-descriptions
+
+  example:
+    zstyle ':filter-select:highlight' matched fg=yellow,standout
+    zstyle ':filter-select' max-lines 10 # use 10 lines for filter-select
+    zstyle ':filter-select' max-lines -10 # use $LINES - 10 for filter-select
+    zstyle ':filter-select' rotate-list yes # enable rotation for filter-select
+    zstyle ':filter-select' case-insensitive yes # enable case-insensitive search
+    zstyle ':filter-select' extended-search yes # see below
+    zstyle ':filter-select' hist-find-no-dups yes # ignore duplicates in history source
+    zstyle ':filter-select' escape-descriptions no # display literal newlines, not \n, etc
+
+  extended-search:
+      If this style set to be true value, the searching bahavior will be
+      extended as follows:
+  
+      ^ Match the beginning of the line if the word begins with ^
+      $ Match the end of the line if the word ends with $
+      ! Match anything except the word following it if the word begins with !
+      so-called smartcase searching
+  
+      If you want to search these metacharacters, please doubly escape them.
+
+environment variable
+====================
+
+ZAW_EDITOR              editor command. If this variable is not set, use EDITOR value.
+ZAW_EDITOR_JUMP_PARAM   open editor command with line params.
+                        %LINE% is replaced by line number.
+                        %FILE% is replaced by file path.
+                        default +%LINE% %FILE%
+
+
+making sources
+==============
+
+If you want to make another source, please do!  Look at https://github.com/termoshtt/zaw-systemd
+as an example of how to make a source repo.  Note that it uses the <name>.plugin.zsh
+convention that plugin managers like zgen and antigen expect for its main file.
+The sources directory contains the files for the actual sources.  All the sources
+in this repository's ``sources`` directory are good references as well for what
+the source files should look like.  They tend to be quite simple.
+If your source requires any additional configuration or dependencies, be sure to
+list all of that in your project's README file.
+
+Let us know when you make new plugins so we can add them to our list!
+
+license
+=======
+
+BSD-3
diff --git a/.zsh/zaw/functions/fill-vars-or-accept b/.zsh/zaw/functions/fill-vars-or-accept
new file mode 100644 (file)
index 0000000..545948a
--- /dev/null
@@ -0,0 +1,121 @@
+#
+# fill-vars-or-accept
+#
+
+# by default, pattern match "${:-variable_name}"
+FILL_VARS_PATTERN='${:-[a-z_][a-z0-9_]#}'
+
+function fill-vars-or-accept() {
+    # TODO: tab completion
+
+    local REPLY
+    local -a orig_region_highlight
+
+    if ! _buffer_has_vars; then
+        zle accept-line
+    fi
+
+    bindkey -N fillvars main
+    bindkey -M fillvars '^i' go-to-next-var
+
+    CURSOR=0
+
+    _get-current-var
+    if [[ -z "${REPLY}" ]]; then
+        go-to-next-var
+    fi
+
+    local POSTDISPLAY=$'\n''[press tab key to move cursor to next variable]'
+
+    while _buffer_has_vars && (( CURSOR < ${#BUFFER} )); do
+        orig_region_highlight=("${(@)region_highlight}")
+        _highlight-right-vars
+        zle -Rc
+        #zle -R '[press tab key to move next variable]'
+
+        zle read-command -K fillvars
+        reply="$?"
+        cmd_name="${REPLY}"
+
+        region_highlight=("${(@)orig_region_highlight}")
+
+        if [[ "${reply}" != 0 ]]; then
+            return 1
+        fi
+
+        if [[ "${cmd_name}" == accept* ]]; then
+            zle "${cmd_name}"
+            return
+
+        else
+            _get-current-var
+            if [[ -n "${REPLY}" ]]; then
+                if [[ "${cmd_name}" == self-insert* ]]; then
+                    # remove current var
+                    RBUFFER="${RBUFFER[$(( ${#REPLY} + 1)),-1]}"
+                elif [[ "${cmd_name}" == (*-delete-*|*-kill-*) ]]; then
+                    # remove current var and continue
+                    RBUFFER="${RBUFFER[$(( ${#REPLY} + 1)),-1]}"
+                    continue
+                fi
+            fi
+        fi
+
+        zle "${cmd_name}"
+    done
+}
+
+function _highlight-right-vars() {
+    emulate -L zsh
+    setopt local_options extended_glob
+
+    local nl=$'\n' rbuffer="${RBUFFER}" REPLY
+    local -a match mbegin mend
+    integer offset="${#LBUFFER}"
+
+    if _buffer_has_vars; then
+        _get-current-var
+        if [[ -n "${REPLY}" ]]; then
+            region_highlight+=( "${offset} $(( offset + ${#REPLY} )) standout" )
+            rbuffer="${rbuffer[$(( ${#REPLY}  )),-1]}"
+            (( offset += ${#REPLY} - 1 ))
+        fi
+
+        region_highlight+=( "${(f)${(S)rbuffer//*(#b)(${~FILL_VARS_PATTERN})/$(( offset + mbegin[1] - 1 )) $(( offset + mend[1] )) fg=yellow,standout${nl}}%$nl*}" )
+    fi
+}
+
+function _buffer_has_vars() {
+    emulate -L zsh
+    setopt local_options extended_glob
+    [[ "${BUFFER}" == *${~FILL_VARS_PATTERN}* ]]
+}
+
+function go-to-next-var() {
+    emulate -L zsh
+    setopt local_options extended_glob
+
+    local -a match mbegin mend
+    local rrbuffer="${RBUFFER[2,-1]}"
+    if [[ "${rrbuffer}" == *${~FILL_VARS_PATTERN}* ]]; then
+        # to match shortest, use variable expantion
+        : "${(S)rrbuffer/*(#b)(${~FILL_VARS_PATTERN})}"
+        (( CURSOR += ${mbegin[1]} ))
+    else
+        (( CURSOR = ${#BUFFER} ))
+    fi
+}
+
+zle -N go-to-next-var
+
+function _get-current-var() {
+    emulate -L zsh
+    setopt local_options extended_glob
+
+    REPLY=""
+    if [[ "${RBUFFER}" == (#b)(${~FILL_VARS_PATTERN})* ]]; then
+        REPLY="${match[1]}"
+    fi
+}
+
+fill-vars-or-accept "$@"
diff --git a/.zsh/zaw/functions/filter-select b/.zsh/zaw/functions/filter-select
new file mode 100644 (file)
index 0000000..6dd12a6
--- /dev/null
@@ -0,0 +1,743 @@
+#
+# filter-select
+#
+# using filter-select, you can incrementaly filter candidate
+# and select one with ^N/^P keys.
+#
+# press enter for filter-select to update $reply and return 0,
+# press meta (alt) + enter to update $reply but return 1,
+# and press ^C or ^G not to update $reply and return 1.
+#
+# you can use ^@ to mark items. marked items are stored in $reply_marked.
+#
+# you can customize keybinds using bindkey command.
+# first, you call::
+#
+#   autoload -U filter-select; filter-select -i
+#
+# to initialize `filterselect` keymap and then do like::
+#
+#   bindkey -M filterselect '^E' accept-search
+#
+#
+# usage:
+#   filter-select [-t title] [-A assoc-array-name]
+#                 [-d array-of-description] [-D assoc-array-of-descrption]
+#                 [-s initial-filter-contents]
+#                 [-n] [-r] [-m] [-e exit-zle-widget-name]... [--] [arg]...
+#   filter-select -i
+#
+#     -t title
+#       title string displayed top of selection.
+#
+#     -A assoc-array-name
+#       name of associative array that contains candidates.
+#       this option is designed to speed up history selection.
+#
+#     -d array-of-description
+#       name of array that contains each candidate's descriptions.
+#       it is used to display and filter candidates.
+#
+#       if not specified, copied from candidates.
+#
+#     -s initial-filter-contents
+#        initial contents of the filter buffer that users type into
+#
+#     -n
+#       assign a number to the description when -d is not specified
+#
+#     -D assoc-array-of-descrption
+#       same as ``-d`` but associative array.
+#
+#     -r
+#       reverse order.
+#
+#     -m
+#       enable mark feature
+#
+#     -e exit-zle-widget-name
+#       if keys bound to `exit-zle-widget-name` is pressed,
+#       filter-select exits and set it's name to $reply[1].
+#
+#     args
+#       selection candidates.
+#
+#     -i
+#       only initialize `filterselect` keymaps.
+#
+#
+# default key binds in filterselect:
+#   enter:              accept-line (update $reply and return)
+#   meta + enter:       accept-search (update $reply but return 1)
+#   ^G:                 send-break (return 0)
+#   ^H, backspace:      backward-delete-char
+#   ^F, right key:      forward-char
+#   ^B, left key:       backward-char
+#   ^A:                 beginning-of-line
+#   ^E:                 end-of-line
+#   ^W:                 backward-kill-word
+#   ^K:                 kill-line
+#   ^U:                 kill-whole-line
+#   ^N, down key:       down-line-or-history (select next item)
+#   ^P, up key:         up-line-or-history (select previous item)
+#   ^V, page up key:    forward-word (page down)
+#   ^[V, page down key: backward-word (page up)
+#   ^[<, home key:      beginning-of-history (select first item)
+#   ^[>, end key:       end-of-history (select last item)
+#
+# available zstyles:
+#   ':filter-select:highlight' selected
+#   ':filter-select:highlight' matched
+#   ':filter-select:highlight' title
+#   ':filter-select:highlight' error
+#   ':filter-select' max-lines
+#   ':filter-select' rotate-list
+#   ':filter-select' case-insensitive
+#   ':filter-select' extended-search
+#
+#   example:
+#     zstyle ':filter-select:highlight' matched fg=yellow,standout
+#     zstyle ':filter-select' max-lines 10 # use 10 lines for filter-select
+#     zstyle ':filter-select' max-lines -10 # use $LINES - 10 for filter-select
+#     zstyle ':filter-select' rotate-list yes # enable rotation for filter-select
+#     zstyle ':filter-select' case-insensitive yes # enable case-insensitive search
+#     zstyle ':filter-select' extended-search yes # enable extended search regardless of the case-insensitive style
+#
+# extended-search:
+#     If this style set to be true value, the searching bahavior will be
+#     extended as follows:
+#
+#     ^ Match the beginning of the line if the word begins with ^
+#     $ Match the end of the line if the word ends with $
+#     ! Match anything except the word following it if the word begins with !
+#     so-called smartcase searching
+#
+#     If you want to search these metacharacters, please doubly escape them.
+
+typeset -ga reply_marked
+
+function filter-select() {
+    emulate -L zsh
+    setopt local_options extended_glob
+
+    # save ZLE related variables
+    local orig_lbuffer="${LBUFFER}"
+    local orig_rbuffer="${RBUFFER}"
+    local orig_predisplay="${PREDISPLAY}"
+    local orig_postdisplay="${POSTDISPLAY}"
+    local -a orig_region_highlight words
+    orig_region_highlight=("${region_highlight[@]}")
+
+    local key cand lines selected cand_disp buffer_pre_zle last_buffer initbuffer=''
+    local opt pattern msg unused title='' exit_pattern nl=$'\n'
+    local selected_index mark_idx_disp hi start end spec
+    local desc desc_num desc_disp bounds
+
+    local -a displays matched_desc_keys match mbegin mend outs exit_wigdets
+    local -a init_region_highlight marked_lines
+    local -A candidates descriptions matched_descs
+
+    integer i bottom_lines cursor_line=1 display_head_line=1 cand_num disp_num ii num_desc
+    integer offset display_bottom_line selected_num rev=0 ret=0 enum=0
+    integer mark_idx markable=0 is_marked
+
+    local hi_selected hi_matched hi_marked hi_title hi_error
+    zstyle -s ':filter-select:highlight' selected hi_selected || hi_selected='standout'
+    zstyle -s ':filter-select:highlight' matched hi_matched || hi_matched='fg=magenta,underline'
+    zstyle -s ':filter-select:highlight' marked hi_marked || hi_marked='fg=blue,standout'
+    zstyle -s ':filter-select:highlight' title hi_title || hi_title='bold'
+    zstyle -s ':filter-select:highlight' error hi_error || hi_error='fg=white,bg=red'
+
+    integer max_lines
+    zstyle -s ':filter-select' max-lines max_lines || max_lines=0
+
+    local rotate_list
+    zstyle -b ':filter-select' rotate-list rotate_list
+
+    _filter-select-init-keybind
+
+    candidates=()
+    descriptions=()
+    exit_wigdets=(accept-line accept-search send-break)
+
+    while getopts 't:A:d:D:nrme:s:i' opt; do
+        case "${opt}" in
+            t)
+                title="${OPTARG}"
+                ;;
+            A)
+                # copy input assc array
+                candidates=("${(@kvP)${OPTARG}}")
+                ;;
+            d)
+                # copy input array
+                integer i=0
+                for desc in "${(@P)${OPTARG}}"; do
+                    (( i++ ))
+                    descriptions+=( $i "${desc}" )
+                done
+                ;;
+            D)
+                # copy input assc array
+                descriptions=("${(@kvP)${OPTARG}}")
+                ;;
+            n)
+                enum=1
+                ;;
+            r)
+                # reverse ordering
+                rev=1
+                ;;
+            m)
+                # can use set-mark-command
+                markable=1
+                ;;
+            e)
+                exit_wigdets+="${OPTARG}"
+                ;;
+            s)
+                initbuffer="${OPTARG}"
+                ;;
+            i)
+                # do nothing. only keybinds are initialized
+                return
+        esac
+    done
+
+    if (( OPTIND > 1 )); then
+        shift $(( OPTIND - 1 ))
+    fi
+    integer i=0
+    for cand in "$@"; do
+        (( i++ ))
+        candidates+=( $i "${cand}" )
+    done
+
+    if (( ${#descriptions} == 0 )); then
+        # copy candidates
+        descriptions=("${(@kv)candidates}")
+        # add number
+        if (( enum )); then
+            num_desc="${#descriptions}"
+            for i in {1.."$num_desc"}; do
+                if (( rev )); then
+                    ii="$(($num_desc-$i+1))"
+                else
+                    ii="$i"
+                fi
+                descriptions[$i]="${(r.5.)ii} ${descriptions[$i]}"
+            done
+        fi
+    fi
+
+    desc_num="${#descriptions}"
+    matched_desc_keys=("${(onk@)descriptions}")
+    if (( rev )); then
+        matched_desc_keys=("${(Oa@)matched_desc_keys}")
+    fi
+
+    key=''
+    bounds=''
+
+    # clear edit buffer
+    BUFFER="$initbuffer"
+
+    # display original edit buffer's contants as PREDISPLAY
+    PREDISPLAY="${orig_predisplay}${orig_lbuffer}${orig_rbuffer}${orig_postdisplay}${nl}"
+
+    # re-calculate region_highlight
+    init_region_highlight=()
+    for hi in "${(@)orig_region_highlight}"; do
+        if [[ "${hi}" == P* ]]; then
+            init_region_highlight+="${hi}"
+        else
+            print -r -- "${hi}" | read start end spec
+            init_region_highlight+="P$(( start + ${#orig_predisplay} )) $(( end + ${#orig_predisplay} )) $spec"
+        fi
+    done
+
+    # prompt for filter-select
+    PREDISPLAY+="filter: "
+
+    # clear strings displayed below the command line
+    zle -Rc
+
+    _filter-select-reset
+
+    exit_pattern="(${(j:|:)exit_wigdets})"
+
+    while [[ "${bounds}" != ${~exit_pattern} ]]; do
+        case "${bounds}" in
+            set-mark-command)
+                if (( markable )); then
+                    # check if ${selected_index} is already in the marked_lines
+                    if (( ${marked_lines[(ie)${selected_index}]} <= ${#marked_lines} )); then
+                        # remove selected_index
+                        marked_lines=("${(@)marked_lines:#${selected_index}}")
+                    else
+                        marked_lines+="${selected_index}"
+                    fi
+                fi
+                ;;
+            *down-line-or-history)
+                (( cursor_line++ ))
+                ;;
+
+            *up-line-or-history)
+                (( cursor_line-- ))
+                ;;
+
+            *forward-word)
+                (( cursor_line += bottom_lines ))
+                ;;
+
+            *backward-word)
+                (( cursor_line -= bottom_lines ))
+                ;;
+
+            beginning-of-history)
+                (( cursor_line = 1 ))
+                (( display_head_line = 1 ))
+                ;;
+
+            end-of-history)
+                (( cursor_line = desc_num ))
+                ;;
+
+            self-insert|undefined-key)
+                LBUFFER="${LBUFFER}${key}"
+                _filter-select-reset
+                ;;
+
+            '')
+                # empty, initial state
+                ;;
+
+            *)
+                buffer_pre_zle="${BUFFER}"
+
+                zle "${bounds}"
+
+                if [[ "${BUFFER}" != "${buffer_pre_zle}" ]]; then
+                    _filter-select-reset
+                fi
+        esac
+
+        if (( cursor_line < 1 )); then
+            (( display_head_line -= 1 - cursor_line ))
+            if (( display_head_line < 1 )); then
+                (( display_head_line = 1 ))
+            fi
+            if [[ $rotate_list == "yes" ]] && (( selected_num <= 1 )); then
+                (( cursor_line = bottom_lines ))
+                (( display_head_line = desc_num - bottom_lines + 1 ))
+            else
+                (( cursor_line = 1 ))
+            fi
+
+        elif (( bottom_lines == 0 )); then
+            (( display_head_line = 1 ))
+            (( cursor_line = 1 ))
+
+        elif (( cursor_line > bottom_lines )); then
+            (( display_head_line += cursor_line - bottom_lines ))
+            if (( display_head_line > desc_num - bottom_lines + 1 )); then
+                (( display_head_line = desc_num - bottom_lines + 1 ))
+            fi
+            if [[ $rotate_list == "yes" ]] && (( selected_num >= desc_num )); then
+                (( cursor_line = 1 ))
+                (( display_head_line = 1 ))
+            else
+                (( cursor_line = bottom_lines ))
+            fi
+        fi
+
+        if (( ! PENDING )); then
+            region_highlight=("${(@)init_region_highlight}")
+
+            displays=()
+            offset="${#BUFFER}"
+            if [[ -n "${title}" ]]; then
+                offset+=$(( 1 + ${#title} ))
+            fi
+
+            selected=""
+            selected_num=0
+
+            if [[ "${BUFFER}" != "${last_buffer}" ]]; then
+                if [[ -n "${BUFFER}" ]]; then
+                    if _filter-select-buffer-words words; then
+                        matched_descs=("${(kv@)descriptions}")
+                        for pattern in $words; do
+                            matched_descs=("${(kv@)matched_descs[(R)*${pattern}*]}")
+                        done
+                        matched_desc_keys=("${(onk@)matched_descs}")
+                    else
+                        matched_desc_keys=("${(onk@)descriptions}")
+                    fi
+                else
+                    matched_desc_keys=("${(onk@)descriptions}")
+                fi
+                if (( rev )); then
+                    matched_desc_keys=("${(Oa@)matched_desc_keys}")
+                fi
+                last_buffer="${BUFFER}"
+            fi
+
+            # nums pattern matched
+            desc_num="${#matched_desc_keys}"
+
+            # nums displayed
+            disp_num=0
+
+            _filter-select-update-bottom-lines
+            display_bottom_line=$(( display_head_line + bottom_lines))
+
+            if (( desc_num )); then
+                for i in "${(@)matched_desc_keys[${display_head_line},$(( display_bottom_line - 1 ))]}"; do
+                    (( disp_num++ ))
+                    desc="${descriptions[$i]}"
+
+                    desc_disp="${desc}"
+
+                    if zstyle -T ':filter-select' escape-descriptions ; then
+                        # escape \r\n\t\
+                        desc_disp="${desc_disp//\\/\\\\}"
+                        desc_disp="${desc_disp//$'\n'/\\n}"
+                        desc_disp="${desc_disp//$'\r'/\\r}"
+                        desc_disp="${desc_disp//$'\t'/\\t}"
+                    fi
+
+                    mark_idx="${marked_lines[(ie)${i}]}"
+                    (( is_marked = mark_idx <= ${#marked_lines} ))
+
+                    if (( is_marked )); then
+                        mark_idx_disp=" (${mark_idx})"
+                    else
+                        mark_idx_disp=""
+                    fi
+
+                    if (( ${(m)#desc_disp} + ${#mark_idx_disp} > COLUMNS - 1 )); then
+                        # strip long line
+                        desc_disp="${(mr:$(( COLUMNS - ${#mark_idx_disp} - 6 )):::::)desc_disp} ...${mark_idx_disp}"
+                    else
+                        desc_disp="${desc_disp}${mark_idx_disp}"
+                    fi
+
+                    displays+="${desc_disp}"
+
+                    if [[ -n "${BUFFER}" ]]; then
+                        # highlight matched words
+                        for pattern in \
+                            "(${(j.|.)${(@M)words:#*'(#e)'}})" \
+                            "(${(j.|.)${(@)words:#(\~*|*'(#e)')}})" ; do
+                            if [[ "$pattern" != '()' ]]; then
+                                region_highlight+=( "${(f)${(S)desc_disp//*(#b)${~pattern}/$(( offset + mbegin[1] )) $(( offset + mend[1] + 1 )) ${hi_matched}${nl}}%$nl*}" )
+                            fi
+                        done
+                    fi
+
+                    if (( is_marked )); then
+                        region_highlight+="${offset} $(( offset + ${#desc_disp} - ${#mark_idx_disp} + 1 )) ${hi_marked}"
+                    fi
+
+                    if (( disp_num == cursor_line )); then
+                        region_highlight+="${offset} $(( offset + ${#desc_disp} + 1 )) ${hi_selected}"
+                        selected="${candidates[$i]}"
+                        (( selected_num = display_head_line + disp_num - 1 ))
+                        selected_index="${i}"
+                    fi
+
+                    (( offset += ${#desc_disp} + 1 )) # +1 -> \n
+                done
+            fi
+
+            POSTDISPLAY=$'\n'
+            if [[ -n "${title}" ]]; then
+                POSTDISPLAY+="${title}"$'\n'
+                region_highlight+="${#BUFFER} $(( ${#BUFFER} + ${#title} + 1 )) ${hi_title}"
+            fi
+
+            if (( ${#displays} == 0 )); then
+                if (( ${#candidates} == 0 )); then
+                    msg='no candidate'
+                else
+                    msg='pattern not found'
+                fi
+                POSTDISPLAY+="${msg}"
+                region_highlight+="${offset} $(( offset + ${#msg} + 1 )) ${hi_error}"
+            fi
+
+            POSTDISPLAY+="${(F)displays}"$'\n'"[${selected_num}/${desc_num}]"
+            zle -R
+
+        fi
+
+        _filter-select-read-keys
+
+        if [[ $? != 0 ]]; then
+            # maybe ^C
+            key=''
+            bounds=''
+            break
+        else
+            key="${reply}"
+            # TODO: key sequence
+            outs=("${(z)$( bindkey -M filterselect -- "${key}" )}")
+            # XXX: will $outs contains more than two values?
+            bounds="${outs[2]}"
+        fi
+    done
+
+    if [[ -z "${key}" && -z "${bounds}" ]]; then
+        # ^C
+        reply=()
+        reply_marked=()
+        ret=1
+
+    elif [[ "${bounds}" == send-break ]]; then
+        # ^G
+        reply=()
+        reply_marked=()
+        ret=1
+
+    elif (( ${#displays} == 0 )); then
+        # no candidate matches pattern (no candidate selected)
+        reply=()
+        reply_marked=()
+        ret=1
+
+    else
+        reply=("${bounds}" "${selected}")
+        reply_marked=()
+        if (( ${#marked_lines} > 0 )); then
+            for i in "${(@)marked_lines}"; do
+                reply_marked+="${candidates[${i}]}"
+            done
+        fi
+        ret=0
+    fi
+
+    LBUFFER="${orig_lbuffer}"
+    RBUFFER="${orig_rbuffer}"
+    PREDISPLAY="${orig_predisplay}"
+    POSTDISPLAY="${orig_postdisplay}"
+    region_highlight=("${orig_region_highlight[@]}")
+    zle -Rc
+    zle reset-prompt
+
+    return $ret
+}
+
+function _filter-select-update-lines() {
+    # XXX: this function override ${lines}
+    #      that define as local in filter-select
+    #      also use ${title}
+
+    local _tmp_postdisplay="${POSTDISPLAY}"
+    # to re-calculate ${BUFFERLINES}
+    if [[ -n "${title}" ]]; then
+        POSTDISPLAY="${title}"$'\n'
+    else
+        POSTDISPLAY=""
+    fi
+    zle -R
+
+    # lines that can be used to display candidates
+    # -1 for current/total number display area
+    (( lines = LINES - BUFFERLINES - 1 ))
+
+    POSTDISPLAY="${_tmp_postdisplay}"
+    zle -R
+}
+
+function _filter-select-update-bottom-lines() {
+    # cursor が移動できる一番下の行
+    # ${max_lines} か ${lines} か ${desc_num} の小さい方を使う
+    if (( max_lines > 0 && max_lines < lines )); then
+        (( bottom_lines = max_lines ))
+    elif (( max_lines < 0 )); then
+        (( bottom_lines = lines + max_lines ))
+    else
+        (( bottom_lines = lines ))
+    fi
+
+    if (( desc_num < bottom_lines )); then
+        (( bottom_lines = desc_num ))
+    fi
+
+    if (( bottom_lines < 1 )); then
+        (( bottom_lines = 1 ))
+    fi
+}
+
+function _filter-select-reset() {
+    display_head_line=1
+    cursor_line=1
+    _filter-select-update-lines
+    _filter-select-update-bottom-lines
+}
+
+function _filter-select-buffer-words() {
+    local place="$1"
+    local -a a
+    local MATCH MBEGIN MEND
+    # split into words using shell's command line parsing,
+    # unquote the words, remove duplicated,
+    # escape "(", ")", "[", "]" and "#" to avoid crash
+    # also escape "|" and "~"
+    a=("${(@)${(@Qu)${(z)BUFFER}}//(#m)[()[\]#\|~]/\\${MATCH}}")
+
+    if ! zstyle -t ':filter-select' extended-search ; then
+        if zstyle -t ':filter-select' case-insensitive; then
+            : ${(A)a::=(#i)${^a}}
+        fi
+    else
+        # remove single "\\", "!",
+        # "^" like the history-incremental-pattern-searches',
+        # and "!^".
+        : ${(A)a::=${a:#([\\!^]|'!^')}}
+
+        # escape "^" other than the beginning's
+        # unescape "\\^" one level
+        : ${(A)a::=${a//(#m)('^'~(#s)'^')/\\${MATCH}}}
+        : ${(A)a::=${a//(#m)'\\^'/${MATCH#\\}}}
+
+        # "!aoe" -> "~*aoe",
+        # ("a!oe" should be held on, the beginning's "!" only be considered)
+        # unescape "\\!" one level
+        : ${(A)a::=${a/(#m)(#s)\!?##/\~\*${MATCH#\!}}}
+        : ${(A)a::=${a//(#m)'\!'/${MATCH#\\}}} # XXX: not '\\!' though...
+
+        # "^abc" -> "(#s)abc",
+        # ("a^bc" should be held on, the beginning's "^" only be considered)
+        : ${(A)a::=${a/(#m)(#s)\^?##/(#s)${MATCH#\^}}}
+
+        # "xyz$" -> "xyz(#e)",
+        # ("x$yz" shoud be held on, the ending's "$" only be considered)
+        # unescape "\\$" one level
+        : ${(A)a::=${a/(#m)*[^\\]\$(#e)/${MATCH%\$}(#e)}}
+        : ${(A)a::=${a//(#m)'\$'/${MATCH#\\}}} # XXX: not '\\$' though...
+
+        # smartcase searching ("(#i)(#I)Search" searches case sensitively)
+        : ${(A)a::=${a/(#m)*[[:upper:]##]*/(#I)${MATCH}}}
+        : ${(A)a::=(#i)${^a}}
+
+        # make "~" to be at the beginning
+        #: ${(A)a::=${a/#(#b)('(#i)'('(#I)')#)'~'/\~${match[1]}}}
+        : ${(A)a::=${a/#'(#i)(#I)~'/\~(#i)(#I)}}
+        : ${(A)a::=${a/#'(#i)~'/\~(#i)}}
+
+        # fixup the '!^'; "~(#i)*\^" -> "~(#i)(#s)"
+        # (for example, "!^aoe" -> "~(#i)*\^aoe" -> "~(#i)(#s)aoe")
+        #: ${(A)a::=${a/#(#b)'~'('(#i)'('(#I)')#)'*\^'/\~${match[1]}(#s)}}
+        : ${(A)a::=${a/#'~(#i)(#I)*\^'/'~(#i)(#I)(#s)'}}
+        : ${(A)a::=${a/#'~(#i)*\^'/'~(#i)(#s)'}}
+    fi
+    : ${(PA)place::=$a}
+    (( ${#a} > 1 )) || (( ${#a} == 1 )) && [[ -n "$a" ]]
+}
+
+function _filter-select-init-keybind() {
+    integer fd ret
+
+    # be quiet and check filterselect keybind defined
+    exec {fd}>&2 2>/dev/null
+    bindkey -l filterselect > /dev/null
+    ret=$?
+    exec 2>&${fd} {fd}>&-
+
+    if (( ret != 0 )); then
+        bindkey -N filterselect
+
+        bindkey -M filterselect '^J' accept-line
+        bindkey -M filterselect '^M' accept-line
+        bindkey -M filterselect '\e^J' accept-search
+        bindkey -M filterselect '\e^M' accept-search
+
+        bindkey -M filterselect '\e^G' send-break
+        bindkey -M filterselect '^G' send-break
+
+        bindkey -M filterselect '^@' set-mark-command
+
+        bindkey -M filterselect '^H' backward-delete-char
+        bindkey -M filterselect '^?' backward-delete-char
+
+        bindkey -M filterselect '^F' forward-char
+        bindkey -M filterselect '\e[C' forward-char
+        bindkey -M filterselect '\eOC' forward-char
+
+        bindkey -M filterselect '^B' backward-char
+        bindkey -M filterselect '\e[D' backward-char
+        bindkey -M filterselect '\eOD' backward-char
+
+        bindkey -M filterselect '^A' beginning-of-line
+        bindkey -M filterselect '^E' end-of-line
+
+        bindkey -M filterselect '^W' backward-kill-word
+        bindkey -M filterselect '^K' kill-line
+        bindkey -M filterselect '^U' kill-whole-line
+
+        # move cursor down/up
+        bindkey -M filterselect '^N' down-line-or-history
+        bindkey -M filterselect '\e[B' down-line-or-history
+        bindkey -M filterselect '\eOB' down-line-or-history
+        bindkey -M filterselect '^P' up-line-or-history
+        bindkey -M filterselect '\e[A' up-line-or-history
+        bindkey -M filterselect '\eOA' up-line-or-history
+
+        # page down/up
+        bindkey -M filterselect '^V' forward-word
+        bindkey -M filterselect '\e[6~' forward-word
+
+        bindkey -M filterselect '\eV' backward-word
+        bindkey -M filterselect '\ev' backward-word
+        bindkey -M filterselect '\e[5~' backward-word
+
+        # home/end
+        bindkey -M filterselect '\e<' beginning-of-history
+        bindkey -M filterselect '\e[1~' beginning-of-history
+
+        bindkey -M filterselect '\e>' end-of-history
+        bindkey -M filterselect '\e[4~' end-of-history
+    fi
+}
+
+function _filter-select-read-keys() {
+    local key key2 key3 nkey
+    integer ret
+
+    read -k key
+    ret=$?
+    reply="${key}"
+    if [[ '#key' -eq '#\\e' ]]; then
+        # M-...
+        read -t $(( KEYTIMEOUT / 1000 )) -k key2
+        if [[ "${key2}" == 'O' ]]; then
+            # ^[O (SS3) affects next character only.
+            # Example: cursor keys on some terminals.
+            read -k key3
+            ret=$?
+            reply="${key}${key2}${key3}"
+        else
+            if [[ "${key2}" == '[' ]]; then
+                # ^[[ (CSI) starts a sequence of [0-9;?] terminated by [@-~].
+                # Examples: Home, End, PgUp, PgDn ...
+                reply="${key}${key2}"
+                while true; do
+                    read -k nkey
+                    reply+=$nkey
+                    ret=$?
+                    (( $ret == 0 )) && [[ "${nkey}" =~ '^[0-9;?]$' ]] || break
+                done
+            else
+                reply="${key}${key2}"
+            fi
+        fi
+    else
+        reply="${key}"
+    fi
+    return $ret
+}
+
+filter-select "$@"
diff --git a/.zsh/zaw/sources/aliases.zsh b/.zsh/zaw/sources/aliases.zsh
new file mode 100644 (file)
index 0000000..247ca34
--- /dev/null
@@ -0,0 +1,11 @@
+function zaw-src-aliases() {
+    candidates=($(alias | cut -d '=' -f 1))
+    actions=(zaw-callback-execute zaw-callback-append-to-buffer zaw-callback-replace-buffer view-alias-pager)
+    act_descriptions=("execute" "append to buffer" "replace buffer" "view alias")
+}
+
+view-alias-pager() {
+    alias $1 | ${PAGER:-less}
+}
+
+zaw-register-src -n aliases zaw-src-aliases
diff --git a/.zsh/zaw/sources/applications.zsh b/.zsh/zaw/sources/applications.zsh
new file mode 100644 (file)
index 0000000..e016d48
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# zaw-src-applications
+#
+# zaw source for desktop applications
+#
+
+function zaw-src-applications() {
+    emulate -L zsh
+    setopt local_options extended_glob null_glob
+
+    case "$OSTYPE" in
+        [Dd]arwin*)
+            candidates=( )
+            # Use the spotlight index to get application paths
+            (( ${+commands[mdfind]} )) && \
+                candidates+=(${(f)"$(mdfind -onlyin / 'kMDItemKind == "Application"' 2>/dev/null)"})
+
+            # Use locate if available and no output from spotlight or if forced use by ZAW_SRC_APPLICATIONS_USE_LOCATE
+            if (( ${+commands[locate]} )) && [ -n "$ZAW_SRC_APPLICATIONS_USE_LOCATE" -o ${#candidates} -eq 0 ]; then
+                # Apps inside apps are not normally useful
+                if [ -n "$ZAW_SRC_APPLICATIONS_INTERNAL_APPS_OK" ]; then
+                    candidates+=(${(f)"$(locate -i '*.app' 2>/dev/null)"})
+                elif [ ${+commands[grep]} -eq 1 ]; then
+                    candidates+=(${(f)"$((locate -i '*.app' | grep -iv '\.app/') 2>/dev/null)"})
+                fi
+            fi
+
+            # Glob common locations anyway since both of previous indexes may
+            # be stale or non-existent
+            candidates+=({,~}/Applications{,/Utilities}/*.app(N^M) /System/Library/CoreServices/*.app(N^M))
+
+            candidates=(${(iou)candidates[@]})
+            actions=("zaw-callback-launch-macapp" "zaw-callback-append-to-buffer")
+            act_descriptions=("execute application" "append to edit buffer")
+            ;;
+        [Ll]inux*|*[Bb][Ss][Dd]*|[Ss]olaris*|[Ss]un[Oo][Ss]*)
+            local d
+            local -a match mbegin mend
+            for d in /usr/share/applications/*.desktop; do
+                local name="" comment="" exec_="" terminal=0 no_display=0
+                while read line; do
+                    case "${line}" in
+                        Name=(#b)(*))
+                            name="${match[1]}"
+                            ;;
+                        Comment=(#b)(*))
+                            comment="${match[1]}"
+                            ;;
+                        Exec=(#b)(*))
+                            exec_="${match[1]}"
+                            ;;
+                        Terminal=true)
+                            terminal=1
+                            ;;
+
+                        NoDisplay=true)
+                            no_display=1
+                            ;;
+                    esac
+                done < "${d}"
+
+                if (( no_display )); then
+                    continue
+                fi
+
+                # TODO: % expansion in $exec_
+                # remove args that match %* from $exec_
+                exec_="${(@m)${(z)exec_}:#%*}"
+
+                if ! (( terminal )); then
+                    # disown
+                    exec_="${exec_} &!"
+                fi
+
+                candidates+=( "${exec_}" )
+                cand_descriptions+=( "${name} - ${comment}" )
+            done
+            actions=("zaw-callback-execute" "zaw-callback-append-to-buffer")
+            act_descriptions=("execute application" "append to edit buffer")
+            ;;
+        *)
+            # Unsupported OS
+            candidates=( )
+            actions=("zaw-callback-execute" "zaw-callback-append-to-buffer")
+            act_descriptions=("execute application" "append to edit buffer")
+            ;;
+    esac
+
+}
+
+function zaw-callback-launch-macapp() {
+    BUFFER="open -a \"${(j:; :)@}\""
+    zle accept-line
+}
+
+zaw-register-src -n applications zaw-src-applications
diff --git a/.zsh/zaw/sources/bookmark.zsh b/.zsh/zaw/sources/bookmark.zsh
new file mode 100644 (file)
index 0000000..170c9ab
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# zaw-src-bookmark
+#
+# bookmark your favorite command lines, access it using zaw interface.
+# you can bookmark command line using zaw-history's `bookmark this command line` action,
+# or bind some key to ``zaw-bookmark-add-buffer`` and use it.
+#
+
+zmodload zsh/system
+autoload -U fill-vars-or-accept
+
+typeset -g BOOKMARKFILE="${BOOKMARKFILE:-"${HOME}/.zaw-bookmarks"}"
+
+function zaw-src-bookmark() {
+    if [[ -f "${BOOKMARKFILE}" ]]; then
+        candidates=("${(Qf)$(zsystem flock -r "${BOOKMARKFILE}" && < "${BOOKMARKFILE}")}")
+    fi
+    actions=("zaw-bookmark-execute" "zaw-callback-replace-buffer" "zaw-callback-append-to-buffer" "zaw-bookmark-remove")
+    act_descriptions=("execute" "replace edit buffer" "append to edit buffer" "removed bookmark")
+    options=("-m")
+}
+
+zaw-register-src -n bookmark zaw-src-bookmark
+
+
+#
+# helper functions for bookmark
+#
+
+function zaw-bookmark-execute() {
+    zaw-callback-replace-buffer "$@"
+    fill-vars-or-accept
+}
+
+function zaw-bookmark-add() {
+    local -a bookmarks
+
+    : >>| "${BOOKMARKFILE}"
+    (
+        if zsystem flock -t 5 "${BOOKMARKFILE}"; then
+            bookmarks=("${(f)$(< "${BOOKMARKFILE}")}" "${(q@)@}")
+
+            # remove empty lines
+            bookmarks=("${(@)bookmarks:#}")
+
+            # remove duplicated lines, sort and write to ${BOOKMARKFILE}
+            print -rl -- "${(@un)bookmarks}" >| "${BOOKMARKFILE}"
+        else
+            print "can't acquire lock for '${BOOKMARKFILE}'" >&2
+            exit 1
+        fi
+    )
+
+    if [[ $? == 0 ]]; then
+        zle -M "bookmark '${(j:', ':)@}'"
+    fi
+}
+
+function zaw-bookmark-add-buffer() {
+    zaw-bookmark-add "${BUFFER}"
+}
+
+zle -N zaw-bookmark-add-buffer
+
+function zaw-bookmark-remove() {
+    local s
+    local -a bookmarks
+
+    : >>| "${BOOKMARKFILE}"
+    (
+        if zsystem flock -t 5 "${BOOKMARKFILE}"; then
+            bookmarks=("${(f)$(< "${BOOKMARKFILE}")}")
+            for s in "${(q@)@}"; do
+                bookmarks=("${(@)bookmarks:#${s}}")
+            done
+
+            # remove duplicated lines, sort and write to ${BOOKMARKFILE}
+            print -rl -- "${(@un)bookmarks}" >| "${BOOKMARKFILE}"
+        else
+            print "can't acquire lock for '${BOOKMARKFILE}'" >&2
+            exit 1
+        fi
+    )
+
+    if [[ $? == 0 ]]; then
+        zle -M "bookmark '${(j:', ':)@}' removed"
+    fi
+}
+
+function zaw-bookmark-remove-buffer() {
+    zaw-bookmark-remove "${BUFFER}"
+}
+
+zle -N zaw-bookmark-remove-buffer
diff --git a/.zsh/zaw/sources/cdr.zsh b/.zsh/zaw/sources/cdr.zsh
new file mode 100644 (file)
index 0000000..315b440
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# zaw-src-cdr
+#
+# zaw source for recent directories
+#
+
+(( $+functions[cdr] )) || return
+
+function zaw-src-cdr () {
+    setopt local_options extended_glob
+    : ${(A)candidates::=${${(f)"$(cdr -l)"}##<-> ##}}
+    actions=(zaw-src-cdr-cd zaw-src-cdr-insert zaw-src-cdr-prune)
+    act_descriptions=("cd" "insert" "prune")
+    options=("-m" "-s" "${BUFFER##cd(r|) }")
+}
+
+function zaw-src-cdr-cd () {
+    BUFFER="cd $1"
+    zle accept-line
+}
+
+function zaw-src-cdr-insert () {
+    [[ -z "$LBUFFER" ]] || LBUFFER+=" "
+    [[ "$LBUFFER[-1]" == " " ]] || LBUFFER+=" "
+    LBUFFER+="${(j. .)@}"
+}
+
+function zaw-src-cdr-prune () {
+    local -aU reply
+    autoload -Uz chpwd_recent_filehandler
+    chpwd_recent_filehandler
+    : ${(A)reply::=${reply:#(${(~j.|.)${~@}})}}
+    chpwd_recent_filehandler $reply
+}
+
+zaw-register-src -n cdr zaw-src-cdr
diff --git a/.zsh/zaw/sources/command-output.zsh b/.zsh/zaw/sources/command-output.zsh
new file mode 100644 (file)
index 0000000..11af0ee
--- /dev/null
@@ -0,0 +1,19 @@
+# zaw source for locate
+
+autoload -U read-from-minibuffer
+
+function zaw-src-command-output() {
+    local buf
+    read-from-minibuffer "command: "
+    buf=$(${(Q@)${(z)REPLY}})
+    if [[ $? != 0 ]]; then
+        return 1
+    fi
+    : ${(A)candidates::=${(f)buf}}
+    : ${(A)cand_descriptions::=${(f)buf}}
+    actions=( zaw-callback-append-to-buffer )
+    act_descriptions=( "append to buffer" )
+}
+
+zaw-register-src -n command-output zaw-src-command-output
+
diff --git a/.zsh/zaw/sources/commands.zsh b/.zsh/zaw/sources/commands.zsh
new file mode 100644 (file)
index 0000000..15f8697
--- /dev/null
@@ -0,0 +1,12 @@
+function zaw-src-commands() {
+    # fill the command hash
+    hash -r
+    hash -f
+    candidates=($(hash | cut -d '=' -f 1))
+    candidates+=($(alias | cut -d '=' -f 1))
+    candidates+=($(print -l ${(ok)functions}))
+    actions=(zaw-callback-execute zaw-callback-append-to-buffer zaw-callback-replace-buffer)
+    act_descriptions=("execute" "append to buffer" "replace buffer")
+}
+
+zaw-register-src -n commands zaw-src-commands
diff --git a/.zsh/zaw/sources/fasd.zsh b/.zsh/zaw/sources/fasd.zsh
new file mode 100644 (file)
index 0000000..cc5a8f7
--- /dev/null
@@ -0,0 +1,27 @@
+function zaw-src-fasd () {
+    candidates=($(fasd -alR))
+    actions=(zaw-callback-append-to-buffer)
+    act_descriptions=("append to edit buffer")
+    options+=(-n -m)
+}
+
+
+function zaw-src-fasd-files () {
+    candidates=($(fasd -flR))
+    actions=(zaw-callback-append-to-buffer)
+    act_descriptions=("append to edit buffer")
+    options+=(-n -m)
+}
+
+
+function zaw-src-fasd-directories () {
+    candidates=($(fasd -dlR))
+    actions=(zaw-callback-append-to-buffer)
+    act_descriptions=("append to edit buffer")
+    options+=(-n -m)
+}
+
+
+zaw-register-src -n fasd zaw-src-fasd
+zaw-register-src -n fasd-directories zaw-src-fasd-directories
+zaw-register-src -n fasd-files zaw-src-fasd-files
diff --git a/.zsh/zaw/sources/functions.zsh b/.zsh/zaw/sources/functions.zsh
new file mode 100644 (file)
index 0000000..8fb2c0a
--- /dev/null
@@ -0,0 +1,7 @@
+function zaw-src-functions() {
+    candidates=($(print -l ${(ok)functions}))
+    actions=(zaw-callback-execute zaw-callback-append-to-buffer zaw-callback-replace-buffer functions) 
+    act_descriptions=("call function" "append to buffer" "replace buffer" "view source")
+}
+
+zaw-register-src -n functions zaw-src-functions
diff --git a/.zsh/zaw/sources/git-branches.zsh b/.zsh/zaw/sources/git-branches.zsh
new file mode 100644 (file)
index 0000000..2f979b8
--- /dev/null
@@ -0,0 +1,172 @@
+# zaw source for git branch
+
+function zaw-src-git-branches() {
+    git rev-parse --git-dir >/dev/null 2>&1
+    if [[ $? == 0 ]]; then
+        local branches_list="$(git show-ref | awk ' $2 != "refs/stash" { print $2 }' )"
+        : ${(A)candidates::=${${(f)${branches_list}}#refs/}}
+        : ${(A)cand_descriptions::=${${(f)${branches_list}}#refs/(remotes|heads|tags)/}}
+    fi
+    actions=( \
+        zaw-src-git-branches-checkout \
+        zaw-src-git-branches-simple-checkout \
+        zaw-callback-append-to-buffer \
+        zaw-src-git-branches-merge \
+        zaw-src-git-branches-merge-rebase \
+        zaw-src-git-branches-merge-no-ff \
+        zaw-src-git-branches-merge-to \
+        zaw-src-git-branches-reset \
+        zaw-src-git-branches-rebase \
+        zaw-src-git-branches-rebase-interactive \
+        zaw-src-git-branches-create \
+        zaw-src-git-branches-diff \
+        zaw-src-git-branches-diff-stat \
+        zaw-src-git-branches-reset-hard \
+        zaw-src-git-branches-delete \
+        zaw-src-git-branches-delete-force)
+    act_descriptions=(
+        "check out locally" \
+        "check out" \
+        "append to edit buffer" \
+        "merge" \
+        "merge rebase" \
+        "merge no ff" \
+        "merge to" \
+        "reset" \
+        "rebase" \
+        "rebase interactive from..." \
+        "create new branch from..." \
+        "diff" \
+        "diff statistics" \
+        "reset hard" \
+        "delete" \
+        "delete force")
+    options=()
+}
+
+function zaw-src-git-branches-checkout () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    case "$b_type" in
+        "heads"|"tags")
+            BUFFER="git checkout $b_name"
+            zle accept-line
+            ;;
+        "remotes")
+            BUFFER="git checkout -t $b_name"
+            zle accept-line
+            ;;
+    esac
+}
+
+function zaw-src-git-branches-simple-checkout () {
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git checkout $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-create () {
+    local b_name=${1#(heads|remotes|tags)/}
+    LBUFFER="git checkout -b "
+    RBUFFER=" $b_name"
+}
+
+function zaw-src-git-branches-merge () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git merge $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-merge-rebase () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git merge --rebase $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-merge-no-ff () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git merge --no-ff $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-merge-to () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    local b_now=${$(git symbolic-ref HEAD)#refs/heads/}
+    if [[ "$b_type" == "heads" ]]; then
+        BUFFER="git checkout $b_name && git merge --no-ff $b_now"
+        zle accept-line
+    fi
+}
+
+function zaw-src-git-branches-reset () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git reset $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-diff() {
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git diff $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-diff-stat() {
+  local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git diff --stat $b_name"
+}
+
+function zaw-src-git-branches-reset-hard () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git reset --hard $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-rebase () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git rebase $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-rebase-interactive () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git rebase -i $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-delete () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    if [[ "$b_type" == "heads" ]] ; then
+        BUFFER="git branch -d $b_name"
+        zle accept-line
+    elif [[ "$b_type" == "remotes" ]] ; then
+        local b_loc=${b_name%%/*}
+        local b_base=${b_name#$b_loc/}
+        BUFFER="git push $b_loc :$b_base"
+        zle accept-line
+    fi
+}
+
+function zaw-src-git-branches-delete-force () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    if [[ "$b_type" == "heads" ]] ; then
+        BUFFER="git branch -D $b_name"
+        zle accept-line
+    elif [[ "$b_type" == "remotes" ]] ; then
+        local b_loc=${b_name%%/*}
+        local b_base=${b_name#$b_loc/}
+        BUFFER="git push $b_loc :$b_base"
+        zle accept-line
+    fi
+}
+
+zaw-register-src -n git-branches zaw-src-git-branches
diff --git a/.zsh/zaw/sources/git-files.zsh b/.zsh/zaw/sources/git-files.zsh
new file mode 100644 (file)
index 0000000..c05a712
--- /dev/null
@@ -0,0 +1,65 @@
+# zaw source for git files
+
+function zaw-src-git-files-raw() {
+    local ret=0
+    git rev-parse --git-dir >/dev/null 2>&1
+    ret=$?
+    if (( ret != 0 )); then
+        return ret
+    fi
+
+    "$1"
+    ret=$?
+    if (( ret != 0 )); then
+        return ret
+    fi
+
+    actions=(zaw-callback-edit-file zaw-src-git-status-add zaw-src-git-status-add-p zaw-src-git-status-reset zaw-src-git-status-checkout zaw-src-git-status-rm zaw-callback-append-to-buffer)
+    act_descriptions=("edit file" "add" "add -p" "reset" "checkout" "rm" "append to edit buffer")
+    options=(-m -n)
+    return 0
+}
+
+function zaw-src-git-files-classify-aux() {
+    local -a as ms ds os
+    : ${(A)as::=${(0)"$(git ls-files $(git rev-parse --show-cdup) -z)"}}
+    : ${(A)ms::=${(0)"$(git ls-files $(git rev-parse --show-cdup) -z -m)"}}
+    if (( ${#ms} == 0 )) || (( ${#ms} == 1 )) &&  [[ -z "$ms" ]]; then
+        candidates=($as)
+        return 0
+    fi
+
+    if is-at-least 5.0.0 || [[ -n "${ZSH_PATCHLEVEL-}" ]] && \
+       is-at-least 1.5637 "$ZSH_PATCHLEVEL"; then
+        os=(${as:|ms})
+    else
+        os=(${as:#(${(~j.|.)ms})}) # TODO: too slower for large work tree
+    fi
+    candidates=($ms $os)
+
+    : ${(A)ds::=${ms/%/                   MODIFIED}}
+    ds+=($os)
+    cand_descriptions=($ds)
+    return 0
+}
+
+function zaw-src-git-files-legacy-aux() {
+    : ${(A)candidates::=${(0)"$(git ls-files $(git rev-parse --show-cdup) -z)"}}
+    return 0
+}
+
+function zaw-src-git-files-add () {
+    BUFFER="git add $1"
+    zle accept-line
+}
+
+{
+    function zaw-src-git-files-register-src() {
+        eval "function $2 () { zaw-src-git-files-raw "$3" }"
+        zaw-register-src -n "$1" "$2"
+    }
+    zaw-src-git-files-register-src git-files zaw-src-git-files zaw-src-git-files-classify-aux
+    zaw-src-git-files-register-src git-files-legacy zaw-src-git-files-legacy{,-aux}
+} always {
+    unfunction zaw-src-git-files-register-src
+}
diff --git a/.zsh/zaw/sources/git-log.zsh b/.zsh/zaw/sources/git-log.zsh
new file mode 100644 (file)
index 0000000..a6d31ac
--- /dev/null
@@ -0,0 +1,64 @@
+
+function zaw-src-git-log() {
+    git rev-parse --git-dir >/dev/null 2>&1
+    if [[ $? == 0 ]]; then
+        local desc="$(git log --all --graph --decorate --oneline --no-color)"
+        
+        : ${(A)cand_descriptions::=${(f)desc}}
+        : ${(A)candidates::=${(f)desc}}
+    fi
+    actions=(zaw-src-git-log-insert \
+             zaw-src-git-log-reset \
+             zaw-src-git-log-reset-hard \
+             zaw-src-git-log-cherry-pick \
+             zaw-src-git-log-create-branch \
+             zaw-src-git-log-revert)
+    act_descriptions=("insert" \
+                      "reset" \
+                      "reset --hard" \
+                      "cherry-pick" \
+                      "create new branch from this hash value" \
+                      "revert")
+    options=()
+}
+
+function _zaw-src-git-log-strip(){
+    echo $1 | sed -e 's/^[*|/\\ ]* \([a-f0-9]*\) .*/\1/'
+}
+
+function zaw-src-git-log-insert(){
+    local hash_val=$(_zaw-src-git-log-strip $1)
+    zaw-callback-append-to-buffer $hash_val
+}
+
+function zaw-src-git-log-reset(){
+    local hash_val=$(_zaw-src-git-log-strip $1)
+    BUFFER="git reset $hash_val"
+    zle accept-line
+}
+
+function zaw-src-git-log-reset-hard(){
+    local hash_val=$(_zaw-src-git-log-strip $1)
+    BUFFER="git reset --hard $hash_val"
+    zle accept-line
+}
+
+function zaw-src-git-log-cherry-pick(){
+    local hash_val=$(_zaw-src-git-log-strip $1)
+    BUFFER="git cherry-pick $hash_val"
+    zle accept-line
+}
+
+function zaw-src-git-log-create-branch(){
+    local hash_val=$(_zaw-src-git-log-strip $1)
+    LBUFFER="git checkout -b "
+    RBUFFER=" $hash_val"
+}
+
+function zaw-src-git-log-revert(){
+    local hash_val=$(_zaw-src-git-log-strip $1)
+    BUFFER="git revert $hash_val"
+    zle accept-line
+}
+
+zaw-register-src -n git-log zaw-src-git-log
diff --git a/.zsh/zaw/sources/git-recent-branches.zsh b/.zsh/zaw/sources/git-recent-branches.zsh
new file mode 100644 (file)
index 0000000..35434fb
--- /dev/null
@@ -0,0 +1,117 @@
+# zaw source for git branches sorted by commit date
+
+function zaw-src-git-recent-branches () {
+    git rev-parse --git-dir >/dev/null 2>&1
+    if [[ $? == 0 ]]; then
+        local branches="$(git for-each-ref --format='%(refname)' --sort=-committerdate refs/heads)"
+        : ${(A)candidates::=${${(f)${branches}}#refs/}}
+        : ${(A)cand_descriptions::=${${(f)${branches}}#refs/(remotes|heads|tags)/}}
+    fi
+
+    actions=( \
+        zaw-src-git-branches-checkout \
+        zaw-src-git-branches-simple-checkout \
+        zaw-callback-append-to-buffer \
+        zaw-src-git-branches-merge \
+        zaw-src-git-branches-merge-rebase \
+        zaw-src-git-branches-merge-no-ff \
+        zaw-src-git-branches-diff \
+        zaw-src-git-branches-diff-stat \
+        zaw-src-git-branches-reset \
+        zaw-src-git-branches-rebase \
+        zaw-src-git-branches-rebase-interactive \
+        zaw-src-git-branches-create \
+        zaw-src-git-branches-reset-hard \
+        zaw-src-git-branches-delete \
+        zaw-src-git-branches-delete-force)
+    act_descriptions=(
+        "check out locally" \
+        "check out" \
+        "append to edit buffer" \
+        "merge" \
+        "merge rebase" \
+        "merge no ff" \
+        "diff" \
+        "diff stat" \
+        "reset" \
+        "rebase" \
+        "rebase interactive from..." \
+        "create new branch from..." \
+        "reset hard" \
+        "delete" \
+        "delete force")
+    options=()
+}
+
+function zaw-src-git-recent-all-branches () {
+    git rev-parse --git-dir >/dev/null 2>&1
+    if [[ $? == 0 ]]; then
+        local branches="$(git for-each-ref --format='%(refname)' --sort=-committerdate refs/heads refs/remotes)"
+        : ${(A)candidates::=${${(f)${branches}}#refs/}}
+        : ${(A)cand_descriptions::=${${(f)${branches}}#refs/(remotes|heads|tags)/}}
+    fi
+
+    actions=( \
+        zaw-src-git-branches-checkout \
+        zaw-src-git-branches-simple-checkout \
+        zaw-callback-append-to-buffer \
+        zaw-src-git-branches-merge \
+        zaw-src-git-branches-merge-rebase \
+        zaw-src-git-branches-merge-no-ff \
+        zaw-src-git-branches-diff \
+        zaw-src-git-branches-diff-stat \
+        zaw-src-git-branches-reset \
+        zaw-src-git-branches-rebase \
+        zaw-src-git-branches-rebase-interactive \
+        zaw-src-git-branches-create \
+        zaw-src-git-branches-reset-hard \
+        zaw-src-git-branches-delete \
+        zaw-src-git-branches-delete-force)
+    act_descriptions=(
+        "check out locally" \
+        "check out" \
+        "append to edit buffer" \
+        "merge" \
+        "merge rebase" \
+        "merge no ff" \
+        "diff" \
+        "diff stat" \
+        "reset" \
+        "rebase" \
+        "rebase interactive from..." \
+        "create new branch from..." \
+        "reset hard" \
+        "delete" \
+        "delete force")
+    options=()
+}
+
+function zaw-src-git-recent-branches-checkout () {
+    local b_type=${1%%/*}
+    local b_name=${1#(heads|remotes|tags)/}
+    case "$b_type" in
+        "heads"|"tags")
+            BUFFER="git checkout $b_name"
+            zle accept-line
+            ;;
+        "remotes")
+            BUFFER="git checkout -t $b_name"
+            zle accept-line
+            ;;
+    esac
+}
+
+function zaw-src-git-branches-diff() {
+    local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git diff $b_name"
+    zle accept-line
+}
+
+function zaw-src-git-branches-diff-stat() {
+  local b_name=${1#(heads|remotes|tags)/}
+    BUFFER="git diff --stat $b_name"
+    zle accept-line
+}
+
+zaw-register-src -n git-recent-branches zaw-src-git-recent-branches
+zaw-register-src -n git-recent-all-branches zaw-src-git-recent-all-branches
diff --git a/.zsh/zaw/sources/git-reflog.zsh b/.zsh/zaw/sources/git-reflog.zsh
new file mode 100644 (file)
index 0000000..5ddad20
--- /dev/null
@@ -0,0 +1,40 @@
+function zaw-src-git-reflog () {
+    git rev-parse --git-dir >/dev/null 2>&1
+    if [[ $? == 0 ]]; then
+        git reflog | \
+            while read id desc; do
+                candidates+=("${id}")
+                cand_descriptions+=("${id} ${desc}")
+            done
+    fi
+    actions=(zaw-callback-append-to-buffer zaw-src-git-commit-checkout zaw-src-git-commit-reset zaw-src-git-commit-rebase zaw-src-git-commit-rebase-interactive zaw-src-git-commit-reset-hard)
+    act_descriptions=("append to edit buffer" "checkout" "reset" "rebase" "rebase interactive from..." "reset hard")
+    options=()
+}
+
+function zaw-src-git-commit-checkout () {
+    BUFFER="git checkout $1"
+    zle accept-line
+}
+
+function zaw-src-git-commit-reset () {
+    BUFFER="git reset $1"
+    zle accept-line
+}
+
+function zaw-src-git-commit-reset-hard () {
+    BUFFER="git reset --hard $1"
+    zle accept-line
+}
+
+function zaw-src-git-commit-rebase () {
+    BUFFER="git rebase $1"
+    zle accept-line
+}
+
+function zaw-src-git-commit-rebase-interactive () {
+    BUFFER="git rebase -i $1"
+    zle accept-line
+}
+
+zaw-register-src -n git-reflog zaw-src-git-reflog
diff --git a/.zsh/zaw/sources/git-status.zsh b/.zsh/zaw/sources/git-status.zsh
new file mode 100644 (file)
index 0000000..7239bda
--- /dev/null
@@ -0,0 +1,77 @@
+function zaw-src-git-status() {
+  git rev-parse --git-dir >/dev/null 2>&1
+    if [[ $? == 0 ]]; then
+      local file_list="$(git status --porcelain)"
+      : ${(A)candidates::=${(f)${file_list}}}
+
+      : ${(A)cand_descriptions::=${${(f)${file_list}}/ M /[modified]        }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/AM /[add|modified]    }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/MM /[staged|modified] }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/M  /[staged]          }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/A  /[staged(add)]     }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/ D /[deleted]         }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/UU /[conflict]        }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/AA /[conflict]        }}
+      : ${(A)cand_descriptions::=${${(M)cand_descriptions}/\?\? /[untracked]       }}
+
+    fi
+
+    actions=( \
+      zaw-src-git-status-add \
+      zaw-src-git-status-add-p \
+      zaw-src-git-status-reset \
+      zaw-src-git-status-checkout \
+      zaw-src-git-status-edit \
+      zaw-src-git-status-rm)
+    act_descriptions=( \
+      "add" \
+      "add -p" \
+      "reset" \
+      "checkout" \
+      "edit" \
+      "rm")
+    options=()
+}
+
+function zaw-src-git-status-add() {
+  local f_path=${1##?* }
+  local git_base="$(git rev-parse --show-cdup)"
+  BUFFER="git add '$git_base$f_path'"
+  zle accept-line
+}
+
+function zaw-src-git-status-add-p() {
+  local f_path=${1##?* }
+  local git_base="$(git rev-parse --show-cdup)"
+  BUFFER="git add -p '$git_base$f_path'"
+  zle accept-line
+}
+
+function zaw-src-git-status-reset() {
+  local f_path=${1##?* }
+  local git_base="$(git rev-parse --show-cdup)"
+  BUFFER="git reset '$git_base$f_path'"
+  zle accept-line
+}
+
+function zaw-src-git-status-checkout() {
+  local f_path=${1##?* }
+  local git_base="$(git rev-parse --show-cdup)"
+  BUFFER="git checkout '$git_base$f_path'"
+  zle accept-line
+}
+
+function zaw-src-git-status-edit() {
+  local f_path=${1##?* }
+  local git_base="$(git rev-parse --show-cdup)"
+  zaw-callback-edit-file "$git_base$f_path"
+}
+
+function zaw-src-git-status-rm() {
+  local f_path=${1##?* }
+  local git_base="$(git rev-parse --show-cdup)"
+  BUFFER="git rm '$git_base$f_path'"
+  zle accept-line
+}
+
+zaw-register-src -n git-status zaw-src-git-status
diff --git a/.zsh/zaw/sources/history.zsh b/.zsh/zaw/sources/history.zsh
new file mode 100644 (file)
index 0000000..1f16bd7
--- /dev/null
@@ -0,0 +1,23 @@
+zmodload zsh/parameter
+
+function zaw-src-history() {
+    if zstyle -t ':filter-select' hist-find-no-dups ; then
+        candidates=(${(@vu)history})
+        options=("-m" "-s" "${BUFFER}")
+    else
+        cands_assoc=("${(@kv)history}")
+        # have filter-select reverse the order (back to latest command first).
+        # somehow, `cands_assoc` gets reversed while `candidates` doesn't. 
+        options=("-r" "-m" "-s" "${BUFFER}")
+    fi
+    actions=("zaw-callback-execute" "zaw-callback-replace-buffer" "zaw-callback-append-to-buffer")
+    act_descriptions=("execute" "replace edit buffer" "append to edit buffer")
+
+    if (( $+functions[zaw-bookmark-add] )); then
+        # zaw-src-bookmark is available
+        actions+="zaw-bookmark-add"
+        act_descriptions+="bookmark this command line"
+    fi
+}
+
+zaw-register-src -n history zaw-src-history
diff --git a/.zsh/zaw/sources/locate.zsh b/.zsh/zaw/sources/locate.zsh
new file mode 100644 (file)
index 0000000..b0c5d37
--- /dev/null
@@ -0,0 +1,19 @@
+# zaw source for locate
+
+autoload -U read-from-minibuffer
+
+function zaw-src-locate() {
+    local buf
+    read-from-minibuffer "locate "
+    buf=$(locate ${(Q@)${(z)REPLY}})
+    if [[ $? != 0 ]]; then
+        return 1
+    fi
+    : ${(A)candidates::=${(f)buf}}
+    : ${(A)cand_descriptions::=${(f)buf}}
+    actions=( zaw-callback-append-to-buffer )
+    act_descriptions=( "append to buffer" )
+}
+
+zaw-register-src -n locate zaw-src-locate
+
diff --git a/.zsh/zaw/sources/open-file.zsh b/.zsh/zaw/sources/open-file.zsh
new file mode 100644 (file)
index 0000000..e1f49e9
--- /dev/null
@@ -0,0 +1,66 @@
+#
+# zaw-open-file
+#
+# zaw source for xdg-open to open file
+#
+
+function zaw-src-open-file() {
+    local root parent d f
+    setopt local_options null_glob
+
+    if (( $# == 0 )); then
+        root="${PWD}/"
+    else
+        root="$1"
+    fi
+
+    parent="${root:h}"
+    if [[ "${parent}" != */ ]]; then
+        parent="${parent}/"
+    fi
+    candidates+=("${parent}")
+    cand_descriptions+=("../")
+
+    # TODO: symlink to directory
+    for d in "${root%/}"/*(/); do
+        candidates+=("${d}/")
+        cand_descriptions+=("${d:t}/")
+    done
+
+    for f in "${root%/}"/*(^/); do
+        candidates+=("${f}")
+        cand_descriptions+=("${f:t}")
+    done
+
+    actions=( "zaw-callback-open-file" "zaw-callback-append-to-buffer" )
+    act_descriptions=( "open file or directory" "append to edit buffer" )
+    # TODO: open multiple files
+    #options=( "-m" )
+    options=( "-t" "${root}" )
+}
+
+zaw-register-src -n open-file zaw-src-open-file
+
+function zaw-callback-open-file() {
+    local open
+    case "${(L)OSTYPE}" in
+        linux*|*bsd*)
+            open="xdg-open"
+            ;;
+        darwin*)
+            open="open"
+            ;;
+        *)
+            # TODO: what is the best fallback?
+            open="xdg-open"
+            ;;
+    esac
+
+    # TODO: symlink to directory
+    if [[ -d "$1" ]]; then
+        zaw zaw-src-open-file "$1"
+    else
+        BUFFER="${open} ${(q)1}"
+        zle accept-line
+    fi
+}
diff --git a/.zsh/zaw/sources/perldoc.zsh b/.zsh/zaw/sources/perldoc.zsh
new file mode 100644 (file)
index 0000000..e91f0c9
--- /dev/null
@@ -0,0 +1,35 @@
+function zaw-src-perldoc() {
+    local code_wanted
+    local -a words
+
+    # XXX: override _wanted to capture module list _perl_modules generates
+    code_wanted="${functions[_wanted]}"
+    function _wanted() {
+        candidates=("${(P@)${@[7]}}")
+    }
+
+    # required by _perl_modules
+    words=(perldoc)
+
+    _perl_modules
+
+    # restore original function
+    eval "function _wanted() { $code_wanted }"
+
+    actions=("zaw-callback-perldoc-view" "zaw-callback-perldoc-vim")
+    act_descriptions=("view perldoc" "open with vim")
+}
+
+zaw-register-src -n perldoc zaw-src-perldoc
+
+function zaw-callback-perldoc-view() {
+    local orig_buffer="${BUFFER}"
+    BUFFER=" perldoc '$1'"
+    zle accept-line
+}
+
+function zaw-callback-perldoc-vim() {
+    local orig_buffer="${BUFFER}"
+    BUFFER=" vim -R $(perldoc -lm "$1")"
+    zle accept-line
+}
diff --git a/.zsh/zaw/sources/process.zsh b/.zsh/zaw/sources/process.zsh
new file mode 100644 (file)
index 0000000..96db973
--- /dev/null
@@ -0,0 +1,34 @@
+# zaw source for processes
+
+function zaw-src-process () {
+    local ps_list title ps pid_list
+    if [ $(uname) = "Darwin" ] ; then       # for Macintosh
+        ps_list="$(ps aux | awk '$11 !~ /^\[/ {print $0}')"              # filter out kernel processes
+    else
+        ps_list="$(ps -aux --sort args | awk '$11 !~ /^\[/ {print $0}')" # filter out kernel processes
+    fi
+    title="${${(f)ps_list}[1]}"
+    ps="$(echo $ps_list | sed '1d')"
+    pid_list="$(echo $ps | awk '{print $2}')"
+    : ${(A)candidates::=${(f)pid_list}}
+    : ${(A)cand_descriptions::=${(f)ps}}
+    actions=(zaw-callback-append-to-buffer zaw-src-process-kill)
+    act_descriptions=("insert" "kill")
+    options=(-t "$title")
+}
+
+function zaw-src-process-kill () {
+    local user="$(ps -ho user $1)"
+    if [[ -z $user ]]; then
+        echo "process with PID=$1 is not found"
+        return 1
+    fi
+    if [[ $user = $USER ]]; then
+        BUFFER="kill $1"
+    else
+        BUFFER="sudo kill $1"
+    fi
+    zle accept-line
+}
+
+zaw-register-src -n process zaw-src-process
diff --git a/.zsh/zaw/sources/programs.zsh b/.zsh/zaw/sources/programs.zsh
new file mode 100644 (file)
index 0000000..9a8f475
--- /dev/null
@@ -0,0 +1,10 @@
+function zaw-src-programs() {
+    # fill the command hash
+    hash -r
+    hash -f
+    candidates=($(hash | cut -d '=' -f 1))
+    actions=(zaw-callback-execute zaw-callback-append-to-buffer zaw-callback-replace-buffer)
+    act_descriptions=("execute" "append to buffer" "replace buffer")
+}
+
+zaw-register-src -n programs zaw-src-programs
diff --git a/.zsh/zaw/sources/screens.zsh b/.zsh/zaw/sources/screens.zsh
new file mode 100644 (file)
index 0000000..c5a8cab
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# zaw-src-screens
+#
+# select screen session and attache it
+#
+
+function zaw-src-screens() {
+    local session state
+
+    screen -ls | awk 'NR==1,/^There (is a|are) screens? on:/ { next } /^[0-9]+ Sockets? in/ { exit } 1' | \
+        while read session state; do
+            candidates+=("${session}")
+            cand_descriptions+=("${(r:30:::::)session} ${state}")
+        done
+        actions=('zaw-callback-screens-attach')
+        act_descriptions=('attach session')
+}
+
+zaw-register-src -n screens zaw-src-screens
+
+function zaw-callback-screens-attach() {
+    BUFFER="screen -rx ${(q)1}"
+    zle accept-line
+}
diff --git a/.zsh/zaw/sources/searcher.zsh b/.zsh/zaw/sources/searcher.zsh
new file mode 100644 (file)
index 0000000..2f90b02
--- /dev/null
@@ -0,0 +1,45 @@
+# zaw source for ack/ag searcher
+
+autoload -U read-from-minibuffer
+
+typeset -g ZAW_SEARCHER_CMD
+
+if (( $+commands[ag] )); then
+    ZAW_SEARCHER_CMD="ag"
+elif (( $+commands[ack-grep] )); then
+    ZAW_SEARCHER_CMD="ack-grep"
+elif (( $+commands[ack] )); then
+    ZAW_SEARCHER_CMD="ack"
+else
+    # ack/ag are not found, and disable this source
+    return
+fi
+
+function zaw-src-searcher() {
+    local buf
+    read-from-minibuffer "${ZAW_SEARCHER_CMD} "
+    buf=$($ZAW_SEARCHER_CMD ${(Q@)${(z)REPLY}})
+    if [[ $? != 0 ]]; then
+        return 1
+    fi
+    : ${(A)candidates::=${(f)buf}}
+    : ${(A)cand_descriptions::=${(f)buf}}
+    actions=(\
+        zaw-src-searcher-edit \
+    )
+    act_descriptions=(\
+        "Edit" \
+    )
+}
+
+function zaw-src-searcher-edit () {
+    local filename=${1%%:*}
+    local line=${${1#*:}%%:*}
+    if [[ -z $ZAW_EDITOR_JUMP_PARAM ]]; then
+        ZAW_EDITOR_JUMP_PARAM="+%LINE% %FILE%"
+    fi
+    BUFFER="${EDITOR} ${${ZAW_EDITOR_JUMP_PARAM/\%LINE\%/$line}/\%FILE\%/$filename}"
+    zle accept-line
+}
+
+zaw-register-src -n searcher zaw-src-searcher
diff --git a/.zsh/zaw/sources/ssh-hosts.zsh b/.zsh/zaw/sources/ssh-hosts.zsh
new file mode 100644 (file)
index 0000000..0980255
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# zaw-src-ssh-hosts
+#
+# Note: .ssh/config must have "HashKnownHosts no" (default) to make known hosts
+# values work.
+
+function zaw-src-ssh-hosts(){
+  local -a _global_ssh_known_hosts _global_ssh_known_hosts2 _ssh_known_hosts _ssh_known_hosts2 _etc_hosts _ssh_config_hosts
+  [ -r /etc/ssh/ssh_known_hosts ] && _global_ssh_known_hosts=(${${${(f)"$(< /etc/ssh/ssh_known_hosts)"}%%\ *}%%,*}) 2>/dev/null || _global_ssh_known_hosts=()
+  [ -r /etc/ssh/ssh_known_hosts2 ] && _global_ssh_known_hosts2=(${${${(f)"$(< /etc/ssh/ssh_known_hosts2)"}%%\ *}%%,*}) 2>/dev/null || _global_ssh_known_hosts2=()
+  [ -r "$HOME/.ssh/known_hosts" ] && _ssh_known_hosts=(${${${(f)"$(< ~/.ssh/known_hosts)"}%%\ *}%%,*}) 2>/dev/null || _ssh_known_hosts=()
+  [ -r "$HOME/.ssh/known_hosts2" ] && _ssh_known_hosts=(${${${(f)"$(< ~/.ssh/known_hosts2)"}%%\ *}%%,*}) 2>/dev/null || _ssh_known_hosts2=()
+  [ -r /etc/hosts ] && : ${(A)_etc_hosts:=${(s: :)${(ps:\t:)${${(f)~~"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} || _etc_hosts=()
+  [ -r "$HOME/.ssh/config" ] && _ssh_config_hosts=(${${${(@M)${(f)"$(< ~/.ssh/config)"}:#Host *}#Host }:#*[*?]*}) || _ssh_config_hosts=()
+  candidates=(
+    $_global_ssh_known_hosts[@]
+    $_global_ssh_known_hosts2[@]
+    $_ssh_known_hosts[@]
+    $_ssh_known_hosts2[@]
+    $_etc_hosts[@]
+    $_ssh_config_hosts[@]
+    "$HOST"
+    ::1
+    localhost
+    127.0.0.1
+  )
+  candidates=(${(iou)candidates[@]})
+
+  actions=("zaw-callback-ssh-connect" "zaw-callback-append-to-buffer" )
+
+  act_descriptions=("ssh to the host" "append to edit buffer")
+}
+
+zaw-register-src -n ssh-hosts zaw-src-ssh-hosts
+
+function zaw-callback-ssh-connect(){
+  local orig_buffer="${BUFFER}"
+  BUFFER="ssh $1"
+  zle accept-line
+}
diff --git a/.zsh/zaw/sources/tmux.zsh b/.zsh/zaw/sources/tmux.zsh
new file mode 100644 (file)
index 0000000..01ea1f4
--- /dev/null
@@ -0,0 +1,36 @@
+# -*- mode:sh -*-
+#
+# zaw-src-tmux
+#
+# select tmux session and attach it
+#
+
+function zaw-src-tmux() {
+    local session state
+
+    tmux list-sessions | \
+        while read session state; do
+            candidates+=("${session}")
+            cand_descriptions+=("${(r:30:::::)session} ${state}")
+        done
+        actions=('zaw-callback-tmux-attach')
+        act_descriptions=('attach session')
+        actions+=('zaw-callback-tmux-kill')
+        act_descriptions+=('kill session')
+}
+
+zaw-register-src -n tmux zaw-src-tmux
+
+function zaw-callback-tmux-attach() {
+    if [ -z $TMUX ]; then
+        BUFFER="tmux attach -t ${(q)1}"
+    else
+        BUFFER="tmux switch-client -t ${(q)1}"
+    fi
+    zle accept-line
+}
+
+function zaw-callback-tmux-kill() {
+    BUFFER="tmux kill-session -t ${(q)1}"
+    zle accept-line
+}
diff --git a/.zsh/zaw/sources/widgets.zsh b/.zsh/zaw/sources/widgets.zsh
new file mode 100644 (file)
index 0000000..20f62dd
--- /dev/null
@@ -0,0 +1,11 @@
+function zaw-src-widgets() {
+    candidates=($(zle -l | cut -d ' ' -f 1))
+    actions=(zle-call)
+    act_descriptions=("call function with zle")
+}
+
+zle-call(){
+    zle $1
+}
+
+zaw-register-src -n widgets zaw-src-widgets
diff --git a/.zsh/zaw/zaw-launcher.zsh b/.zsh/zaw/zaw-launcher.zsh
new file mode 100755 (executable)
index 0000000..ca7e1a2
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/zsh
+#
+# zaw-launcher.zsh
+#
+# launcher script to start zaw as command
+
+# source zaw.zsh
+local this_file="$0"
+local cur_dir="${this_file:A:h}"
+source "${cur_dir}/zaw.zsh"
+
+
+# parse arguments
+do_eval=0
+
+while getopts 'eh' opt; do
+    case "${opt}" in
+        e)
+            do_eval=1
+            ;;
+
+        h)
+            print \
+"Usage: $0 [options] [source name]
+
+Options:
+  -h     show this help
+  -e     eval result string
+"
+            exit
+            ;;
+    esac
+done
+
+if (( OPTIND > 1 )); then
+    shift $(( OPTIND - 1 ))
+fi
+
+zaw_args=()
+if [[ $# > 0 && "${zaw_sources[$1]}" != "" ]]; then
+    zaw_args+="${zaw_sources[$1]}"
+fi
+
+
+# use zle-line-init to start zaw right after vared
+function zle-line-init() {
+    zle zaw "${(@)zaw_args}"
+
+    # return from vared
+    zle accept-line
+}
+zle -N zle-line-init
+
+vared -c cmd
+
+if (( do_eval )); then
+    eval "${cmd}"
+else
+    print "${cmd}"
+fi
diff --git a/.zsh/zaw/zaw.plugin.zsh b/.zsh/zaw/zaw.plugin.zsh
new file mode 120000 (symlink)
index 0000000..6c3ba25
--- /dev/null
@@ -0,0 +1 @@
+zaw.zsh
\ No newline at end of file
diff --git a/.zsh/zaw/zaw.zsh b/.zsh/zaw/zaw.zsh
new file mode 100644 (file)
index 0000000..2f6c7e0
--- /dev/null
@@ -0,0 +1,223 @@
+#
+# zaw - zsh anything.el-like widget
+#
+# usage:
+#
+#   add following line to your .zshrc::
+#
+#     source /path/to/zaw.zsh
+#
+#   and type "^X;"
+
+# to create namespace, use anonymous function
+function() {
+
+zmodload zsh/parameter
+autoload -U is-at-least
+
+local this_file="${funcsourcetrace[1]%:*}"
+if is-at-least 4.3.10; then
+    # "A" flag (turn a file name into an absolute path with symlink
+    # resolution) is only available on 4.3.10 and latter
+    local cur_dir="${this_file:A:h}"
+else
+    local cur_dir="${this_file:h}"
+fi
+fpath+=("${cur_dir}/functions")
+
+autoload -U filter-select
+
+typeset -g -A zaw_sources
+zaw_sources=()
+
+function zaw-register-src() {
+    # register zaw source
+    #
+    # zaw-register-src [-n NAME] SOURCE
+    #
+    # SOURCE is function name that define (overrite) these variables
+    #
+    # $candidates        -> array of candidates
+    # $cands_assoc       -> assoc array of candidates
+    # $cand_descriptions -> (optional) array of candidates descriptions
+    # $cand_descriptions_assoc -> (optional) assoc array of candidates descriptions
+    # $actions           -> list of callback function names that receive selected item
+    # $act_descriptions  -> (optional) list of callback function descriptions
+    # $options           -> (optional) array of options passed to filter-select
+    #
+    # whether one of candidates or cands-assoc is required
+    local name func widget_name opts OPTARG OPTIND
+
+    while getopts 'n:' opts; do
+        name="${OPTARG}"
+    done
+    if (( OPTIND > 1 )); then
+        shift $(( OPTIND - 1 ))
+    fi
+
+    func="$1"
+
+    if [[ -z "${name}" ]]; then
+        name="${func}"
+    fi
+
+    # TODO: check name duplication
+    zaw_sources+=("${name}" "${func}")
+
+    # define shortcut function
+    widget_name="zaw-${(L)name// /-}"
+    eval "function ${widget_name} { zle zaw ${func} \$@ }"
+    eval "zle -N ${widget_name}"
+}
+
+
+function zaw() {
+    local action ret func
+    local -a reply candidates actions act_descriptions options selected cand_descriptions
+    local -A cands_assoc
+
+    if [[ $# == 0 ]]; then
+        if zle zaw-select-src; then
+            func="${reply[2]}"
+            reply=()
+        else
+            return 0
+        fi
+    else
+        func="$1"
+        shift
+    fi
+
+    zle -R "now loading ..."
+
+    # call source function to generate candidates
+    "${func}" "$@"
+
+    ret="$?"
+    if [[ "${ret}" != 0 ]]; then
+        return 1
+    fi
+
+    reply=()
+
+    if (( ${#cand_descriptions} )); then
+        options=("-d" "cand_descriptions" "${(@)options}")
+    fi
+    # TODO: cand_descriptions_assoc
+
+    # call filter-select to allow user select item
+    if (( ${#cands_assoc} )); then
+        filter-select -e select-action -A cands_assoc "${(@)options}"
+    else
+        filter-select -e select-action "${(@)options}" -- "${(@)candidates}"
+    fi
+
+    if [[ $? == 0 ]]; then
+        if (( ${#reply_marked} > 0 )); then
+            selected=("${(@)reply_marked}")
+        else
+            selected=("${reply[2]}")
+        fi
+
+        case "${reply[1]}" in
+            accept-line)
+                action="${actions[1]}"
+                ;;
+            accept-search)
+                action="${actions[2]}"
+                ;;
+            select-action)
+                reply=()
+                filter-select -t "select action for '${(j:', ':)selected}'" -d act_descriptions -- "${(@)actions}"
+                ret=$?
+
+                if [[ $ret == 0 ]]; then
+                    action="${reply[2]}"
+                else
+                    return 1
+                fi
+                ;;
+        esac
+
+        if [[ -n "${action}" ]]; then
+            "${action}" "${(@)selected}"
+        fi
+    fi
+}
+
+zle -N zaw
+
+
+function zaw-select-src() {
+    local name
+    local -a cands descs
+    cands=()
+    descs=()
+    for name in "${(@ko)zaw_sources}"; do
+        cands+="${zaw_sources[${name}]}"
+        descs+="${name}"
+    done
+
+    filter-select -e select-action -d descs -- "${(@)cands}"
+}
+
+zle -N zaw-select-src
+
+
+function zaw-print-src() {
+    local name func widget_name
+    printf '%-16s %s\n' "source name" "shortcut widget name"
+    print -- '----------------------------------------'
+    for name in "${(@ko)zaw_sources}"; do
+        widget_name="zaw-${(L)name// /-}"
+        printf '%-16s %s\n' "${name}" "${widget_name}"
+    done
+}
+
+
+# common callbacks
+function zaw-callback-execute() {
+    BUFFER="${(j:; :)@}"
+    zle accept-line
+}
+
+function zaw-callback-replace-buffer() {
+    LBUFFER="${(j:; :)@}"
+    RBUFFER=""
+}
+
+function zaw-callback-append-to-buffer() {
+    LBUFFER="${BUFFER}${(j:; :)@}"
+}
+
+function zaw-callback-edit-file() {
+    local -a args
+    args=("${(@q)@}")
+
+    if [ ! ${ZAW_EDITOR} ]; then
+      ZAW_EDITOR=${EDITOR}
+    fi
+
+    BUFFER="${ZAW_EDITOR} ${args}"
+    zle accept-line
+}
+
+
+# load zaw sources
+setopt local_options extended_glob
+local src_dir="${cur_dir}/sources" f
+if [[ -d "${src_dir}" ]]; then
+    for f in "${src_dir}"/^*.zwc; do
+        source "${f}"
+    done
+fi
+
+# dummy function
+# only used for exit-zle-widget-name
+function select-action() {}; zle -N select-action
+filter-select -i
+bindkey -M filterselect '^i' select-action
+
+bindkey '^X;' zaw
+
+}
index 6c2af42..0f81d5f 100644 (file)
@@ -182,7 +182,8 @@ lmanpath=(
 ## what you load.
 # zstyle ':ganneff:config' plugins git-extras.plugin.zsh \
 #    history-substring-search.zsh \
-#    per-directory-history.plugin.zsh
+#    per-directory-history.plugin.zsh \
+#    zaw.zsh
 
 ## oh-my-zsh plugins can also be loaded, in case you like one of it.
 ## Simply list their names here, and put their directories into