about summary refs log tree commit diff
path: root/.config/zsh/plugins/manydots-magic
diff options
context:
space:
mode:
Diffstat (limited to '.config/zsh/plugins/manydots-magic')
-rw-r--r--.config/zsh/plugins/manydots-magic187
1 files changed, 187 insertions, 0 deletions
diff --git a/.config/zsh/plugins/manydots-magic b/.config/zsh/plugins/manydots-magic
new file mode 100644
index 0000000..1d02c4e
--- /dev/null
+++ b/.config/zsh/plugins/manydots-magic
@@ -0,0 +1,187 @@
+# -*- mode: sh -*-
+#
+# manydots-magic - zle tweak for emulating "..."=="../.." etc.
+#
+# This tweek helps input ancestor directories beyond the parent (`..')
+# in a handy way.  You can just type triple dots to input `../..',
+# quadruple dots to `../../..', etc..
+#
+#     % .. [Hit <.>]
+#     % ../.. [Hit <.>]
+#     % ../../.. [Hit <^H>]
+#     % ../.. [Hit <^H>]
+#     % ..
+#
+# As you see above, each of the `/..' parts complemented by this tweak
+# can be deleted by a single invocation of the backward-delete-char
+# command, only if invoked right after the magic happens.
+#
+#     % .. [Hit </><.><.>]
+#     % ../.. [Hit <^H>]
+#     % ../.
+#
+# Triple-dot is not a rarely used character sequence, and this tweak
+# kind of "knows" when it should be expanded.
+#
+#     % ruby -e '(1.. [Hit <.>]
+#     % ruby -e '(1...
+#
+#     % git log branch.. [Hit <.>]
+#     % git log branch...
+#
+#     % git diff .. [Hit <.>]
+#     % git diff ../.. [Hit <b>]      <- This may be a path...
+#     % git diff ...b [Hit <ranch>]   <- Or not.
+#     % git diff ...branch
+#
+# Usage:
+#     autoload -Uz manydots-magic
+#     manydots-magic
+#
+
+manydots-magic.self-insert() {
+    emulate -L zsh
+    local self_insert_function magic_count
+    zstyle -s ':manydots-magic' self-insert-function self_insert_function
+
+    if [[ "$KEYS" == .* && "$LBUFFER" != *...* && "$LBUFFER" == *.. ]] && {
+        local -a words
+        words=("${(@Q)${(z)LBUFFER}}")
+        # `...` is a wildcard operator in go
+        [[ ${${(@)words[1,-2]}[(I)go]} = 0 ]] &&
+        [[ $words[-1] == (|*[/=]|[\<\>=]\().. ]]
+    }
+    then
+        [[ "$LASTWIDGET" == (self-insert|backward-delete-char) ]] &&
+        zstyle -s ':manydots-magic' magic-count magic_count
+        zstyle ':manydots-magic' magic-count $((magic_count+1))
+        LBUFFER="$LBUFFER/."
+        zle "$self_insert_function"
+        return
+    fi
+
+    # cancel expansion if it does not seem right
+    if [[ "$KEYS" != [=/,:\;\|\&\<\>\(\)\[\]{}^~\'\"\`[:space:]]* &&
+        "$LASTWIDGET" == (self-insert|backward-delete-char) && "$LBUFFER" == *../.. ]] && {
+        zstyle -s ':manydots-magic' magic-count magic_count
+        [[ "$magic_count" -gt 0 ]]
+    }
+    then
+        repeat $magic_count LBUFFER="${LBUFFER%/..}"
+        repeat $magic_count LBUFFER="$LBUFFER."
+    fi
+
+    zstyle ':manydots-magic' magic-count 0
+
+    zle "$self_insert_function"
+}
+
+manydots-magic.backward-delete-char() {
+    emulate -L zsh
+    local backward_delete_char_function
+    zstyle -s ':manydots-magic' backward-delete-char-function backward_delete_char_function
+
+    if [[ "$LASTWIDGET" == (self-insert|backward-delete-char) && "$LBUFFER" == *../.. ]] && {
+        local magic_count
+        zstyle -s ':manydots-magic' magic-count magic_count
+        [[ "$magic_count" -gt 0 ]]
+    }
+    then
+        zstyle ':manydots-magic' magic-count $((magic_count-1))
+        LBUFFER="${LBUFFER%..}"
+    else
+        zstyle ':manydots-magic' magic-count 0
+    fi
+
+    zle "$backward_delete_char_function"
+}
+
+manydots-magic.on() {
+    emulate -L zsh
+    local self_insert_function="${$(zle -lL | awk \
+        '$1=="zle"&&$2=="-N"&&$3=="self-insert"{print $4;exit}'):-.self-insert}"
+
+    [[ "$self_insert_function" == manydots-magic.self-insert ]] &&
+        return 0
+
+    # For url-quote-magic which does not zle -N itself
+    zle -la "$self_insert_function" || zle -N "$self_insert_function"
+
+    zstyle ':manydots-magic' self-insert-function "$self_insert_function"
+
+    zle -A manydots-magic.self-insert self-insert
+
+    local backward_delete_char_function="$(zle -lL | awk \
+        '$1=="zle"&&$2=="-N"&&$3=="backward-delete-char"{print $4;exit}')"
+
+    if [[ -n "$backward_delete_char_function" ]]
+    then
+        zle -la "$backward_delete_char_function" || zle -N "$backward_delete_char_function"
+    else
+        zle -A backward-delete-char manydots-magic.orig.backward-delete-char
+        backward_delete_char_function=manydots-magic.orig.backward-delete-char
+    fi
+
+    zstyle ':manydots-magic' backward-delete-char-function "$backward_delete_char_function"
+
+    zle -A manydots-magic.backward-delete-char backward-delete-char
+
+    zstyle ':manydots-magic' magic-count 0
+
+    return 0
+}
+
+manydots-magic.off() {
+    emulate -L zsh
+    local self_insert_function backward_delete_char_function
+    zstyle -s ':manydots-magic' self-insert-function self_insert_function
+
+    [[ -n "$self_insert_function" ]] &&
+        zle -A "$self_insert_function" self-insert
+
+    zstyle -s ':manydots-magic' backward-delete-char-function backward_delete_char_function
+
+    [[ -n "$backward_delete_char_function" ]] &&
+        zle -A "$backward_delete_char_function" backward-delete-char
+
+    zstyle ':manydots-magic' magic-count 0
+
+    return 0
+}
+
+zle -N manydots-magic.self-insert
+zle -N manydots-magic.backward-delete-char
+zle -N manydots-magic.on
+zle -N manydots-magic.off
+
+manydots-magic() {
+    manydots-magic.on
+}
+
+[[ -o kshautoload ]] || manydots-magic "$@"
+
+# Copyright (c) 2011, 2012 Akinori MUSHA
+# 
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+