/* vim.css
 *
 * Copyright (C) 2015 Christian Hergert <christian@hergert.me>
 *
 * This file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This file is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Contributing:
 *
 * There are a lot of corner cases that vim handles. As you can see from the
 * text below, we do not handle all of them. If you would like to contribute
 * something that is missing, please do!
 *
 * In general, we use the selectors at the bottom to determine which binding
 * sets are active in a mode.
 *
 * "set-mode" is used to move our way through the state machine. Take a look
 * at the current uses to get an idea. "permanent" means that the mode will
 * stay active until it has been released (by Escape or something). transient
 * means that the the mode will disappear after a followup key press. However,
 * transient mode may simply trigger another transient mode. (cip would be
 * an example of this.
 *
 * If you need more advanced operations than you can perform, you might have
 * to dig into IdeSourceView to add a new GSignal (with G_SIGNAL_ACTION flag).
 * Any signal with G_SIGNAL_ACTION set in the following widget hierarchy
 * should be callable from these bindings.
 *
 *   - GtkWidget
 *     - GtkTextView
 *       - GtkSourceView
 *         - IdeSourceView
 *
 * For example, you could make the ficticious three-finger-salute keybinding
 * to delete the entire buffer like so:
 *
 *   bind "<ctrl><alt>delete" { "movement" (first-line, 0, 0, 0)
 *                              "movement" (last-line, 1, 0, 0)
 *                              "movement" (last-char, 1, 0, 0)
 *                              "copy-clipboard-extended" ()
 *                              "delete-selection" () };
 *
 * The "movement" action takes three parameters.
 *
 *   1) If we want to extend the selection with the movement. Otherwise, it
 *      will be cleared.
 *   2) If the movement is exclusive. See :help exlusive in vim.
 *   3) If the current count (digit prefix) should be applied to the movement.
 *
 * The first line will move the cursor to line and column 0:0. The second
 * movement will extend the selection to the last line of the file (1
 * indicates TRUE to the second action parameter "extend_selection").
 * The third movement will move to the end of the current line (now the last
 * line due to second movement). We then copy to the clipboard just to be
 * nice, and then delete the whole thing from the buffer.
 *
 * NOTE: the exclusive/inclusive parameters are probably not right. They need
 *       either careful study or battle testing.
 *
 * That's pretty much it, happy Vim'ing!
 *
 *   -- Christian
 */

@import url("resource:///org/gnome/builder/keybindings/shared.css");

@binding-set builder-vim-source-view
{
  bind "Escape" { "end-macro" ()
                  "set-overwrite" (0)
                  "clear-count" ()
                  "clear-selection" ()
                  "clear-snippets" ()
                  "hide-completion" ()
                  "set-mode" ("vim-normal", permanent)
                  "remove-cursors" () };
  bind "<ctrl>bracketleft" { "end-macro" ()
                             "set-overwrite" (0)
                             "clear-count" ()
                             "clear-selection" ()
                             "clear-snippets" ()
                             "hide-completion" ()
                             "set-mode" ("vim-normal", permanent) };
  bind "<ctrl>c" { "end-macro" ()
                   "set-overwrite" (0)
                   "clear-count" ()
                   "clear-selection" ()
                   "clear-snippets" ()
                   "hide-completion" ()
                   "set-mode" ("vim-normal", permanent) };

  bind "<ctrl>k" { "action" ("frame", "show-list", "") };
  bind "<ctrl>minus" { "decrease-font-size" () };
  bind "<ctrl>plus" { "increase-font-size" () };
  bind "<ctrl>KP_Subtract" { "decrease-font-size" () };
  bind "<ctrl>KP_Add" { "increase-font-size" () };
  bind "<ctrl>equal" { "increase-font-size" () };
  bind "<ctrl>0" { "reset-font-size" () };
  bind "<ctrl><shift>e" { "add-cursor" (column) };
  bind "<ctrl><shift>d" { "add-cursor" (match) };

  bind "F4" { "action" ("win", "find-other-file", "") };
  bind "<ctrl>asciicircum" { "action" ("win", "find-other-file", "") };
}

@binding-set builder-vim-source-view-normal-with-count
{
  bind "0" { "append-to-count" (0)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_0" { "append-to-count" (0)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "percent" { "movement" (line-percentage, 0, 1, 1)
                   "set-mode" ("vim-normal-with-count", transient) };
}

@binding-set builder-vim-source-view-normal
{
  bind "<ctrl>l" { "rebuild-highlight" () };

  bind "1" { "append-to-count" (1)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "2" { "append-to-count" (2)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "3" { "append-to-count" (3)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "4" { "append-to-count" (4)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "5" { "append-to-count" (5)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "6" { "append-to-count" (6)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "7" { "append-to-count" (7)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "8" { "append-to-count" (8)
             "set-mode" ("vim-normal-with-count", transient) };
  bind "9" { "append-to-count" (9)
             "set-mode" ("vim-normal-with-count", transient) };

  bind "KP_1" { "append-to-count" (1)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_2" { "append-to-count" (2)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_3" { "append-to-count" (3)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_4" { "append-to-count" (4)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_5" { "append-to-count" (5)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_6" { "append-to-count" (6)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_7" { "append-to-count" (7)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_8" { "append-to-count" (8)
                "set-mode" ("vim-normal-with-count", transient) };
  bind "KP_9" { "append-to-count" (9)
                "set-mode" ("vim-normal-with-count", transient) };

  bind "colon" { "action" ("win", "reveal-command-bar", "") };

  /* cycle "tabs" */
  bind "<ctrl><alt>Page_Up" { "action" ("frame", "previous-page", "") };
  bind "<ctrl><alt>KP_Page_Up" { "action" ("frame", "previous-page", "") };
  bind "<ctrl><alt>Page_Down" { "action" ("frame", "next-page", "") };
  bind "<ctrl><alt>KP_Page_Down" { "action" ("frame", "next-page", "") };

  /* replay the last recording */
  bind "period" { "replay-macro" (1) };

  /* start search backward */
  /* TODO: use internal sourceview search */
  bind "question" { "action" ("editor-page", "find", "") };

  /* start search */
  bind "slash" { "action" ("editor-search", "at-word-boundaries", "false")
                 "action" ("editor-page", "find", "") };
  bind "KP_Divide" { "action" ("editor-page", "find", "") };

  /* insert at cursor */
  bind "i" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent) };

  /* insert after cursor */
  bind "a" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (next-char, 0, 1, 0) };
  bind "<shift>a" { "begin-macro" ()
                    "set-mode" ("vim-insert", permanent)
                    "movement" (last-char, 0, 0, 0) };

  /* insert at first non-whitespace character */
  bind "<shift>i" { "begin-macro" ()
                    "set-mode" ("vim-insert", permanent)
                    "movement" (first-nonspace-char, 0, 1, 0) };

  /* insert line after current, insert mode */
  bind "o" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (line-end, 0, 1, 0)
             "insert-at-cursor" ("\n")
             "reindent" ()
             "movement" (last-char, 0, 0, 0) };

  /* insert line before current */
  bind "<shift>o" { "begin-macro" ()
                    "set-mode" ("vim-insert", permanent)
                    "movement" (first-char, 0, 0, 0)
                    "insert-at-cursor" ("\n")
                    "move-cursor" (display-lines, -1, 0)
                    "reindent" ()
                    "movement" (last-char, 0, 0, 0) };

  bind "minus" { "movement" (previous-line, 0, 1, 1)
                 "movement" (first-nonspace-char, 0, 1, 0)
                 "clear-count" () };

  bind "plus" { "movement" (next-line, 0, 1, 1)
                 "movement" (first-nonspace-char, 0, 1, 0)
                 "clear-count" () };
  bind "KP_Enter" { "movement" (next-line, 0, 1, 1)
                    "movement" (first-nonspace-char, 0, 1, 0)
                    "clear-count" () };
  bind "<shift>KP_Enter" { "movement" (next-line, 0, 1, 1)
                           "movement" (first-nonspace-char, 0, 1, 0)
                           "clear-count" () };
  bind "Return" { "movement" (next-line, 0, 1, 1)
                  "movement" (first-nonspace-char, 0, 1, 0)
                  "clear-count" () };
  bind "<shift>Return" { "movement" (next-line, 0, 1, 0)
                         "movement" (first-nonspace-char, 0, 1, 0)
                         "clear-count" () };

  bind "<shift>k" { "clear-selection" ()
                    "save-insert-mark" ()
                    "movement" (previous-word-end, 0, 1, 1)
                    "movement" (next-word-start, 0, 1, 0)
                    "movement" (next-word-end, 1, 0, 1)
                    "request-documentation" ()
                    "clear-count" ()
                    "clear-selection" ()
                    "restore-insert-mark" () };

  /* swallow the current character and go to insert */
  bind "s" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (next-char, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" () };

  /* overwrite the current character with a modifier */
  bind "r" { "begin-macro" ()
             "begin-user-action" ()
             "capture-modifier" ()
             "movement" (next-char, 1, 1, 1)
             "delete-selection" ()
             "insert-modifier" (1)
             "clear-modifier" ()
             "movement" (previous-char, 0, 1, 0)
             "end-user-action" ()
             "end-macro" () };

  bind "Left"  { "movement" (previous-char, 0, 1, 1)
                 "clear-count" () };
  bind "Right" { "movement" (next-char, 0, 1, 1)
                 "clear-count" () };
  bind "Up"    { "movement" (previous-line, 0, 1, 1)
                 "clear-count" () };
  bind "Down"  { "movement" (next-line, 0, 1, 1)
                 "clear-count" () };

  bind "h"     { "movement" (previous-char, 0, 1, 1)
                 "clear-count" () };
  bind "l"     { "movement" (next-char, 0, 1, 1)
                 "clear-count" () };
  bind "k"     { "movement" (previous-line, 0, 1, 1)
                 "clear-count" () };
  bind "j"     { "movement" (next-line, 0, 1, 1)
                 "clear-count" () };

  /* move to special sub-mode 'g' */
  bind "g" { "set-mode" ("vim-normal-g", transient ) };

  /* move by word ends */
  bind "e"        { "movement" (next-word-end, 0, 1, 1)
                    "clear-count" () };
  bind "<shift>e" { "movement" (next-full-word-end, 0, 1, 1)
                    "clear-count" () };

  /* move to by word start */
  bind "w"        { "movement" (next-word-start, 0, 1, 1)
                    "clear-count" () };
  bind "<shift>w" { "movement" (next-full-word-start, 0, 1, 1)
                    "clear-count" () };
  bind "b"        { "movement" (previous-word-start, 0, 1, 1)
                    "clear-count" () };
  bind "<shift>b" { "movement" (previous-full-word-start, 0, 1, 1)
                    "clear-count" () };

  /* find matching char */
  bind "f" { "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 0, 1, 1)
             "clear-modifier" () };
  bind "t" { "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 0, 1, 1)
             "movement" (previous-char, 0, 1, 0)
             "clear-modifier" () };
  bind "<shift>f" { "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "movement" (previous-match-modifier, 0, 1, 1)
                    "clear-modifier" () };
  bind "<shift>t" { "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "movement" (previous-match-modifier, 0, 0, 1)
                    "clear-modifier" () };
  bind "comma" { "movement" (previous-match-search-char, 0, 0, 1)
                 "clear-count" () };
  bind "semicolon" { "movement" (next-match-search-char, 0, 0, 1)
                     "clear-count" () };

  bind "n" { "save-insert-mark" ()
             "move-search" (tab-forward, 0, 0, 1, 1, 0)
             "restore-insert-mark" () };
  bind "<shift>n" { "save-insert-mark" ()
                    "move-search" (tab-backward, 0, 0, 0, 1, 0)
                    "restore-insert-mark" () };

  bind "numbersign" { "save-insert-mark" ()
                      "movement" (next-word-end, 0, 1, 0)
                      "movement" (previous-word-start, 0, 1, 0)
                      "movement" (next-word-end, 1, 0, 0)
                      "set-search-text" ("", 1)
                      "movement" (previous-char, 0, 1, 0)
                      "move-search" (up, 0, 0, 0, 1, 1)
                      "restore-insert-mark" () };

  bind "asterisk" { "save-insert-mark" ()
                    "movement" (next-word-end, 0, 1, 0)
                    "movement" (previous-word-start, 0, 1, 0)
                    "movement" (next-word-end, 1, 0, 0)
                    "set-search-text" ("", 1)
                    "move-search" (down, 0, 0, 1, 1, 1)
                    "restore-insert-mark" () };

  bind "KP_Multiply" { "save-insert-mark" ()
                       "movement" (previous-word-end, 0, 1, 1)
                       "movement" (next-word-start, 0, 1, 0)
                       "movement" (next-word-end, 1, 0, 1)
                       "set-search-text" ("", 1)
                       "move-search" (down, 0, 0, 1, 1, 1)
                       "restore-insert-mark" () };

  /* page movements */
  bind "<ctrl>b" { "movement" (page-up, 0, 0, 1)
                   "clear-count" () };
  bind "<ctrl>f" { "movement" (page-down, 0, 0, 1)
                   "clear-count" () };
  bind "<ctrl>u" { "movement" (half-page-up, 0, 0, 1)
                   "clear-count" () };
  bind "<ctrl>d" { "movement" (half-page-down, 0, 0, 1)
                   "clear-count" () };
  bind "Page_Up" { "movement" (page-up, 0, 0, 1)
                   "clear-count" () };
  bind "Page_Down" { "movement" (page-down, 0, 0, 1)
                     "clear-count" () };

  /* screen movements, keeping cursor locked to visible region */
  bind "<ctrl>e" { "movement" (screen-up, 0, 0, 1)
                   "clear-count" () };
  bind "<ctrl>y" { "movement" (screen-down, 0, 0, 1)
                   "clear-count" () };
  bind "z" { "set-mode" ("vim-normal-z", transient) };
  bind "<shift>z" { "set-mode" ("vim-normal-Z", transient) };

  /* macro recording! */
  bind "q" { "set-mode" ("vim-normal-q", transient) };

  /* goto definition (or follow-link, really) */
  bind "<ctrl>bracketright" { "goto-definition" () };

  /* submode for bracket */
  bind "bracketleft" { "set-mode" ("vim-normal-bracket", transient) };

  /* move by paragraph */
  bind "braceleft" { "movement" (paragraph-start, 0, 0, 1)
                     "clear-count" () };
  bind "braceright" { "movement" (paragraph-end, 0, 0, 1)
                      "clear-count" () };

  /* move by sentence */
  bind "parenleft" { "movement" (sentence-start, 0, 0, 1)
                     "clear-count" () };
  bind "parenright" { "movement" (sentence-end, 0, 0, 1)
                      "clear-count" () };

  /* move to line offset of zero, and first non-whitespace char, end of line */
  bind "0" { "movement" (first-char, 0, 1, 0)
             "clear-count" () };
  bind "KP_0" { "movement" (first-char, 0, 1, 0)
                "clear-count" () };
  bind "Home" { "movement" (first-char, 0, 1, 0)
                "clear-count" () };
  bind "asciicircum" { "movement" (first-nonspace-char, 0, 1, 0)
                       "clear-count" () };

  /* this is a count - 1 motion, we handle this specific case in C code */
  bind "underscore" { "movement" (next-line, 0, 1, 1)
                      "movement" (first-nonspace-char, 0, 1, 0)
                      "clear-count" () };

  bind "dollar" { "movement" (last-char, 0, 1, 0)
                  "clear-count" () };
  bind "End" { "movement" (last-char, 0, 1, 0)
               "clear-count" () };
  bind "bar" { "movement" (nth-char, 0, 1, 1)
               "clear-count" () };

  /* jump to match of brace/bracket/comment/etc */
  bind "percent" { "movement" (match-special, 0, 1, 1)
                   "clear-count" () };

  /* move based on visible screen area */
  bind "<shift>h" { "movement" (screen-top, 0, 0, 0)
                    "clear-count" () };
  bind "<shift>m" { "movement" (screen-middle, 0, 0, 0)
                    "clear-count" () };
  bind "<shift>l" { "movement" (screen-bottom, 0, 0, 0)
                    "clear-count" () };

  /* move to nth line, defaults to last */
  bind "<shift>g" { "movement" (nth-line, 0, 1, 1)
                    "movement" (first-nonspace-char, 0, 1, 0)
                    "clear-count" () };

  /* undo - todo: how do we land cursor on right spot? */
  bind "u" { "undo" ()
             "clear-count" ()
             "clear-selection" ()};

  /* redo */
  bind "<ctrl>r" { "redo" ()
                   "clear-count" ()
                   "clear-selection" () };

  bind "p" { "begin-macro" ()
             "paste-clipboard-extended" (1, 1, 0)
             "movement" (previous-char, 0, 1, 0)
             "clear-count" ()
             "end-macro" () };
  bind "<shift>p" { "begin-macro" ()
                    "paste-clipboard-extended" (1, 0, 0)
                    "movement" (previous-char, 0, 1, 0)
                    "clear-count" ()
                    "end-macro" () };

  /* overwrite */
  bind "<shift>r" { "begin-macro" ()
                    "set-mode" ("vim-replace", permanent)
                    "set-overwrite" (1) };

 /* jump to sub-mode */
  bind "c" { "set-mode" ("vim-normal-c", transient) };
  bind "d" { "set-mode" ("vim-normal-d", transient) };

  /* delete to end of line */
  bind "<shift>d" { "begin-macro" ()
                    "movement" (last-char, 1, 0, 0)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "clear-count" ()
                    "end-macro" () };

 /* delete to end of line and go to insert */
  bind "<shift>c" { "begin-macro" ()
                    "movement" (last-char, 1, 0, 0)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "clear-count" ()
                    "set-mode" ("vim-insert", permanent) };

  /* delete current char */
  bind "x" { "begin-macro" ()
             "movement" (next-char, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "clear-count" ()
             "end-macro" () };

  /* delete previous char */
  bind "<shift>x" { "begin-macro" ()
                    "movement" (previous-char, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "clear-count" ()
                    "end-macro" () };

  bind "greater" { "set-mode" ("vim-normal-indent", transient) };
  bind "less" { "set-mode" ("vim-normal-indent", transient) };

  /* join selected lines */
  /* todo: this actually grabs one more line than vim does when prefixed with
   *       a count. 1J and 2J are both the same thing.
   */
  bind "<shift>j" { "begin-macro" ()
                    "movement" (first-char, 0, 0, 0)
                    "movement" (next-line, 1, 0, 1)
                    "join-lines" ()
                    "clear-count" ()
                    "end-macro" () };

  /* change number */
  bind "<ctrl>a" { "begin-macro" ()
                   "change-number" (1)
                   "clear-count" ()
                   "end-macro" () };
  bind "<ctrl>x" { "begin-macro" ()
                   "change-number" (-1)
                   "clear-count" ()
                   "end-macro" () };

  /* toggle character case */
  bind "asciitilde" { "begin-macro" ()
                      "movement" (next-char, 1, 1, 1)
                      "change-case" (toggle)
                      "clear-count" ()
                      "end-macro" () };

  bind "BackSpace" { "movement" (previous-offset, 0, 1, 1)
                     "clear-count" () };
  bind "space" { "movement" (next-offset, 0, 1, 1)
                 "clear-count" () };

  /* copy */
  bind "y" { "set-mode" ("vim-normal-y", transient) };
  bind "<shift>y" { "save-insert-mark" ()
                    "movement" (first-char, 0, 0, 0)
                    "movement" (next-line, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (expand)
                    "clear-count" ()
                    "clear-selection" ()
                    "restore-insert-mark" () };

  /* visual mode transition */
  bind "v" { "begin-macro" ()
             "movement" (next-char, 1, 1, 1)
             "set-mode" ("vim-visual", permanent) };
  bind "<shift>v" { "begin-macro" ()
                    "movement" (first-char, 0, 1, 0)
                    "movement" (next-line, 1, 0, 1)
                    "set-mode" ("vim-visual-line", permanent) };
  bind "<ctrl>v" { "set-mode" ("vim-visual-block", permanent) };

  /* navigation */
  bind "<ctrl>o" { "action" ("history", "move-previous-edit", "") };
  bind "<ctrl>i" { "action" ("history", "move-next-edit", "") };

  /* window controls */
  bind "<ctrl>w" { "set-mode" ("vim-normal-ctrl-w", transient) };

  /* reindent */
  bind "equal" { "set-mode" ("vim-normal-equal", transient) };
}

@binding-set builder-vim-source-view-normal-equal
{
  bind "equal" { "reindent" () };
}

@binding-set builder-vim-source-view-normal-bracket
{
  bind "braceleft" { "movement" (previous-unmatched-brace, 0, 1, 1) };
  bind "braceright" { "movement" (next-unmatched-brace, 0, 1, 1) };

  bind "parenleft" { "movement" (previous-unmatched-paren, 0, 1, 1) };
  bind "parenright" { "movement" (next-unmatched-paren, 0, 1, 1) };
}

@binding-set builder-vim-source-view-normal-c
{
  bind "1" { "append-to-count" (1)
             "set-mode" ("vim-c-with-count", transient) };
  bind "2" { "append-to-count" (2)
             "set-mode" ("vim-c-with-count", transient) };
  bind "3" { "append-to-count" (3)
             "set-mode" ("vim-c-with-count", transient) };
  bind "4" { "append-to-count" (4)
             "set-mode" ("vim-c-with-count", transient) };
  bind "5" { "append-to-count" (5)
             "set-mode" ("vim-c-with-count", transient) };
  bind "6" { "append-to-count" (6)
             "set-mode" ("vim-c-with-count", transient) };
  bind "7" { "append-to-count" (7)
             "set-mode" ("vim-c-with-count", transient) };
  bind "8" { "append-to-count" (8)
             "set-mode" ("vim-c-with-count", transient) };
  bind "9" { "append-to-count" (9)
             "set-mode" ("vim-c-with-count", transient) };

  bind "KP_1" { "append-to-count" (1)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_2" { "append-to-count" (2)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_3" { "append-to-count" (3)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_4" { "append-to-count" (4)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_5" { "append-to-count" (5)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_6" { "append-to-count" (6)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_7" { "append-to-count" (7)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_8" { "append-to-count" (8)
                "set-mode" ("vim-c-with-count", transient) };
  bind "KP_9" { "append-to-count" (9)
                "set-mode" ("vim-c-with-count", transient) };

  bind "i" { "set-mode" ("vim-normal-c-i", transient) };

  bind "a" { "set-mode" ("vim-normal-c-a", transient) };

  bind "e" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (next-word-end, 1, 0, 1)
             "copy-clipboard-extended" ()
             "delete-selection" () };
  bind "w" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (next-word-end, 1, 0, 1)
             "copy-clipboard-extended" ()
             "delete-selection" () };

  bind "l" { "begin-macro" ()
             "movement" (next-char, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "set-mode" ("vim-insert", permanent) };
  bind "h" { "begin-macro" ()
             "movement" (previous-char, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "set-mode" ("vim-insert", permanent) };
  bind "k" { "begin-macro" ()
             "movement" (last-char, 0, 0, 0)
             "movement" (previous-line, 1, 0, 1)
             "movement" (first-char, 1, 1, 0)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "set-mode" ("vim-insert", permanent) };
  bind "j" { "begin-macro" ()
             "movement" (first-char, 0, 1, 0)
             "movement" (next-line, 1, 0, 1)
             "movement" (last-char, 1, 0, 0)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "set-mode" ("vim-insert", permanent) };
  bind "Right" { "begin-macro" ()
                 "movement" (next-char, 1, 1, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "set-mode" ("vim-insert", permanent) };
  bind "Left" { "begin-macro" ()
                "movement" (previous-char, 1, 1, 1)
                "copy-clipboard-extended" ()
                "delete-selection" ()
                "set-mode" ("vim-insert", permanent) };
  bind "Up" { "begin-macro" ()
              "movement" (last-char, 0, 0, 0)
              "movement" (previous-line, 1, 0, 1)
              "movement" (first-char, 1, 1, 0)
              "copy-clipboard-extended" ()
              "delete-selection" ()
              "set-mode" ("vim-insert", permanent) };
  bind "Down" { "begin-macro" ()
                "movement" (first-char, 0, 1, 0)
                "movement" (next-line, 1, 0, 1)
                "movement" (last-char, 1, 0, 0)
                "copy-clipboard-extended" ()
                "delete-selection" ()
                "set-mode" ("vim-insert", permanent) };

  bind "0" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (first-char, 1, 0, 0)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "KP_0" { "begin-macro" ()
                "set-mode" ("vim-insert", permanent)
                "movement" (first-char, 1, 0, 0)
                "copy-clipboard-extended" ()
                "delete-selection" ()
                "end-macro" () };

  bind "plus" { "begin-macro" ()
                "movement" (first-char, 0, 1, 0)
                "movement" (next-line, 1, 0, 1)
                "movement" (last-char, 1, 0, 0)
                "copy-clipboard-extended" ()
                "delete-selection" ()
                "reindent" ()
                "clear-count" ()
                "set-mode" ("vim-insert", permanent) };
  bind "KP_Enter" { "begin-macro" ()
                    "movement" (first-char, 0, 1, 0)
                    "movement" (next-line, 1, 0, 1)
                    "movement" (last-char, 1, 0, 0)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "reindent" ()
                    "clear-count" ()
                    "set-mode" ("vim-insert", permanent) };
  bind "<shift>KP_Enter" { "begin-macro" ()
                           "movement" (first-char, 0, 1, 0)
                           "movement" (next-line, 1, 0, 1)
                           "movement" (last-char, 1, 0, 0)
                           "copy-clipboard-extended" ()
                           "delete-selection" ()
                           "reindent" ()
                           "clear-count" ()
                           "set-mode" ("vim-insert", permanent) };
  bind "Return" { "begin-macro" ()
                  "movement" (first-char, 0, 1, 0)
                  "movement" (next-line, 1, 0, 1)
                  "movement" (last-char, 1, 0, 0)
                  "copy-clipboard-extended" ()
                  "delete-selection" ()
                  "reindent" ()
                  "clear-count" ()
                  "set-mode" ("vim-insert", permanent) };
  bind "<shift>Return" { "begin-macro" ()
                         "movement" (first-char, 0, 1, 0)
                         "movement" (next-line, 1, 0, 1)
                         "movement" (last-char, 1, 0, 0)
                         "copy-clipboard-extended" ()
                         "delete-selection" ()
                         "reindent" ()
                         "clear-count" ()
                         "set-mode" ("vim-insert", permanent) };

  bind "<shift>asciicircum" { "begin-macro" ()
                              "set-mode" ("vim-insert", permanent)
                              "movement" (first-nonspace-char, 1, 1, 1)
                              "copy-clipboard-extended" ()
                              "delete-selection" ()
                              "end-macro" () };

  /* this is a count - 1 motion, we handle this specific case in C code */
  bind "underscore" { "begin-macro" ()
                      "movement" (first-char, 0, 1, 0)
                      "movement" (next-line, 1, 0, 1)
                      "movement" (last-char, 1, 0, 0)
                      "copy-clipboard-extended" ()
                      "delete-selection" ()
                      "reindent" ()
                      "clear-count" ()
                      "set-mode" ("vim-insert", permanent) };

  bind "dollar" { "begin-macro" ()
                  "set-mode" ("vim-insert", permanent)
                  "movement" (line-end, 1, 1, 0)
                  "copy-clipboard-extended" ()
                  "delete-selection" ()
                  "end-macro" () };


  bind "f" { "begin-macro" ()
             "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (next-match-modifier, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" ()
             "clear-modifier" () };

  bind "t" { "begin-macro" ()
             "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (next-match-modifier, 1, 1, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" ()
             "clear-modifier" () };

  bind "c" { "begin-macro" ()
             "movement" (first-char, 0, 1, 0)
             "movement" (last-char, 1, 0, 0)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "reindent" ()
             "set-mode" ("vim-insert", permanent) };

  bind "<shift>f" { "begin-macro" ()
                    "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "set-mode" ("vim-insert", permanent)
                    "movement" (previous-match-modifier, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" ()
                    "clear-modifier" () };

  bind "<shift>t" { "begin-macro" ()
                    "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "set-mode" ("vim-insert", permanent)
                    "movement" (previous-match-modifier, 1, 0, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" ()
                    "clear-modifier" () };

  bind "comma" { "begin-macro" ()
                 "movement" (previous-match-search-char, 1, 0, 1)
                 "set-mode" ("vim-insert", permanent)
                 "copy-clipboard-extended" ()
                 "selection-theatric" (shrink)
                 "delete-selection" () };

  bind "semicolon" { "begin-macro" ()
                     "movement" (next-match-search-char, 1, 0, 1)
                     "set-mode" ("vim-insert", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };
}

@binding-set builder-vim-source-view-c-with-count
{
  bind "0" { "append-to-count" (0)
             "set-mode" ("vim-c-with-count", transient) };
  bind "KP_0" { "append-to-count" (0)
                "set-mode" ("vim-c-with-count", transient) };
}

@binding-set builder-vim-source-view-normal-c-i
{
  /* cip */
  bind "p" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (paragraph-start, 1, 1, 1)
             "swap-selection-bounds" ()
             "movement" (paragraph-end, 1, 1, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* cis */
  bind "s" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (sentence-start, 1, 1, 1)
             "swap-selection-bounds" ()
             "movement" (sentence-end, 1, 1, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* ciw */
  bind "w" { "begin-macro" ()
             "set-mode" ("vim-insert", permanent)
             "movement" (previous-word-end, 0, 1, 1)
             "movement" (next-word-start, 0, 1, 0)
             "movement" (next-word-end, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* ciW */
  bind "<shift>w" { "begin-macro" ()
                    "set-mode" ("vim-insert", permanent)
                    "movement" (previous-full-word-end, 0, 1, 1)
                    "movement" (next-full-word-start, 0, 1, 0)
                    "movement" (next-full-word-end, 1, 0, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" () };

  /* ci( , ci) , cib */
  bind "parenleft" { "begin-macro" ()
                     "select-inner" ("(", ")", 1, 0)
                     "set-mode" ("vim-insert", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "parenright" { "begin-macro" ()
                      "select-inner" ("(", ")", 1, 0)
                      "set-mode" ("vim-insert", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "b" { "begin-macro" ()
             "select-inner" ("(", ")", 1, 0)
             "set-mode" ("vim-insert", permanent)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* ci[ and ci] */
  bind "bracketleft" { "begin-macro" ()
                       "select-inner" ("[", "]", 1, 0)
                       "set-mode" ("vim-insert", permanent)
                       "copy-clipboard-extended" ()
                       "selection-theatric" (shrink)
                       "delete-selection" () };

  bind "bracketright" { "begin-macro" ()
                        "select-inner" ("[", "]", 1, 0)
                        "set-mode" ("vim-insert", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

  /* ci{ , ci} , ciB */
  bind "braceleft" { "begin-macro" ()
                     "select-inner" ("{", "}", 1, 0)
                     "set-mode" ("vim-insert", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "braceright" { "begin-macro" ()
                      "select-inner" ("{", "}", 1, 0)
                      "set-mode" ("vim-insert", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "<shift>b" { "begin-macro" ()
                    "select-inner" ("{", "}", 1, 0)
                    "set-mode" ("vim-insert", permanent)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" () };

  /* ci< and ci> */
    bind "less" { "begin-macro" ()
                  "select-inner" ("<", ">", 1, 0)
                  "set-mode" ("vim-insert", permanent)
                  "copy-clipboard-extended" ()
                  "selection-theatric" (shrink)
                  "delete-selection" () };

    bind "greater" { "begin-macro" ()
                     "select-inner" ("<", ">", 1, 0)
                     "set-mode" ("vim-insert", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  /* ci" ci' ci` */
    bind "quotedbl" { "begin-macro" ()
                      "select-inner" ("\"", "\"", 1, 1)
                      "set-mode" ("vim-insert", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

    bind "apostrophe" { "begin-macro" ()
                        "select-inner" ("'", "'", 1, 1)
                        "set-mode" ("vim-insert", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

    bind "grave" { "begin-macro" ()
                   "select-inner" ("`", "`", 1, 1)
                   "set-mode" ("vim-insert", permanent)
                   "copy-clipboard-extended" ()
                   "selection-theatric" (shrink)
                   "delete-selection" () };

  /* cit */
    bind "t" { "begin-macro" ()
               "select-tag" (1)
               "set-mode" ("vim-insert", permanent)
               "copy-clipboard-extended" ()
               "selection-theatric" (shrink)
               "delete-selection" () };
}

@binding-set builder-vim-source-view-normal-c-a
{
  /* ca( , ca) , cab */
  bind "parenleft" { "begin-macro" ()
                     "select-inner" ("(", ")", 0, 0)
                     "set-mode" ("vim-insert", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "parenright" { "begin-macro" ()
                      "select-inner" ("(", ")", 0, 0)
                      "set-mode" ("vim-insert", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "b" { "begin-macro" ()
             "select-inner" ("(", ")", 0, 0)
             "set-mode" ("vim-insert", permanent)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* ca[ and ca] */
  bind "bracketleft" { "begin-macro" ()
                       "select-inner" ("[", "]", 0, 0)
                       "set-mode" ("vim-insert", permanent)
                       "copy-clipboard-extended" ()
                       "selection-theatric" (shrink)
                       "delete-selection" () };

  bind "bracketright" { "begin-macro" ()
                        "select-inner" ("[", "]", 0, 0)
                        "set-mode" ("vim-insert", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

  /* ca{ , ca} , caB */
  bind "braceleft" { "begin-macro" ()
                     "select-inner" ("{", "}", 0, 0)
                     "set-mode" ("vim-insert", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "braceright" { "begin-macro" ()
                      "select-inner" ("{", "}", 0, 0)
                      "set-mode" ("vim-insert", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "<shift>b" { "begin-macro" ()
                    "select-inner" ("{", "}", 0, 0)
                    "set-mode" ("vim-insert", permanent)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" () };

  /* ca< and ca> */
    bind "less" { "begin-macro" ()
                  "select-inner" ("<", ">", 0, 0)
                  "set-mode" ("vim-insert", permanent)
                  "copy-clipboard-extended" ()
                  "selection-theatric" (shrink)
                  "delete-selection" () };

    bind "greater" { "begin-macro" ()
                     "select-inner" ("<", ">", 0, 0)
                     "set-mode" ("vim-insert", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  /* ca" ca' ca` */
    bind "quotedbl" { "begin-macro" ()
                      "select-inner" ("\"", "\"", 0, 1)
                      "set-mode" ("vim-insert", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

    bind "apostrophe" { "begin-macro" ()
                        "select-inner" ("'", "'", 0, 1)
                        "set-mode" ("vim-insert", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

    bind "grave" { "begin-macro" ()
                   "select-inner" ("`", "`", 0, 1)
                   "set-mode" ("vim-insert", permanent)
                   "copy-clipboard-extended" ()
                   "selection-theatric" (shrink)
                   "delete-selection" () };

  /* cat */
    bind "t" { "begin-macro" ()
               "select-tag" (0)
               "set-mode" ("vim-insert", permanent)
               "copy-clipboard-extended" ()
               "selection-theatric" (shrink)
               "delete-selection" () };
}

@binding-set builder-vim-source-view-normal-d
{
  bind "Left"  { "begin-macro" ()
                 "movement" (previous-char, 1, 1, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "end-macro" () };
  bind "h"     { "begin-macro" ()
                 "movement" (previous-char, 1, 1, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "end-macro" () };

  bind "braceleft"  { "begin-macro" ()
                      "movement" (paragraph-start, 1, 0, 1)
                      "copy-clipboard-extended" ()
                      "delete-selection" ()
                      "end-macro" () };

  bind "braceright" { "begin-macro" ()
                      "movement" (paragraph-end, 1, 0, 1)
                      "copy-clipboard-extended" ()
                      "delete-selection" ()
                      "end-macro" () };

  bind "Right" { "begin-macro" ()
                 "movement" (next-char, 1, 1, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "end-macro" () };
  bind "l"     { "begin-macro" ()
                 "movement" (next-char, 1, 1, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "end-macro" () };

  bind "Up"    { "begin-macro" ()
                 "movement" (line-end, 0, 0, 0)
                 "movement" (previous-line, 1, 0, 0)
                 "movement" (previous-line, 1, 0, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "movement" (first-nonspace-char, 0, 1, 0)
                 "end-macro" () };
  bind "k"     { "begin-macro" ()
                 "movement" (line-end, 0, 0, 0)
                 "movement" (previous-line, 1, 0, 0)
                 "movement" (previous-line, 1, 0, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "movement" (first-nonspace-char, 0, 1, 0)
                 "end-macro" () };

  bind "Down"  { "begin-macro" ()
                 "movement" (first-char, 0, 1, 0)
                 "movement" (next-line, 1, 0, 0)
                 "movement" (next-line, 1, 0, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "movement" (first-nonspace-char, 0, 1, 0)
                 "end-macro" () };
  bind "j"     { "begin-macro" ()
                 "movement" (first-char, 0, 1, 0)
                 "movement" (next-line, 1, 0, 0)
                 "movement" (next-line, 1, 0, 1)
                 "copy-clipboard-extended" ()
                 "delete-selection" ()
                 "movement" (first-nonspace-char, 0, 1, 0)
                 "end-macro" () };
  bind "Return" { "begin-macro" ()
                  "movement" (first-char, 0, 1, 0)
                  "movement" (next-line, 1, 0, 0)
                  "movement" (next-line, 1, 0, 1)
                  "copy-clipboard-extended" ()
                  "delete-selection" ()
                  "movement" (first-nonspace-char, 0, 1, 0)
                  "end-macro" () };

  bind "<shift>g" { "begin-macro" ()
                    "movement" (nth-line, 1, 0, 1)
                    "movement" (last-char, 1, 0, 0)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "movement" (last-char, 0, 0, 0)
                    "end-macro" () };

  bind "i" { "set-mode" ("vim-normal-d-i", transient) };
  bind "a" { "set-mode" ("vim-normal-d-a", transient) };
  bind "g" { "set-mode" ("vim-normal-d-g", transient) };

  bind "f" { "begin-macro" ()
             "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" ()
             "clear-modifier" ()
             "end-macro" () };
  bind "t" { "begin-macro" ()
             "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 1, 1, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" ()
             "clear-modifier" ()
             "end-macro" () };

  bind "<shift>f" { "begin-macro" ()
                    "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "movement" (previous-match-modifier, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" ()
                    "clear-modifier" ()
                    "end-macro" () };
  bind "<shift>t" { "begin-macro" ()
                    "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "movement" (previous-match-modifier, 1, 0, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" ()
                    "clear-modifier" ()
                    "end-macro" () };
  bind "comma" { "begin-macro" ()
                 "movement" (previous-match-search-char, 1, 1, 1)
                 "copy-clipboard-extended" ()
                 "selection-theatric" (shrink)
                 "delete-selection" ()
                 "clear-count" ()
                 "end-macro" () };

  bind "semicolon" { "begin-macro" ()
                     "movement" (next-match-search-char, 1, 0, 1)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" ()
                     "clear-count" ()
                     "end-macro" () };

  bind "d" { "begin-macro" ()
             "movement" (first-char, 0, 1, 0)
             "movement" (next-line, 1, 0, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "movement" (first-nonspace-char, 0, 1, 0)
             "end-macro" () };

  bind "plus" { "begin-macro" ()
                "movement" (first-char, 0, 1, 0)
                "movement" (next-line, 1, 0, 0)
                "movement" (next-line, 1, 0, 1)
                "copy-clipboard-extended" ()
                "delete-selection" ()
                "movement" (first-nonspace-char, 0, 1, 0)
                "clear-count" () };
  bind "KP_Enter" { "begin-macro" ()
                    "movement" (first-char, 0, 1, 0)
                    "movement" (next-line, 1, 0, 0)
                    "movement" (next-line, 1, 0, 1)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "movement" (first-nonspace-char, 0, 1, 0)
                    "clear-count" () };
  bind "<shift>KP_Enter" { "begin-macro" ()
                           "movement" (first-char, 0, 1, 0)
                           "movement" (next-line, 1, 0, 0)
                           "movement" (next-line, 1, 0, 1)
                           "copy-clipboard-extended" ()
                           "delete-selection" ()
                           "movement" (first-nonspace-char, 0, 1, 0)
                           "clear-count" () };
  bind "Return" { "begin-macro" ()
                  "movement" (first-char, 0, 1, 0)
                  "movement" (next-line, 1, 0, 0)
                  "movement" (next-line, 1, 0, 1)
                  "copy-clipboard-extended" ()
                  "delete-selection" ()
                  "movement" (first-nonspace-char, 0, 1, 0)
                  "clear-count" () };
  bind "<shift>Return" { "begin-macro" ()
                         "movement" (first-char, 0, 1, 0)
                         "movement" (next-line, 1, 0, 0)
                         "movement" (next-line, 1, 0, 1)
                         "copy-clipboard-extended" ()
                         "delete-selection" ()
                         "movement" (first-nonspace-char, 0, 1, 0)
                         "clear-count" () };

  /* this is a count - 1 motion, we handle this specific case in C code */
  bind "underscore" { "begin-macro" ()
                      "movement" (first-char, 0, 1, 0)
                      "movement" (next-line, 1, 0, 0)
                      "movement" (next-line, 1, 0, 1)
                      "copy-clipboard-extended" ()
                      "delete-selection" ()
                      "movement" (first-nonspace-char, 0, 1, 0)
                      "clear-count" () };

  bind "b" { "begin-macro" ()
             "movement" (previous-word-start-newline-stop, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };

  bind "<shift>b" { "begin-macro" ()
                    "movement" (previous-full-word-start-newline-stop, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "end-macro" () };

  bind "e" { "begin-macro" ()
             "movement" (next-word-end-newline-stop, 1, 0, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "<shift>e" { "begin-macro" ()
                    "movement" (next-full-word-end-newline-stop, 1, 0, 1)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "end-macro" () };
  bind "w" { "begin-macro" ()
             "movement" (next-word-start-newline-stop, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "<shift>w" { "begin-macro" ()
                    "movement" (next-full-word-start-newline-stop, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "end-macro" () };
  bind "0" { "begin-macro" ()
             "movement" (first-char, 1, 0, 0)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "KP_0" { "begin-macro" ()
                "movement" (first-char, 1, 0, 0)
                "copy-clipboard-extended" ()
                "delete-selection" ()
                "end-macro" () };
  bind "<shift>asciicircum" { "begin-macro" ()
                              "movement" (first-nonspace-char, 1, 1, 1)
                              "copy-clipboard-extended" ()
                              "delete-selection" ()
                              "end-macro" () };
  bind "dollar" { "begin-macro" ()
                  "movement" (line-end, 1, 1, 0)
                  "copy-clipboard-extended" ()
                  "delete-selection" ()
                  "end-macro" () };
}

@binding-set builder-vim-source-view-normal-indent
{
  bind "greater" { "begin-macro" ()
                   "movement" (first-char, 0, 1, 0)
                   "movement" (line-end, 1, 1, 0)
                   "indent-selection" (1)
                   "clear-selection" ()
                   "movement" (first-nonspace-char, 0, 1, 0)
                   "end-macro" () };
  bind "less"    { "begin-macro" ()
                   "movement" (first-char, 0, 1, 0)
                   "movement" (line-end, 1, 1, 0)
                   "indent-selection" (-1)
                   "clear-selection" ()
                   "movement" (first-nonspace-char, 0, 1, 0)
                   "end-macro" () };
}

@binding-set builder-vim-source-view-normal-z
{
  bind "z" { "movement" (scroll-screen-center, 0, 0, 1) };
  bind "period" { "movement" (scroll-screen-center, 0, 1, 1) };

  bind "t" { "movement" (scroll-screen-top,    0, 0, 1) };
  bind "Return" { "movement" (scroll-screen-top, 0, 1, 1) };
  bind "KP_Enter" { "movement" (scroll-screen-top, 0, 1, 1) };

  bind "b" { "movement" (scroll-screen-bottom, 0, 0, 1) };
  bind "minus" { "movement" (scroll-screen-bottom, 0, 1, 1) };

  bind "l" { "movement" (screen-left, 0, 0, 1) };
  bind "Left" { "movement" (screen-left, 0, 0, 1) };

  bind "<shift>l" { "movement" (half-page-left, 0, 0, 1)
                    "clear-count" () };

  bind "h" { "movement" (screen-right, 0, 0, 1) };
  bind "Right" { "movement" (screen-right, 0, 0, 1) };

  bind "<shift>h" { "movement" (half-page-right, 0, 0, 1)
                    "clear-count" () };

  bind "s" { "movement" (scroll-screen-left, 0, 0, 1) };
  bind "e" { "movement" (scroll-screen-right, 0, 0, 1) };
}

@binding-set builder-vim-source-view-normal-Z
{
  bind "<shift>z" { "action" ("win", "save-all-quit", "") };
}

@binding-set builder-vim-source-view-visual-z
{
  bind "z" { "movement" (scroll-screen-center, 1, 0, 0)
             "set-mode" ("vim-visual", permanent) };
  bind "period" { "movement" (scroll-screen-center, 1, 1, 0)
                  "set-mode" ("vim-visual", permanent) };

  bind "t" { "movement" (scroll-screen-top, 1, 0, 0)
             "set-mode" ("vim-visual", permanent) };
  bind "Return" { "movement" (scroll-screen-top, 1, 1, 0)
                  "set-mode" ("vim-visual", permanent) };
  bind "KP_Enter" { "movement" (scroll-screen-top, 1, 1, 0)
                    "set-mode" ("vim-visual", permanent) };

  bind "b" { "movement" (scroll-screen-bottom, 1, 0, 0)
             "set-mode" ("vim-visual", permanent) };
  bind "minus" { "movement" (scroll-screen-bottom, 1, 1, 0)
                 "set-mode" ("vim-visual", permanent) };

  bind "l" { "movement" (screen-left, 1, 0, 1)
             "set-mode" ("vim-visual", permanent) };
  bind "Left" { "movement" (screen-left, 1, 0, 1)
                "set-mode" ("vim-visual", permanent) };

  bind "<shift>l" { "movement" (half-page-left, 1, 0, 1)
                    "set-mode" ("vim-visual", permanent) };

  bind "h" { "movement" (screen-right, 1, 0, 1)
             "set-mode" ("vim-visual", permanent) };
  bind "Right" { "movement" (screen-right, 1, 0, 1)
                 "set-mode" ("vim-visual", permanent) };

  bind "<shift>h" { "movement" (half-page-right, 1, 0, 1)
                    "set-mode" ("vim-visual", permanent) };

  bind "s" { "movement" (scroll-screen-left, 1, 0, 1)
             "set-mode" ("vim-visual", permanent) };
  bind "e" { "movement" (scroll-screen-right, 1, 0, 1)
             "set-mode" ("vim-visual", permanent) };
}

@binding-set builder-vim-source-view-visual-line-z
{
  bind "z" { "movement" (scroll-screen-center, 1, 0, 0)
             "set-mode" ("vim-visual-line", permanent) };
  bind "period" { "movement" (scroll-screen-center, 1, 1, 0)
                  "set-mode" ("vim-visual-line", permanent) };

  bind "t" { "movement" (scroll-screen-top, 1, 0, 0)
             "set-mode" ("vim-visual-line", permanent) };
  bind "Return" { "movement" (scroll-screen-top, 1, 1, 0)
                  "set-mode" ("vim-visual-line", permanent) };
  bind "KP_Enter" { "movement" (scroll-screen-top, 1, 1, 0)
                    "set-mode" ("vim-visual-line", permanent) };

  bind "b" { "movement" (scroll-screen-bottom, 1, 0, 0)
             "set-mode" ("vim-visual-line", permanent) };
  bind "minus" { "movement" (scroll-screen-bottom, 1, 1, 0)
                 "set-mode" ("vim-visual-line", permanent) };
}

@binding-set builder-vim-source-view-normal-y
{
  bind "y" { "save-insert-mark" ()
             "movement" (first-char, 0, 1, 0)
             "movement" (next-line, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-selection" ()
             "restore-insert-mark" () };

  bind "j" { "save-insert-mark" ()
             "movement" (line-end, 0, 1, 0)
             "movement" (first-char, 0, 1, 0)
             "movement" (next-line, 1, 0, 0)
             "movement" (next-line, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-selection" ()
             "restore-insert-mark" () };

  bind "k" { "movement" (line-end, 0, 0, 0)
             "movement" (previous-line, 1, 0, 0)
             "movement" (previous-line, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-selection" ()
             "movement" (first-nonspace-char, 0, 1, 0) };

  bind "w" { "save-insert-mark" ()
             "movement" (next-word-start, 1, 1, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "restore-insert-mark" ()
             "clear-count" () };

  bind "<shift>w" { "save-insert-mark" ()
                    "movement" (next-full-word-start, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (expand)
                    "restore-insert-mark" ()
                    "clear-count" () };

  bind "f" { "begin-macro" ()
             "save-insert-mark" ()
             "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-modifier" ()
             "restore-insert-mark" ()
             "clear-count" ()
             "end-macro" () };

  bind "t" { "begin-macro" ()
             "save-insert-mark" ()
             "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 1, 1, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-modifier" ()
             "restore-insert-mark" ()
             "clear-count" ()
             "end-macro" () };

  bind "i" { "set-mode" ("vim-normal-y-i", transient) };

  bind "dollar" { "begin-macro" ()
                  "save-insert-mark" ()
                  "movement" (line-end, 1, 1, 1)
                  "copy-clipboard-extended" ()
                  "selection-theatric" (expand)
                  "restore-insert-mark" ()
                  "clear-count" ()
                  "end-macro" () };
}

@binding-set builder-vim-source-view-normal-y-i
{
  bind "p" { "begin-macro" ()
             "movement" (paragraph-start, 1, 1, 1)
             "movement" (first-char, 1, 1, 0)
             "swap-selection-bounds" ()
             "movement" (paragraph-end, 1, 1, 1)
             "movement" (last-char, 1, 1, 0)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-selection" ()
             "end-macro" () };

  /* yiw */
  bind "w" { "begin-macro" ()
             "set-mode" ("vim-normal", permanent)
             "movement" (previous-word-end, 0, 1, 1)
             "movement" (next-word-start, 0, 1, 0)
             "movement" (next-word-end, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-selection" ()
             "end-macro" () };

  /* yiW */
  bind "<shift>w" { "begin-macro" ()
                    "set-mode" ("vim-normal", permanent)
                    "movement" (previous-full-word-end, 0, 1, 1)
                    "movement" (next-full-word-start, 0, 1, 0)
                    "movement" (next-full-word-end, 1, 0, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (expand)
                    "clear-selection" ()
                    "end-macro" () };

  /* yi( , yi) , yib */
  bind "parenleft" { "begin-macro" ()
                     "select-inner" ("(", ")", 1, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (expand)
                     "clear-selection" ()
                     "end-macro" () };

  bind "parenright" { "begin-macro" ()
                      "select-inner" ("(", ")", 1, 0)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (expand)
                      "clear-selection" ()
                      "end-macro" () };

  bind "b" { "begin-macro" ()
             "select-inner" ("(", ")", 1, 0)
             "set-mode" ("vim-normal", permanent)
             "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-selection" ()
             "end-macro" () };

  /* yi[ and yi] */
  bind "bracketleft" { "begin-macro" ()
                       "select-inner" ("[", "]", 1, 0)
                       "set-mode" ("vim-normal", permanent)
                       "copy-clipboard-extended" ()
                       "selection-theatric" (expand)
                       "clear-selection" ()
                       "end-macro" () };

  bind "bracketright" { "begin-macro" ()
                        "select-inner" ("[", "]", 1, 0)
                        "set-mode" ("vim-normal", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (expand)
                        "clear-selection" ()
                        "end-macro" () };

  /* yi{ , yi} , yiB */
  bind "braceleft" { "begin-macro" ()
                     "select-inner" ("{", "}", 1, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (expand)
                     "end-macro" () };

  bind "braceright" { "begin-macro" ()
                      "select-inner" ("{", "}", 1, 0)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (expand)
                      "end-macro" () };

  bind "<shift>b" { "begin-macro" ()
                    "select-inner" ("{", "}", 1, 0)
                    "set-mode" ("vim-normal", permanent)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (expand)
                    "end-macro" () };

  /* yi< and yi> */
  bind "less" { "begin-macro" ()
                "select-inner" ("<", ">", 1, 0)
                "set-mode" ("vim-normal", permanent)
                "copy-clipboard-extended" ()
                "selection-theatric" (expand)
                "end-macro" () };

  bind "greater" { "begin-macro" ()
                   "select-inner" ("<", ">", 1, 0)
                   "set-mode" ("vim-normal", permanent)
                   "copy-clipboard-extended" ()
                   "selection-theatric" (expand)
                   "end-macro" () };

  /* yi" yi' yi` */
  bind "quotedbl" { "begin-macro" ()
                    "select-inner" ("\"", "\"", 1, 1)
                    "set-mode" ("vim-normal", permanent)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (expand)
                    "end-macro" () };

  bind "apostrophe" { "begin-macro" ()
                      "select-inner" ("'", "'", 1, 1)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (expand)
                      "end-macro" () };

  bind "grave" { "begin-macro" ()
                 "select-inner" ("`", "`", 1, 1)
                 "set-mode" ("vim-normal", permanent)
                 "copy-clipboard-extended" ()
                 "selection-theatric" (expand)
                 "end-macro" () };

  /* yit */
  bind "t" { "begin-macro" ()
              "select-tag" (1)
              "set-mode" ("vim-normal", permanent)
              "copy-clipboard-extended" ()
              "selection-theatric" (expand)
              "end-macro" () };
}


@binding-set builder-vim-source-view-normal-g
{
  bind "<shift>i" { "set-mode" ("vim-insert", permanent)
                    "movement" (first-char, 0, 1, 0) };
  bind "d" { "goto-definition" () };
  bind "e" { "movement" (previous-word-end, 0, 1, 1) };
  bind "<shift>e" { "movement" (previous-full-word-end, 0, 1, 1) };
  bind "g" { "movement" (first-line, 0, 1, 0 ) };
  bind "j" { "movement" (next-line, 0, 1, 1) };

  /* todo: this should actually be screen middle. this does middle of the text width */
  bind "m" { "movement" (middle-char, 0, 1, 0) };

  bind "u"        { "set-mode" ("vim-normal-g-u", transient) };
  bind "<shift>u" { "set-mode" ("vim-normal-g-u", transient) };

  /* cycle "tabs" */
  bind "<shift>t" { "action" ("frame", "previous-page", "") };
  bind "t" { "action" ("frame", "next-page", "") };
  bind "q" { "format-selection" () };
}

@binding-set builder-vim-source-view-normal-g-u
{
  bind "u" { "begin-macro" ()
             "movement" (first-char, 0, 1, 0)
             "movement" (next-line, 1, 0, 1)
             "swap-selection-bounds" ()
             "selection-theatric" (expand)
             "change-case" (lower)
             "clear-selection" ()
             "movement" (first-nonspace-char, 0, 1, 0)
             "end-macro" () };

  bind "<shift>u" { "begin-macro" ()
                    "movement" (first-char, 0, 1, 0)
                    "movement" (next-line, 1, 0, 1)
                    "swap-selection-bounds" ()
                    "selection-theatric" (expand)
                    "change-case" (upper)
                    "clear-selection" ()
                    "movement" (first-nonspace-char, 0, 1, 0)
                    "end-macro" () };
}

@binding-set builder-vim-source-view-normal-d-g
{
  bind "e" { "begin-macro" ()
             "movement" (previous-word-end, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "<shift>e" { "begin-macro" ()
                    "movement" (previous-full-word-end, 1, 1, 1)
                    "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "end-macro" () };
  bind "g" { "begin-macro" ()
             "movement" (first-line, 1, 1, 0)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "k" { "begin-macro" ()
             "movement" (next-char, 1, 1, 0)
             "movement" (previous-line, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "j" { "begin-macro" ()
             "movement" (next-char, 1, 1, 0)
             "movement" (next-line, 1, 1, 1)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
  bind "m" { "begin-macro" ()
             "movement" (middle-char, 1, 1, 0)
             "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" () };
}

@binding-set builder-vim-source-view-normal-d-i
{
  bind "p" { "begin-macro" ()
             "movement" (paragraph-start, 1, 1, 1)
             "movement" (first-char, 1, 1, 0)
             "swap-selection-bounds" ()
             "movement" (paragraph-end, 1, 1, 1)
             "movement" (last-char, 1, 1, 0)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" ()
             "end-macro" () };

  /* diw */
  bind "w" { "begin-macro" ()
             "set-mode" ("vim-normal", permanent)
             "movement" (previous-word-end, 0, 1, 1)
             "movement" (next-word-start, 0, 1, 0)
             "movement" (next-word-end, 1, 0, 1)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* diW */
  bind "<shift>w" { "begin-macro" ()
                    "set-mode" ("vim-normal", permanent)
                    "movement" (previous-full-word-end, 0, 1, 1)
                    "movement" (next-full-word-start, 0, 1, 0)
                    "movement" (next-full-word-end, 1, 0, 1)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" () };

  /* di( , di) , dib */
  bind "parenleft" { "begin-macro" ()
                     "select-inner" ("(", ")", 1, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "parenright" { "begin-macro" ()
                      "select-inner" ("(", ")", 1, 0)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "b" { "begin-macro" ()
             "select-inner" ("(", ")", 1, 0)
             "set-mode" ("vim-normal", permanent)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* di[ and di] */
  bind "bracketleft" { "begin-macro" ()
                       "select-inner" ("[", "]", 1, 0)
                       "set-mode" ("vim-normal", permanent)
                       "copy-clipboard-extended" ()
                       "selection-theatric" (shrink)
                       "delete-selection" () };

  bind "bracketright" { "begin-macro" ()
                        "select-inner" ("[", "]", 1, 0)
                        "set-mode" ("vim-normal", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

  /* di{ , di} , diB */
  bind "braceleft" { "begin-macro" ()
                     "select-inner" ("{", "}", 1, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "braceright" { "begin-macro" ()
                      "select-inner" ("{", "}", 1, 0)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "<shift>b" { "begin-macro" ()
                    "select-inner" ("{", "}", 1, 0)
                    "set-mode" ("vim-normal", permanent)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" () };

  /* di< and di> */
    bind "less" { "begin-macro" ()
                  "select-inner" ("<", ">", 1, 0)
                  "set-mode" ("vim-normal", permanent)
                  "copy-clipboard-extended" ()
                  "selection-theatric" (shrink)
                  "delete-selection" () };

    bind "greater" { "begin-macro" ()
                     "select-inner" ("<", ">", 1, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  /* di" di' di` */
    bind "quotedbl" { "begin-macro" ()
                      "select-inner" ("\"", "\"", 1, 1)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

    bind "apostrophe" { "begin-macro" ()
                        "select-inner" ("'", "'", 1, 1)
                        "set-mode" ("vim-normal", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

    bind "grave" { "begin-macro" ()
                   "select-inner" ("`", "`", 1, 1)
                   "set-mode" ("vim-normal", permanent)
                   "copy-clipboard-extended" ()
                   "selection-theatric" (shrink)
                   "delete-selection" () };

  /* dit */
    bind "t" { "begin-macro" ()
               "select-tag" (1)
               "set-mode" ("vim-normal", permanent)
               "copy-clipboard-extended" ()
               "selection-theatric" (shrink)
               "delete-selection" () };
}

@binding-set builder-vim-source-view-normal-d-a
{
  /* da( , da) , dab */
  bind "parenleft" { "begin-macro" ()
                     "select-inner" ("(", ")", 0, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "parenright" { "begin-macro" ()
                      "select-inner" ("(", ")", 0, 0)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "b" { "begin-macro" ()
             "select-inner" ("(", ")", 0, 0)
             "set-mode" ("vim-normal", permanent)
             "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" () };

  /* da[ and da] */
  bind "bracketleft" { "begin-macro" ()
                       "select-inner" ("[", "]", 0, 0)
                       "set-mode" ("vim-normal", permanent)
                       "copy-clipboard-extended" ()
                       "selection-theatric" (shrink)
                       "delete-selection" () };

  bind "bracketright" { "begin-macro" ()
                        "select-inner" ("[", "]", 0, 0)
                        "set-mode" ("vim-normal", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

  /* da{ , da} , daB */
  bind "braceleft" { "begin-macro" ()
                     "select-inner" ("{", "}", 0, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  bind "braceright" { "begin-macro" ()
                      "select-inner" ("{", "}", 0, 0)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

  bind "<shift>b" { "begin-macro" ()
                    "select-inner" ("{", "}", 0, 0)
                    "set-mode" ("vim-normal", permanent)
                    "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" () };

  /* da< and da> */
    bind "less" { "begin-macro" ()
                  "select-inner" ("<", ">", 0, 0)
                  "set-mode" ("vim-normal", permanent)
                  "copy-clipboard-extended" ()
                  "selection-theatric" (shrink)
                  "delete-selection" () };

    bind "greater" { "begin-macro" ()
                     "select-inner" ("<", ">", 0, 0)
                     "set-mode" ("vim-normal", permanent)
                     "copy-clipboard-extended" ()
                     "selection-theatric" (shrink)
                     "delete-selection" () };

  /* da" da' da` */
    bind "quotedbl" { "begin-macro" ()
                      "select-inner" ("\"", "\"", 0, 1)
                      "set-mode" ("vim-normal", permanent)
                      "copy-clipboard-extended" ()
                      "selection-theatric" (shrink)
                      "delete-selection" () };

    bind "apostrophe" { "begin-macro" ()
                        "select-inner" ("'", "'", 0, 1)
                        "set-mode" ("vim-normal", permanent)
                        "copy-clipboard-extended" ()
                        "selection-theatric" (shrink)
                        "delete-selection" () };

    bind "grave" { "begin-macro" ()
                   "select-inner" ("`", "`", 0, 1)
                   "set-mode" ("vim-normal", permanent)
                   "copy-clipboard-extended" ()
                   "selection-theatric" (shrink)
                   "delete-selection" () };

  /* dat */
    bind "t" { "begin-macro" ()
               "select-tag" (0)
               "set-mode" ("vim-normal", permanent)
               "copy-clipboard-extended" ()
               "selection-theatric" (shrink)
               "delete-selection" () };
}

@binding-set builder-vim-source-view-visual-g
{
  bind "e" { "movement" (previous-word-end, 1, 1, 0)
             "set-mode" ("vim-visual", permanent) };
  bind "<shift>e" { "movement" (previous-full-word-end, 1, 1, 0)
                    "set-mode" ("vim-visual", permanent) };
  bind "g" { "movement" (first-line, 1, 1, 0)
             "set-mode" ("vim-visual", permanent) };
  bind "j" { "movement" (next-line, 1, 1, 0)
             "set-mode" ("vim-visual", permanent) };
  bind "m" { "movement" (middle-char, 1, 1, 0)
             "set-mode" ("vim-visual", permanent) };
}

@binding-set builder-vim-source-view-normal-q
{
  /* this is wrong, you can store in any character for recording and then
   * replay with @char.
   */
  bind "q" { "begin-macro" () };
}

@binding-set builder-vim-source-view-normal-ctrl-w
{
  bind "v" { "action" ("frame", "open-in-new-frame", "''") "grab_focus" () };
  bind "<Control>v" { "action" ("frame", "open-in-new-frame", "''") "grab_focus" () };

  bind "c" { "action" ("frame", "close-page", "") };
  bind "<Control>c" { "action" ("frame", "close-page", "") };

  bind "s" { "action" ("frame", "split-page", "''") };
  bind "<Control>s" { "action" ("frame", "split-page", "''") };

  bind "w" { "action" ("grid", "focus-neighbor", "0") };
  bind "<Control>w" { "action" ("grid", "focus-neighbor", "0") };

  bind "l" { "action" ("grid", "focus-neighbor", "5") };
  bind "Right" { "action" ("grid", "focus-neighbor", "5") };

  bind "h" { "action" ("grid", "focus-neighbor", "4") };
  bind "Left" { "action" ("grid", "focus-neighbor", "4") };

  bind "j" { "action" ("grid", "focus-neighbor", "3") };
  bind "Down" { "action" ("grid", "focus-neighbor", "3") };

  bind "k" { "action" ("grid", "focus-neighbor", "2") };
  bind "Up" { "action" ("grid", "focus-neighbor", "2") };
}

@binding-set builder-vim-source-view-visual-line-g
{
  /* XXX: This is a bit of a hack to just reuse the special
   *      line handling case to wrap around our first selected
   *      line. Otherwise, we lose that line. This type of stuff
   *      really belongs in a special case keybinding context
   *      once that subsystem lands.
   */
  bind "g" { "clear-count" ()
             "append-to-count" (1)
             "append-to-count" (0)
             "append-to-count" (0)
             "append-to-count" (0)
             "append-to-count" (0)
             "append-to-count" (0)
             "append-to-count" (0)
             "append-to-count" (0)
             "movement" (previous-line, 1, 0, 1)
             "set-mode" ("vim-visual-line", permanent) };
  bind "j" { "movement" (next-line, 1, 1, 0)
             "set-mode" ("vim-visual-line", permanent) };
  bind "k" { "movement" (next-line, 1, 1, 0)
             "set-mode" ("vim-visual-line", permanent) };

  bind "q" { "format-selection" () };
}

@binding-set builder-vim-source-view-insert
{
  bind "<ctrl>u" { "movement" (line-chars, 1, 1, 0)
                   "delete-selection" () };
  bind "<ctrl>w" { "movement" (previous-word-start, 1, 1, 0)
                   "delete-selection" () };

  bind "<ctrl>d" { "save-insert-mark" ()
                   "movement" (first-nonspace-char, 0, 1, 0)
                   "movement" (line-end, 1, 1, 0)
                   "begin-user-action" ()
                   "indent-selection" (-1)
                   "end-user-action" ()
                   "restore-insert-mark" () };
  bind "<ctrl>t" { "save-insert-mark" ()
                   "movement" (first-nonspace-char, 0, 1, 0)
                   "movement" (line-end, 1, 1, 0)
                   "begin-user-action" ()
                   "indent-selection" (1)
                   "end-user-action" ()
                   "restore-insert-mark" () };

  bind "<ctrl>e" { "movement" (screen-up, 0, 0, 1) };
  bind "<ctrl>y" { "movement" (screen-down, 0, 0, 1) };

  bind "<ctrl>n" { "cycle-completion" (down) };
  bind "<ctrl>p" { "cycle-completion" (up) };

  /* raw keycode (to some degree) */
  bind "<ctrl>v" { "capture-modifier" ()
                   "insert-modifier" (0)
                   "clear-modifier" () };

  bind "Escape" { "end-macro" ()
                  "set-overwrite" (0)
                  "clear-count" ()
                  "clear-selection" ()
                  "clear-snippets" ()
                  "hide-completion" ()
                  "movement" (previous-char, 0, 1, 0)
                  "set-mode" ("vim-normal", permanent) 
                  "remove-cursors" () };
  bind "<ctrl>bracketleft" { "end-macro" ()
                             "set-overwrite" (0)
                             "clear-count" ()
                             "clear-selection" ()
                             "clear-snippets" ()
                             "hide-completion" ()
                             "movement" (previous-char, 0, 1, 0)
                             "set-mode" ("vim-normal", permanent) };

  /* Add back emoji */
  bind "<ctrl>semicolon" { "insert-emoji" () };
}

@binding-set builder-vim-source-view-visual-with-count
{
  bind "0" { "append-to-count" (0)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "KP_0" { "append-to-count" (0)
                "set-mode" ("vim-visual-with-count", transient) };
  bind "percent" { "movement" (line-percentage, 1, 1, 1)
                   "set-mode" ("vim-visual-with-count", transient) };
}

@binding-set builder-vim-source-view-visual
{
  bind "i" { "set-mode" ("vim-visual-i", transient) };
  bind "a" { "set-mode" ("vim-visual-a", transient) };

  bind "colon" { "action" ("win", "reveal-command-bar", "") };

  bind "percent" { "move-to-matching-bracket" (1) };

  bind "1" { "append-to-count" (1)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "2" { "append-to-count" (2)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "3" { "append-to-count" (3)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "4" { "append-to-count" (4)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "5" { "append-to-count" (5)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "6" { "append-to-count" (6)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "7" { "append-to-count" (7)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "8" { "append-to-count" (8)
             "set-mode" ("vim-visual-with-count", transient) };
  bind "9" { "append-to-count" (9)
             "set-mode" ("vim-visual-with-count", transient) };

  bind "x" { "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" ()
             "set-mode" ("vim-normal", permanent) };

  bind "c" { "copy-clipboard-extended" ()
             "selection-theatric" (shrink)
             "delete-selection" ()
             "set-mode" ("vim-insert", permanent) };

  bind "d" { "copy-clipboard-extended" ()
             "delete-selection" ()
             "end-macro" ()
             "set-mode" ("vim-normal", permanent) };

  bind "<shift>x" { "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "h" { "movement" (previous-char, 1, 1, 1) };
  bind "l" { "movement" (next-char, 1, 1, 1) };
  bind "k" { "movement" (previous-line, 1, 1, 1) };
  bind "j" { "movement" (next-line, 1, 1, 1) };

  bind "p" { "begin-macro" ()
             "delete-selection" ()
             "paste-clipboard-extended" (1, 0, 0)
             "movement" (previous-char, 0, 1, 0)
             "clear-count" ()
             "end-macro" ()
             "set-mode" ("vim-normal", permanent) };
  bind "<shift>p" { "begin-macro" ()
                    "delete-selection" ()
                    "paste-clipboard-extended" (1, 0, 0)
                    "movement" (previous-char, 0, 1, 0)
                    "clear-count" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "Left" { "movement" (previous-char, 1, 1, 1) };
  bind "Right" { "movement" (next-char, 1, 1, 1) };
  bind "Up" { "movement" (previous-line, 1, 1, 1) };
  bind "Down" { "movement" (next-line, 1, 1, 1) };

  bind "BackSpace" { "movement" (previous-offset, 1, 1, 1)
                     "clear-count" () };
  bind "space" { "movement" (next-offset, 1, 1, 1)
                 "clear-count" () };

  bind "equal" { "reindent" ()
                 "set-mode" ("vim-normal", permanent) };

  /* TODO: we really want to rollback the macro here */
  bind "y" { "copy-clipboard-extended" ()
             "selection-theatric" (expand)
             "clear-selection" ()
             "end-macro" ()
             "set-mode" ("vim-normal", permanent) };

  bind "slash" { "set-search-text" ("", 1)
                 "action" ("editor-page", "find", "") };

  bind "e" { "movement" (next-word-end, 1, 0, 1) };
  bind "<shift>e" { "movement" (next-full-word-end, 1, 0, 1) };

  bind "w" { "movement" (next-word-start, 1, 1, 1) };
  bind "<shift>w" { "movement" (next-full-word-start, 1, 1, 1) };
  bind "b" { "movement" (previous-word-start, 1, 1, 1) };
  bind "<shift>b" { "movement" (previous-full-word-start, 1, 1, 1) };

  bind "n" { "move-search" (tab-forward, 1, 0, 1, 1, 0) };
  bind "<shift>n" { "move-search" (tab-backward, 1, 0, 0, 1, 0) };

  bind "numbersign" { "save-insert-mark" ()
                      "movement" (previous-word-end, 0, 1, 1)
                      "movement" (next-word-start, 0, 1, 0)
                      "movement" (next-word-end, 1, 0, 1)
                      "set-search-text" ("", 1)
                      "restore-insert-mark" ()
                      "move-search" (up, 1, 0, 0, 1, 1) };

  bind "asterisk" { "save-insert-mark" ()
                    "movement" (previous-word-end, 0, 1, 1)
                    "movement" (next-word-start, 0, 1, 0)
                    "movement" (next-word-end, 1, 0, 1)
                    "set-search-text" ("", 1)
                    "restore-insert-mark" ()
                    "move-search" (down, 1, 0, 1, 1, 1) };

bind "KP_Multiply" { "save-insert-mark" ()
                     "movement" (previous-word-end, 0, 1, 1)
                     "movement" (next-word-start, 0, 1, 0)
                     "movement" (next-word-end, 1, 0, 1)
                     "set-search-text" ("", 1)
                     "restore-insert-mark" ()
                     "move-search" (down, 1, 0, 1, 1, 1) };

  bind "<ctrl>b" { "movement" (page-up, 1, 0, 1) };
  bind "Page_Up" { "movement" (page-up, 1, 0, 1) };
  bind "<ctrl>f" { "movement" (page-down, 1, 0, 1) };
  bind "Page_Down" { "movement" (page-down, 1, 0, 1) };
  bind "<ctrl>u" { "movement" (half-page-up, 1, 0, 1) };
  bind "<ctrl>d" { "movement" (half-page-down, 1, 0, 1) };

  bind "greater" { "indent-selection" (1)
                   "movement" (first-nonspace-char, 0, 1, 0)
                   "end-macro" ()
                   "set-mode" ("vim-normal", permanent) };
  bind "less" { "indent-selection" (-1)
                "movement" (first-nonspace-char, 0, 1, 0)
                "end-macro" ()
                "set-mode" ("vim-normal", permanent) };

  bind "0" { "movement" (first-char, 1, 1, 0) };
  bind "KP_0" { "movement" (first-char, 1, 1, 0) };
  bind "Home" { "movement" (first-char, 1, 1, 0) };
  bind "asciicircum" { "movement" (first-nonspace-char, 1, 0, 0) };
  bind "dollar" { "movement" (last-char, 1, 0, 0) };
  bind "End" { "movement" (last-char, 1, 0, 0) };
  bind "bar" { "movement" (nth-char, 1, 1, 1) };

  bind "<shift>h" { "movement" (screen-top, 1, 0, 0) };
  bind "<shift>m" { "movement" (screen-middle, 1, 0, 0) };
  bind "<shift>l" { "movement" (screen-bottom, 1, 0, 0) };

  bind "braceleft" { "movement" (paragraph-start, 1, 1, 1) };
  bind "braceright" { "movement" (paragraph-end, 1, 1, 1) };

  bind "parenleft" { "movement" (sentence-start, 1, 1, 1) };
  bind "parenright" { "movement" (sentence-end, 1, 1, 1) };

  bind "<ctrl>e" { "movement" (screen-up, 1, 0, 1) };
  bind "<ctrl>y" { "movement" (screen-down, 1, 0, 1) };

  bind "<shift>j" { "join-lines" ()
                    "selection-theatric" (expand)
                    "clear-selection" ()
                    "movement" (last-char, 0, 1, 0)
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "g" { "set-mode" ("vim-visual-g", transient) };
  bind "z" { "set-mode" ("vim-visual-z", transient) };

  bind "f" { "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 1, 0, 1)
             "clear-modifier" () };
  bind "t" { "save-command" ()
             "capture-modifier" ()
             "save-search-char" ()
             "movement" (next-match-modifier, 1, 1, 1)
             "clear-modifier" () };

  bind "<shift>f" { "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "movement" (previous-match-modifier, 1, 1, 1)
                    "clear-modifier" () };
  bind "<shift>t" { "save-command" ()
                    "capture-modifier" ()
                    "save-search-char" ()
                    "movement" (previous-match-modifier, 1, 0, 1)
                    "clear-modifier" () };
  bind "comma" { "movement" (previous-match-search-char, 1, 0, 1)
                 "clear-count" () };
  bind "semicolon" { "movement" (next-match-search-char, 1, 0, 1)
                     "clear-count" () };

  bind "asciitilde" { "selection-theatric" (expand)
                      "change-case" (toggle)
                      "clear-selection" ()
                      "end-macro" ()
                      "set-mode" ("vim-normal", permanent) };
  bind "u" { "selection-theatric" (expand)
             "change-case" (lower)
             "clear-selection" ()
             "end-macro" ()
             "set-mode" ("vim-normal", permanent) };
  bind "<shift>u" { "selection-theatric" (expand)
                    "change-case" (upper)
                    "clear-selection" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "plus" { "begin-macro" ()
                "movement" (next-line, 1, 0, 1)
                "movement" (first-nonspace-char, 1, 1, 0)
                "clear-count" () };
  bind "KP_Enter" { "begin-macro" ()
                    "movement" (next-line, 1, 0, 1)
                    "movement" (first-nonspace-char, 1, 1, 0)
                    "clear-count" () };
  bind "<shift>KP_Enter" { "begin-macro" ()
                           "movement" (next-line, 1, 0, 1)
                           "movement" (first-nonspace-char, 1, 1, 0)
                           "clear-count" () };
  bind "Return" { "begin-macro" ()
                  "movement" (next-line, 1, 0, 1)
                  "movement" (first-nonspace-char, 1, 1, 0)
                  "clear-count" () };
  bind "<shift>Return" { "begin-macro" ()
                         "movement" (next-line, 1, 0, 1)
                         "movement" (first-nonspace-char, 1, 1, 0)
                         "clear-count" () };

  /* this is a count - 1 motion, we handle this specific case in C code */
  bind "underscore" { "begin-macro" ()
                      "movement" (next-line, 1, 0, 1)
                      "movement" (first-nonspace-char, 1, 1, 0)
                      "clear-count" () };
}

@binding-set builder-vim-source-view-visual-i
{
  /* vi( , vi) , vib */
  bind "parenleft" { "begin-macro" ()
                     "select-inner" ("(", ")", 1, 0)
                     "set-mode" ("vim-visual", permanent) };

  bind "parenright" { "begin-macro" ()
                      "select-inner" ("(", ")", 1, 0)
                      "set-mode" ("vim-visual", permanent) };

  bind "b" { "begin-macro" ()
             "select-inner" ("(", ")", 1, 0)
             "set-mode" ("vim-visual", permanent) };

  /* vi[ and vi] */
  bind "bracketleft" { "begin-macro" ()
                       "select-inner" ("[", "]", 1, 0)
                       "set-mode" ("vim-visual", permanent) };

  bind "bracketright" { "begin-macro" ()
                        "select-inner" ("[", "]", 1, 0)
                        "set-mode" ("vim-visual", permanent) };

  /* vi{ , vi} , viB */
  bind "braceleft" { "begin-macro" ()
                     "select-inner" ("{", "}", 1, 0)
                     "set-mode" ("vim-visual", permanent) };

  bind "braceright" { "begin-macro" ()
                      "select-inner" ("{", "}", 1, 0)
                      "set-mode" ("vim-visual", permanent) };

  bind "<shift>b" { "begin-macro" ()
                    "select-inner" ("{", "}", 1, 0)
                    "set-mode" ("vim-visual", permanent) };

  /* vi< and vi> */
  bind "less" { "begin-macro" ()
                "select-inner" ("<", ">", 1, 0)
                "set-mode" ("vim-visual", permanent) };

  bind "greater" { "begin-macro" ()
                   "select-inner" ("<", ">", 1, 0)
                   "set-mode" ("vim-visual", permanent) };

  /* vi" vi' vi` */
  bind "quotedbl" { "begin-macro" ()
                    "select-inner" ("\"", "\"", 1, 1)
                    "set-mode" ("vim-visual", permanent) };

  bind "apostrophe" { "begin-macro" ()
                        "select-inner" ("'", "'", 1, 1)
                        "set-mode" ("vim-visual", permanent) };

  bind "grave" { "begin-macro" ()
                 "select-inner" ("`", "`", 1, 1)
                 "set-mode" ("vim-visual", permanent) };

   /* vit */
  bind "t" { "begin-macro" ()
              "select-tag" (1)
              "set-mode" ("vim-visual", permanent) };
}

@binding-set builder-vim-source-view-visual-a
{
  /* va( , va) , vab */
  bind "parenleft" { "begin-macro" ()
                     "select-inner" ("(", ")", 0, 0)
                     "set-mode" ("vim-visual", permanent) };

  bind "parenright" { "begin-macro" ()
                      "select-inner" ("(", ")", 0, 0)
                      "set-mode" ("vim-visual", permanent) };

  bind "b" { "begin-macro" ()
             "select-inner" ("(", ")", 0, 0)
             "set-mode" ("vim-visual", permanent) };

  /* va[ and va] */
  bind "bracketleft" { "begin-macro" ()
                       "select-inner" ("[", "]", 0, 0)
                       "set-mode" ("vim-visual", permanent) };

  bind "bracketright" { "begin-macro" ()
                        "select-inner" ("[", "]", 0, 0)
                        "set-mode" ("vim-visual", permanent) };

  /* va{ , va} , vaB */
  bind "braceleft" { "begin-macro" ()
                     "select-inner" ("{", "}", 0, 0)
                     "set-mode" ("vim-visual", permanent) };

  bind "braceright" { "begin-macro" ()
                      "select-inner" ("{", "}", 0, 0)
                      "set-mode" ("vim-visual", permanent) };

  bind "<shift>b" { "begin-macro" ()
                    "select-inner" ("{", "}", 0, 0)
                    "set-mode" ("vim-visual", permanent) };

  /* va< and va> */
    bind "less" { "begin-macro" ()
                  "select-inner" ("<", ">", 0, 0)
                  "set-mode" ("vim-visual", permanent) };

    bind "greater" { "begin-macro" ()
                     "select-inner" ("<", ">", 0, 0)
                     "set-mode" ("vim-visual", permanent) };

  /* va" va' va` */
    bind "quotedbl" { "begin-macro" ()
                      "select-inner" ("\"", "\"", 0, 1)
                      "set-mode" ("vim-visual", permanent) };

    bind "apostrophe" { "begin-macro" ()
                        "select-inner" ("'", "'", 0, 1)
                        "set-mode" ("vim-visual", permanent) };

    bind "grave" { "begin-macro" ()
                   "select-inner" ("`", "`", 0, 1)
                   "set-mode" ("vim-visual", permanent) };

  /* vat */
    bind "t" { "begin-macro" ()
               "select-tag" (0)
               "set-mode" ("vim-visual", permanent) };
}

@binding-set builder-vim-source-view-visual-line-with-count
{
  bind "0" { "append-to-count" (0)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "KP_0" { "append-to-count" (0)
                "set-mode" ("vim-visual-line-with-count", transient) };
  bind "percent" { "movement" (line-percentage, 0, 1, 1)
                   "set-mode" ("vim-visual-line-with-count", transient) };
}

@binding-set builder-vim-source-view-visual-line
{
  bind "colon" { "action" ("win", "reveal-command-bar", "") };

  bind "1" { "append-to-count" (1)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "2" { "append-to-count" (2)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "3" { "append-to-count" (3)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "4" { "append-to-count" (4)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "5" { "append-to-count" (5)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "6" { "append-to-count" (6)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "7" { "append-to-count" (7)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "8" { "append-to-count" (8)
             "set-mode" ("vim-visual-line-with-count", transient) };
  bind "9" { "append-to-count" (9)
             "set-mode" ("vim-visual-line-with-count", transient) };

  bind "k" { "movement" (previous-line, 1, 0, 1) };
  bind "j" { "movement" (next-line, 1, 0, 1) };

  bind "g" { "set-mode" ("vim-visual-line-g", transient ) };

  /* just to be nice */
  bind "h" { "end-macro" ()
             "clear-selection" ()
             "set-mode" ("vim-normal", permanent) };
  bind "l" { "end-macro" ()
             "clear-selection" ()
             "set-mode" ("vim-normal", permanent) };

  bind "p" { "begin-macro" ()
             "delete-selection" ()
             "paste-clipboard-extended" (1, 0, 0)
             "movement" (previous-char, 0, 1, 0)
             "clear-count" ()
             "end-macro" ()
             "set-mode" ("vim-normal", permanent) };
  bind "<shift>p" { "begin-macro" ()
                    "delete-selection" ()
                    "paste-clipboard-extended" (1, 0, 0)
                    "movement" (previous-char, 0, 1, 0)
                    "clear-count" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "Up" { "movement" (previous-line, 1, 0, 1) };
  bind "Down" { "movement" (next-line, 1, 0, 1) };

  bind "equal" { "reindent" ()
                 "set-mode" ("vim-normal", permanent) };

  bind "z" { "set-mode" ("vim-visual-line-z", transient) };

  bind "<shift>g" { "movement" (nth-line, 1, 0, 1)
                    "movement" (last-char, 1, 0, 0) };

  bind "x"        { "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "d"        { "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "c"        { "copy-clipboard-extended" ()
                    "selection-theatric" (shrink)
                    "delete-selection" ()
                    "set-mode" ("vim-insert", permanent)
                    "insert-at-cursor" ("\n")
                    "move-cursor" (display-lines, -1, 0)
                    "reindent" () };

  bind "<shift>x" { "copy-clipboard-extended" ()
                    "delete-selection" ()
                    "delete-from-cursor" (chars, 1)
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  /* TODO: this should actually cancel the macro */
  bind "y"        { "copy-clipboard-extended" ()
                    "selection-theatric" (expand)
                    "clear-selection" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  /* TODO: this should actually cancel the macro */
  bind "<shift>y" { "copy-clipboard-extended" ()
                    "selection-theatric" (expand)
                    "clear-selection" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "<shift>j" { "join-lines" ()
                    "selection-theatric" (expand)
                    "clear-selection" ()
                    "movement" (last-char, 0, 1, 0)
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };

  bind "asciitilde" { "selection-theatric" (expand)
                      "change-case" (toggle)
                      "clear-selection" ()
                      "end-macro" ()
                      "set-mode" ("vim-normal", permanent) };

  bind "<shift>u" { "selection-theatric" (expand)
                    "change-case" (upper)
                    "clear-selection" ()
                    "end-macro" ()
                    "set-mode" ("vim-normal", permanent) };
  bind "u" { "selection-theatric" (expand)
             "change-case" (lower)
             "clear-selection" ()
             "end-macro" ()
             "set-mode" ("vim-normal", permanent) };

  bind "braceleft" { "movement" (paragraph-start, 1, 1, 1)
                     "movement" (last-char, 1, 1, 0) };
  bind "braceright" { "movement" (paragraph-end, 1, 1, 1)
                      "movement" (last-char, 1, 1, 0) };

  bind "parenleft" { "movement" (sentence-start, 1, 1, 1)
                     "movement" (last-char, 1, 1, 0) };
  bind "parenright" { "movement" (sentence-end, 1, 1, 1)
                      "movement" (last-char, 1, 1, 0) };

  bind "greater" { "save-insert-mark" ()
                   "indent-selection" (1)
                   "clear-selection" ()
                   "movement" (first-nonspace-char, 0, 1, 0)
                   "restore-insert-mark" ()
                   "movement" (first-nonspace-char, 0, 1, 0)
                   "end-macro" ()
                   "set-mode" ("vim-normal", permanent) };
  bind "less" { "save-insert-mark" ()
                "indent-selection" (-1)
                "clear-selection" ()
                "movement" (first-nonspace-char, 0, 1, 0)
                "restore-insert-mark" ()
                "movement" (first-nonspace-char, 0, 1, 0)
                "end-macro" ()
                "set-mode" ("vim-normal", permanent) };

  bind "<ctrl>e" { "movement" (screen-up, 1, 0, 1) };
  bind "<ctrl>y" { "movement" (screen-down, 1, 0, 1) };

  /* page movements */
  bind "<ctrl>b" { "movement" (page-up-lines, 1, 0, 1)
                   "clear-count" () };
  bind "Page_Up" { "movement" (page-up-lines, 1, 0, 1)
                   "clear-count" () };
  bind "<ctrl>f" { "movement" (page-down-lines, 1, 0, 1)
                   "clear-count" () };
  bind "Page_Down" { "movement" (page-down-lines, 1, 0, 1)
                     "clear-count" () };
  bind "<ctrl>u" { "movement" (half-page-up, 1, 0, 1)
                   "clear-count" () };
  bind "<ctrl>d" { "movement" (half-page-down, 1, 0, 1)
                   "clear-count" () };
}

@binding-set builder-vim-source-view-visual-block
{
}

@binding-set builder-vim-tree-view
{
  bind "<ctrl>n" { "move-cursor" (display-lines, 1) };
  bind "<ctrl>p" { "move-cursor" (display-lines, -1) };
  bind "slash" { "start-interactive-search" () };
  bind "KP_Divide" { "start-interactive-search" () };
}

@binding-set builder-vim-list-box
{
  bind "<ctrl>n" { "move-cursor" (display-lines, 1) };
  bind "<ctrl>p" { "move-cursor" (display-lines, -1) };
}

@binding-set builder-gb-project-tree-vim
{
  bind "colon" { "action" ("win", "reveal-command-bar", "") };
}

@binding-set builder-vim-workbench
{
  bind "<ctrl>period" { "action" ("win", "global-search", "") };
}

@binding-set builder-vim-global-search
{
  bind "Escape" { "action" ("search", "unfocus", "") };
  bind "Return" { "activate-suggestion" () };

  bind "Up" { "move-suggestion" (-1) };
  bind "<ctrl>p" { "move-suggestion" (-1) };
  bind "Page_Up" { "move-suggestion" (-10) };
  bind "KP_Page_Up" { "move-suggestion" (-10) };
  bind "Prior" { "move-suggestion" (-10) };

  bind "Down" { "move-suggestion" (1) };
  bind "<ctrl>n" { "move-suggestion" (1) };
  bind "Page_Down" { "move-suggestion" (10) };
  bind "KP_Page_Down" { "move-suggestion" (10) };
  bind "Next" { "move-suggestion" (10) };
}

/*
 * Sadly, this will draw from the middle, so it does not result in our
 * cursor being over the actual character, but between two characters.
 *
 *   IdeSourceView {
 *     -GtkWidget-cursor-aspect-ratio: 0.5;
 *   }
 */

idesourceviewmode.default,
idesourceviewmode.vim-normal {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-keep-mark-on-char: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal;
}

idesourceviewmode.vim-normal-with-count {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-with-count,
                     builder-vim-source-view-normal;
}

idesourceviewmode.vim-normal-bracket {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-bracket;
}

idesourceviewmode.vim-normal-equal {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-equal;
}

idesourceviewmode.vim-normal-c {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-c;
}

idesourceviewmode.vim-c-with-count {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-default-mode: "vim-normal-c";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-c-with-count,
                     builder-vim-source-view-normal-c;
}

idesourceviewmode.vim-normal-c-i {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-c-i;
}

idesourceviewmode.vim-normal-c-a {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-c-a;
}

idesourceviewmode.vim-normal-d {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Delete";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-d;
}

idesourceviewmode.vim-normal-d-g {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-d-g;
}

idesourceviewmode.vim-normal-d-i {
  -IdeSourceViewMode-suppress-unbound: true;
  -block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-d-i;
}

idesourceviewmode.vim-normal-d-a {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-d-a;
}

idesourceviewmode.vim-normal-g {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-g;
}

idesourceviewmode.vim-normal-g-u {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-g-u;
}

idesourceviewmode.vim-normal-q {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-q;
}

idesourceviewmode.vim-normal-indent {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-indent;
}

idesourceviewmode.vim-normal-ctrl-w {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "^w";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-ctrl-w;
}

idesourceviewmode.vim-normal-y {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-y;
}

idesourceviewmode.vim-normal-y-i {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-y-i;
}

idesourceviewmode.vim-normal-z {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-z;
}

idesourceviewmode.vim-normal-Z {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Z";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-normal-Z;
}

idesourceviewmode.vim-insert {
  -IdeSourceViewMode-suppress-unbound: false;
  -IdeSourceViewMode-block-cursor: false;
  -IdeSourceViewMode-display-name: "Insert";

  -gtk-key-bindings: builder-vim-source-view-insert,
                     builder-vim-source-view;
}

idesourceviewmode.vim-replace {
  -IdeSourceViewMode-suppress-unbound: false;
  -IdeSourceViewMode-block-cursor: false;
  -IdeSourceViewMode-display-name: "Replace";

  -gtk-key-bindings: builder-vim-source-view-insert,
                     builder-vim-source-view;
}

idesourceviewmode.vim-visual {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual;
}

idesourceviewmode.vim-visual-i {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-i;
}

idesourceviewmode.vim-visual-a {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-a;
}

idesourceviewmode.vim-visual-with-count {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-default-mode: "vim-visual";
  -IdeSourceViewMode-display-name: "Visual";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-with-count,
                     builder-vim-source-view-visual;
}

idesourceviewmode.vim-visual-g {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-g;
}

idesourceviewmode.vim-visual-z {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-z;
}

idesourceviewmode.vim-visual-line {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual Line";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-line;
}

idesourceviewmode.vim-visual-line-with-count {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-default-mode: "vim-visual-line";
  -IdeSourceViewMode-display-name: "Visual Line";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-line-with-count,
                     builder-vim-source-view-visual-line;
}

idesourceviewmode.vim-visual-line-g {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual Line";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-line-g;
}

idesourceviewmode.vim-visual-line-z {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual Line";

  -gtk-key-bindings: builder-vim-source-view,
                     builder-vim-source-view-visual-line-z;
}

idesourceviewmode.vim-visual-block {
  -IdeSourceViewMode-suppress-unbound: true;
  -IdeSourceViewMode-block-cursor: true;
  -IdeSourceViewMode-display-name: "Visual Block";

  -gtk-key-bindings: builder-vim-source-view, builder-vim-source-view-visual-block;
}

treeview {
  -gtk-key-bindings: builder-vim-tree-view;
}

treeview.project-tree {
  -gtk-key-bindings: builder-vim-tree-view,
                     builder-gb-project-tree-vim;
}

list {
  -gtk-key-bindings: builder-vim-list-box;
}

window.workbench {
  -gtk-key-bindings: builder-vim-workbench;
}

window entry.global-search {
  -gtk-key-bindings: builder-vim-global-search;
}
