diff --git a/.config/zsh/config/plugins/zsh-vi-mode/.github/FUNDING.yml b/.config/zsh/config/plugins/zsh-vi-mode/.github/FUNDING.yml
deleted file mode 100644
index 15a0e78..0000000
--- a/.config/zsh/config/plugins/zsh-vi-mode/.github/FUNDING.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-# These are supported funding model platforms
-
-github: jeffreytse # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-patreon: jeffreytse
-open_collective: # Replace with a single Open Collective username
-ko_fi: jeffreytse
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: jeffreytse
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
-
diff --git a/.config/zsh/config/plugins/zsh-vi-mode/.github/ISSUE_TEMPLATE.md b/.config/zsh/config/plugins/zsh-vi-mode/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index 7bd126a..0000000
--- a/.config/zsh/config/plugins/zsh-vi-mode/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-## General information
-
-
-
-## Basic examination
-
-
-
-- [ ] I have read through the [README](https://github.com/jeffreytse/zsh-vi-mode) page
-- [ ] I have the latest version of zsh-vi-mode
-- [ ] I have tested with another terminal program
-
-## Problem description
-
-
-
-## Reproduction steps
-
-1.
-2.
-3.
-
-## Expected behavior
-
diff --git a/.config/zsh/config/plugins/zsh-vi-mode/LICENSE b/.config/zsh/config/plugins/zsh-vi-mode/LICENSE
deleted file mode 100644
index 0ce3f29..0000000
--- a/.config/zsh/config/plugins/zsh-vi-mode/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2020 Jeffrey Tse
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/.config/zsh/config/plugins/zsh-vi-mode/README.md b/.config/zsh/config/plugins/zsh-vi-mode/README.md
deleted file mode 100644
index a75e970..0000000
--- a/.config/zsh/config/plugins/zsh-vi-mode/README.md
+++ /dev/null
@@ -1,789 +0,0 @@
-
-
-
-
-
💻 A better and friendly vi(vim) mode plugin for ZSH.
-
-
⚒️ Zsh Vi Mode ⚒️
-
-
-
-
-
-
- ZSH
plugin for Agnosticism.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-## 🤔 Why ZVM?
-
-Maybe you have experienced the default Vi mode in Zsh, after turning on
-the default Vi mode, you gradually found that it had many problems, some
-features were not perfect or non-existent, and some behaviors even were
-different from the native Vi(Vim) mode.
-
-Although the default Vi mode was a bit embarrassing and unpleasant, you
-kept on using it and gradually lost your interest on it after using for
-a period of time. Eventually, you disappointedly gave up.
-
-You never think of the Vi mode for a long time, one day you accidentally
-discovered this plugin, you read here and realize that this plugin is to
-solve the above problems and make you fall in love to Vi mode again. A
-smile suddenly appeared on your face like regaining a good life.
-
-> If winter comes, can spring be far behind?
-
-
-## ✨ Features
-
-- 🌟 Pure Zsh's script without any third-party dependencies.
-- 🎉 Better experience with the near-native vi(vim) mode.
-- ⌛ Lower delay and better response (Mode switching speed, etc.).
-- ✏️ Mode indication with different cursor styles.
-- 🧮 Cursor movement (Navigation).
-- 📝 Insert & Replace (Insert mode).
-- 💡 Text Objects (A word, inner word, etc.).
-- 🔎 Searching history.
-- ❇️ Undo, Redo, Cut, Copy, Paste, and Delete.
-- 🪐 Better surrounds functionality (Add, Replace, Delete, Move Around, and Highlight).
-- 🧽 Switch keywords (Increase/Decrease Number, Boolean, Weekday, Month, etc.).
-- ⚙️ Better functionality in command mode (**In progress**).
-- 🪀 Repeating command such as `10p` and `4fa` (**In progress**).
-- 📒 System clipboard (**In progress**).
-
-## 💼 Requirements
-
-ZSH: >= 5.1.0
-
-## 🛠️ Installation
-
-#### Using [Antigen](https://github.com/zsh-users/antigen)
-
-Bundle `zsh-vi-mode` in your `.zshrc`
-
-```shell
-antigen bundle jeffreytse/zsh-vi-mode
-```
-
-#### Using [zplug](https://github.com/b4b4r07/zplug)
-Load `zsh-vi-mode` as a plugin in your `.zshrc`
-
-```shell
-zplug "jeffreytse/zsh-vi-mode"
-```
-
-#### Using [zgen](https://github.com/tarjoilija/zgen)
-
-Include the load command in your `.zshrc`
-
-```shell
-zgen load jeffreytse/zsh-vi-mode
-```
-
-#### Using [zinit](https://github.com/zdharma-continuum/zinit)
-
-Include the load command in your `.zshrc`
-
-```shell
-zinit ice depth=1
-zinit light jeffreytse/zsh-vi-mode
-```
-
-Note: the use of `depth=1` ice is optional, other types of ice are neither
-recommended nor officially supported by this plugin.
-
-#### As an [Oh My Zsh!](https://github.com/robbyrussell/oh-my-zsh) custom plugin
-
-Clone `zsh-vi-mode` into your custom plugins repo
-
-```shell
-git clone https://github.com/jeffreytse/zsh-vi-mode \
- $ZSH_CUSTOM/plugins/zsh-vi-mode
-```
-Then load as a plugin in your `.zshrc`
-
-```shell
-plugins+=(zsh-vi-mode)
-```
-
-Keep in mind that plugins need to be added before `oh-my-zsh.sh` is sourced.
-
-#### Using [Antibody](https://getantibody.github.io/)
-
-Add `zsh-vi-mode` to your plugins file (e.g. `~/.zsh_plugins.txt`)
-
-```shell
-jeffreytse/zsh-vi-mode
-```
-
-#### Using [Homebrew](https://brew.sh/)
-
-For Homebrew users, you can install it through the following command
-
-```shell
-brew install zsh-vi-mode
-```
-
-#### Arch Linux (AUR)
-
-For Arch Linux users, you can install it through the following command
-
-```shell
-yay -S zsh-vi-mode
-```
-
-or the latest update (unstable)
-
-```shell
-yay -S zsh-vi-mode-git
-```
-
-Then source it in your `.zshrc` (or `.bashrc`)
-
-```shell
-source /usr/share/zsh/plugins/zsh-vi-mode/zsh-vi-mode.plugin.zsh
-```
-
-#### Nix
-
-For users of Nix, as of [e7e3480530b34a9fe8cb52963ec2cf66e6707e15](https://github.com/NixOS/nixpkgs/commit/e7e3480530b34a9fe8cb52963ec2cf66e6707e15) you can source the plugin through the following configuration
-
-```shell
-programs = {
- zsh = {
- interactiveShellInit = ''
- source ${pkgs.zsh-vi-mode}/share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
- '';
- };
-};
-```
-
-Or if you prefer `home-manager`:
-
-```shell
-home-manager.users.[your username] = { pkgs, ... }: {
- programs = {
- zsh = {
- initExtra = ''
- source ${pkgs.zsh-vi-mode}/share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
- '';
- };
- };
-};
-```
-
-#### Manually
-
-Clone this repository somewhere (`$HOME/.zsh-vi-mode` for example)
-
-```shell
-git clone https://github.com/jeffreytse/zsh-vi-mode.git $HOME/.zsh-vi-mode
-```
-Then source it in your `.zshrc` (or `.bashrc`)
-
-```shell
-source $HOME/.zsh-vi-mode/zsh-vi-mode.plugin.zsh
-```
-
-## 📚 Usage
-
-Use `ESC` or `CTRL-[` to enter `Normal mode`.
-
-But some people may like the custom escape key such as `jj`, `jk` and so on,
-if you want to custom the escape key, you can learn more from [here](#custom-escape-key).
-
-History
--------
-
-- `ctrl-p` : Previous command in history
-- `ctrl-n` : Next command in history
-- `/` : Search backward in history
-- `n` : Repeat the last `/`
-
-
-Mode indicators
----------------
-
-`Normal mode` is indicated with block style cursor, and `Insert mode` with
-beam style cursor by default.
-
-Vim edition
------------
-
-In `Normal mode` you can use `vv` to edit current command line in an editor
-(e.g. `vi`/`vim`/`nvim`...), because it is bound to the `Visual mode`.
-
-You can change the editor by `ZVM_VI_EDITOR` option, by default it is
-`$EDITOR`.
-
-Movement
---------
-
-- `$` : To the end of the line
-- `^` : To the first non-blank character of the line
-- `0` : To the first character of the line
-- `w` : [count] words forward
-- `W` : [count] WORDS forward
-- `e` : Forward to the end of word [count] inclusive
-- `E` : Forward to the end of WORD [count] inclusive
-- `b` : [count] words backward
-- `B` : [count] WORDS backward
-- `t{char}` : Till before [count]'th occurrence of {char} to the right
-- `T{char}` : Till before [count]'th occurrence of {char} to the left
-- `f{char}` : To [count]'th occurrence of {char} to the right
-- `F{char}` : To [count]'th occurrence of {char} to the left
-- `;` : Repeat latest f, t, F or T [count] times
-- `,` : Repeat latest f, t, F or T in opposite direction
-
-
-Insertion
----------
-
-- `i` : Insert text before the cursor
-- `I` : Insert text before the first character in the line
-- `a` : Append text after the cursor
-- `A` : Append text at the end of the line
-- `o` : Insert new command line below the current one
-- `O` : Insert new command line above the current one
-
-Surround
---------
-
-There are 2 kinds of keybinding mode for surround operating, default is
-`classic` mode, you can choose the mode by setting `ZVM_VI_SURROUND_BINDKEY`
-option.
-
-1. `classic` mode (verb->s->surround)
-
-- `S"` : Add `"` for visual selection
-- `ys"` : Add `"` for visual selection
-- `cs"'` : Change `"` to `'`
-- `ds"` : Delete `"`
-
- 2. `s-prefix` mode (s->verb->surround)
-- `sa"` : Add `"` for visual selection
-- `sd"` : Delete `"`
-- `sr"'` : Change `"` to `'`
-
-Note that key sequences must be pressed in fairly quick succession to avoid a timeout. You may extend this timeout with the [`ZVM_KEYTIMEOUT` option](#readkey-engine).
-
-#### How to select surround text object?
-
-- `vi"` : Select the text object inside the quotes
-- `va(` : Select the text object including the brackets
-
-Then you can do any operation for the selection:
-
-1. Add surrounds for text object
-
-- `vi"` -> `S[` or `sa[` => `"object"` -> `"[object]"`
-- `va"` -> `S[` or `sa[` => `"object"` -> `["object"]`
-
-2. Delete/Yank/Change text object
-
-- `di(` or `vi(` -> `d`
-- `ca(` or `va(` -> `c`
-- `yi(` or `vi(` -> `y`
-
-Increment and Decrement
---------
-
-In normal mode, typing `ctrl-a` will increase to the next keyword, and typing
-`ctrl-x` will decrease to the next keyword. The keyword can be at the cursor,
-or to the right of the cursor (on the same line). The keyword could be as
-below:
-
-- Number (Decimal, Hexadecimal, Binary...)
-- Boolean (True or False, Yes or No, On or Off...)
-- Weekday (Sunday, Monday, Tuesday, Wednesday...)
-- Month (January, February, March, April, May...)
-- Operator (&&, ||, ++, --, ==, !==, and, or...)
-- ...
-
-For example:
-
-1. Increment
-
-- `9` => `10`
-- `aa99bb` => `aa100bb`
-- `aa100bc` => `aa101bc`
-- `0xDe` => `0xdf`
-- `0Xdf` => `0Xe0`
-- `0b101` => `0b110`
-- `0B11` => `0B101`
-- `true` => `false`
-- `yes` => `no`
-- `on` => `off`
-- `T` => `F`
-- `Fri` => `Sat`
-- `Oct` => `Nov`
-- `Monday` => `Tuesday`
-- `January` => `February`
-- `+` => `-`
-- `++` => `--`
-- `==` => `!=`
-- `!==` => `===`
-- `&&` => `||`
-- `and` => `or`
-- ...
-
-2. Decrement:
-
-- `100` => `99`
-- `aa100bb` => `aa99bb`
-- `0` => `-1`
-- `0xdE0` => `0xDDF`
-- `0xffFf0` => `0xfffef`
-- `0xfffF0` => `0xFFFEF`
-- `0x0` => `0xffffffffffffffff`
-- `0Xf` => `0Xe`
-- `0b100` => `0b010`
-- `0B100` => `0B011`
-- `True` => `False`
-- `On` => `Off`
-- `Sun` => `Sat`
-- `Jan` => `Dec`
-- `Monday` => `Sunday`
-- `August` => `July`
-- `/` => `*`
-- `++` => `--`
-- `==` => `!=`
-- `!==` => `===`
-- `||` => `&&`
-- `or` => `and`
-- ...
-
-Custom Escape Key
---------
-
-You can use below options to custom the escape key which could better match
-your flavor, such as `jj` or `jk` and so on.
-
-- `ZVM_VI_ESCAPE_BINDKEY`: The vi escape key in all modes (default is `^[`
- => `ESC`)
-- `ZVM_VI_INSERT_ESCAPE_BINDKEY`: The vi escape key in insert mode (default
- is `$ZVM_VI_ESCAPE_BINDKEY`)
-- `ZVM_VI_VISUAL_ESCAPE_BINDKEY`: The vi escape key in visual mode (default
- is `$ZVM_VI_ESCAPE_BINDKEY`)
-- `ZVM_VI_OPPEND_ESCAPE_BINDKEY`: The vi escape key in operator pending mode
- (default is `$ZVM_VI_ESCAPE_BINDKEY`)
-
-For example:
-
-```zsh
-# Only changing the escape key to `jk` in insert mode, we still
-# keep using the default keybindings `^[` in other modes
-ZVM_VI_INSERT_ESCAPE_BINDKEY=jk
-```
-
-Readkey Engine
---------
-
-This plugin has supported to choose the readkey engine for reading and
-processing the key events. It easy to do by the `ZVM_READKEY_ENGINE`option,
-currently the below engines are supported:
-
-- `ZVM_READKEY_ENGINE_NEX`: It is a better readkey engine to replace ZLE (Beta).
-- `ZVM_READKEY_ENGINE_ZLE`: It is Zsh's default readkey engine (ZLE).
-- `ZVM_READKEY_ENGINE_DEFAULT`: It is the default engine of this plugin
- (It's the NEX engine now).
-
-The NEX is a better engine for reading and handling the key events than the
-Zsh's ZLE engine, currently the NEX engine is still at beta stage, you can
-change back to Zsh's ZLE engine if you want.
-
-For example:
-
-```zsh
-# Change to Zsh's default readkey engine
-ZVM_READKEY_ENGINE=$ZVM_READKEY_ENGINE_ZLE
-```
-
-You can use `ZVM_KEYTIMEOUT` option to adjust the key input timeout for
-waiting for next key, default is `0.4` seconds.
-
-The escape key is a special case, it can be used standalone. NEX engine
-waits for a period after receiving the escape character, to determine
-whether it is standalone or part of an escape sequence. While waiting,
-additional key presses make the escape key behave as a meta key. If no
-other key presses come in, it is handled as a standalone escape.
-
-For the NEX engine, we can use `ZVM_ESCAPE_KEYTIMEOUT` option to adjust
-the waiting timeout for the escape key, default is `0.03` seconds.
-
-Configuration Function
---------
-
-Since there are some config options relied to some variables defined in
-the plugin, however, some not. We need to provide an unified config entry
-function. The name of entry function is stored in an option called
-`ZVM_CONFIG_FUNC` and default value is `zvm_config`, you can change to
-others for fitting your flavor.
-
-If this config function exists, it will be called automatically, you can
-do some configurations in this aspect before you source this plugin. For
-example:
-
-```zsh
-function zvm_config() {
- ZVM_LINE_INIT_MODE=$ZVM_MODE_INSERT
- ZVM_VI_INSERT_ESCAPE_BINDKEY=jk
-}
-
-source ~/zsh-vi-mode.zsh
-```
-
-Execute Extra Commands
---------
-
-This plugin has provided a mechanism to execute extra commands, and now
-you have the below aspects for executing something:
-
-```zsh
-zvm_before_init_commands=()
-zvm_after_init_commands=()
-zvm_before_select_vi_mode_commands=()
-zvm_after_select_vi_mode_commands=()
-zvm_before_lazy_keybindings_commands=()
-zvm_after_lazy_keybindings_commands=()
-```
-
-Since the default [initialization mode](#initialization-mode), this plugin
-will overwrite the previous key bindings, this causes the key bindings of
-other plugins (i.e. `fzf`, `zsh-autocomplete`, etc.) to fail.
-
-You can solve the compatibility issue as below:
-
-```zsh
-# Append a command directly
-zvm_after_init_commands+=('[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh')
-```
-
-or
-
-```zsh
-# Define an init function and append to zvm_after_init_commands
-function my_init() {
- [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
-}
-zvm_after_init_commands+=(my_init)
-```
-
-or
-
-```zsh
-# The plugin will auto execute this zvm_after_init function
-function zvm_after_init() {
- [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
-}
-```
-
-or if you are using the `zinit`:
-
-```zsh
-# For postponing loading `fzf`
-zinit ice lucid wait
-zinit snippet OMZP::fzf
-```
-
-By default, [the lazy keybindings feature](#lazy-keybindings) is enabled, all
-the keybindings of `normal` and `visual` mode should be executed by the
-`zvm_after_lazy_keybindings_commands`. For example:
-
-```zsh
-# The plugin will auto execute this zvm_after_lazy_keybindings function
-function zvm_after_lazy_keybindings() {
- bindkey -M vicmd 's' your_normal_widget
- bindkey -M visual 'n' your_visual_widget
-}
-```
-
-Custom widgets and keybindings
---------
-
-This plugin has two functions for you to define custom widgets and keybindings.
-In case of unnecessary problems, it is better to use them, especially when you
-meet the key conflicts.
-
-To define a custom widget, you should:
-
-```zsh
-# If [your_custom_widget] were ignored, it will be the same with
-zvm_define_widget [your_custom_function]
-```
-
-To define a keybinding, you should:
-
-```zsh
-zvm_bindkey
-```
-
-For example:
-
-```zsh
-# Your custom widget
-function my_custom_widget() {
- echo 'Hello, ZSH!'
-}
-
-# The plugin will auto execute this zvm_after_lazy_keybindings function
-function zvm_after_lazy_keybindings() {
- # Here we define the custom widget
- zvm_define_widget my_custom_widget
-
- # In normal mode, press Ctrl-E to invoke this widget
- zvm_bindkey vicmd '^E' my_custom_widget
-}
-```
-
-Vi Mode Indicator
---------
-
-This plugin has provided a `ZVM_MODE` variable for you to retrieve
-current vi mode and better show the indicator.
-
-And currently the below modes are supported:
-
-```zsh
-ZVM_MODE_NORMAL
-ZVM_MODE_INSERT
-ZVM_MODE_VISUAL
-ZVM_MODE_VISUAL_LINE
-ZVM_MODE_REPLACE
-```
-
-For updating the vi mode indicator, we should add our commands to
-`zvm_after_select_vi_mode_commands`. For example:
-
-```zsh
-# The plugin will auto execute this zvm_after_select_vi_mode function
-function zvm_after_select_vi_mode() {
- case $ZVM_MODE in
- $ZVM_MODE_NORMAL)
- # Something you want to do...
- ;;
- $ZVM_MODE_INSERT)
- # Something you want to do...
- ;;
- $ZVM_MODE_VISUAL)
- # Something you want to do...
- ;;
- $ZVM_MODE_VISUAL_LINE)
- # Something you want to do...
- ;;
- $ZVM_MODE_REPLACE)
- # Something you want to do...
- ;;
- esac
-}
-```
-
-Custom Cursor Style
---------
-
-This plugin has provided some options for users to custom the cursor
-style for better terminal compatibility.
-
-- You can disable this feature by the `ZVM_CURSOR_STYLE_ENABLED`
- option (Default is `true`)
-
-```zsh
-# Disable the cursor style feature
-ZVM_CURSOR_STYLE_ENABLED=false
-```
-
-- You can set your cursor style for different vi mode:
-
-```zsh
-# The prompt cursor in normal mode
-ZVM_NORMAL_MODE_CURSOR
-
-# The prompt cursor in insert mode
-ZVM_INSERT_MODE_CURSOR
-
-# The prompt cursor in visual mode
-ZVM_VISUAL_MODE_CURSOR
-
-# The prompt cursor in visual line mode
-ZVM_VISUAL_LINE_MODE_CURSOR
-
-# The prompt cursor in operator pending mode
-ZVM_OPPEND_MODE_CURSOR
-```
-
-- And the below cursor styles are supported:
-
-```zsh
-ZVM_CURSOR_USER_DEFAULT
-ZVM_CURSOR_BLOCK
-ZVM_CURSOR_UNDERLINE
-ZVM_CURSOR_BEAM
-ZVM_CURSOR_BLINKING_BLOCK
-ZVM_CURSOR_BLINKING_UNDERLINE
-ZVM_CURSOR_BLINKING_BEAM
-```
-
-- Custom your cursor style is easy as below:
-
-```zsh
-ZVM_INSERT_MODE_CURSOR=$ZVM_CURSOR_BEAM
-ZVM_NORMAL_MODE_CURSOR=$ZVM_CURSOR_BLOCK
-ZVM_OPPEND_MODE_CURSOR=$ZVM_CURSOR_UNDERLINE
-```
-
-- Also, custom your colorful cursor style as below:
-
-```zsh
-# The plugin will auto execute this zvm_config function
-zvm_config() {
- # Retrieve default cursor styles
- local ncur=$(zvm_cursor_style $ZVM_NORMAL_MODE_CURSOR)
- local icur=$(zvm_cursor_style $ZVM_INSERT_MODE_CURSOR)
-
- # Append your custom color for your cursor
- ZVM_INSERT_MODE_CURSOR=$icur'\e\e]12;red\a'
- ZVM_NORMAL_MODE_CURSOR=$ncur'\e\e]12;#008800\a'
-}
-```
-
-We can use `ZVM_TERM` option to set the term type for plugin to handle
-terminal escape sequences, default is `$TERM`. It could be `xterm-256color`,
-`alacritty-256color`, `st-256color`, etc. It's important for some
-terminal emulators to show cursor properly.
-
-Highlight Behavior
---------
-
-You can use `ZVM_VI_HIGHLIGHT_BACKGROUND`, `ZVM_VI_HIGHLIGHT_FOREGROUND`
-and `ZVM_VI_HIGHLIGHT_EXTRASTYLE` to change the highlight behaviors (
-surrounds, visual-line, etc.), the color value could be _a color name_ or
-_a hex color value_.
-
-For example:
-
-```zsh
-ZVM_VI_HIGHLIGHT_FOREGROUND=green # Color name
-ZVM_VI_HIGHLIGHT_FOREGROUND=#008800 # Hex value
-ZVM_VI_HIGHLIGHT_BACKGROUND=red # Color name
-ZVM_VI_HIGHLIGHT_BACKGROUND=#ff0000 # Hex value
-ZVM_VI_HIGHLIGHT_EXTRASTYLE=bold,underline # bold and underline
-```
-
-Command Line Initial Mode
---------
-
-You can set the command line initial mode by the `ZVM_LINE_INIT_MODE`
-option.
-
-Currently the below modes are supported:
-
-- `ZVM_MODE_LAST` : Starting with last mode (Default).
-- `ZVM_MODE_INSERT` : Starting with insert mode.
-- `ZVM_MODE_NORMAL` : Starting with normal mode.
-
-For example:
-
-```zsh
-# Always starting with insert mode for each command line
-ZVM_LINE_INIT_MODE=$ZVM_MODE_INSERT
-```
-
-Lazy Keybindings
---------
-
-This plugin has supported the lazy keybindings feature, and it is enabled
-by default. To disable it, you can set the option `ZVM_LAZY_KEYBINDINGS`
-to `false` before this plugin is loaded. This feature will postpone all
-the keybindings of `normal` and `visual` mode to the first time you enter
-the normal mode.
-
-It can greatly improve the startup speed, especially you open the terminal
-and just want to execute a simple command.
-
-Initialization Mode
---------
-
-In order to prevent various problems related to keybindings caused by the
-plugin sourcing sequence, and also keep the same functionality for this
-plugin, the initialization of this plugin was postponed to the first
-command line starting.
-
-However, almost all plugins are initialized when the script is sourced.
-Therefore, this plugin provides an option `ZVM_INIT_MODE` to change the
-initialization mode.
-
-For example:
-
-```zsh
-# Do the initialization when the script is sourced (i.e. Initialize instantly)
-ZVM_INIT_MODE=sourcing
-```
-
-## 💎 Credits
-
-- [Zsh](https://www.zsh.org/) - A powerful shell that operates as both an interactive shell and as a scripting language interpreter.
-- [Oh-My-Zsh](https://github.com/ohmyzsh/ohmyzsh) - A delightful, open source, community-driven framework for managing your ZSH configuration.
-- [vim-surround](https://github.com/tpope/vim-surround) - A vim plugin that all about "surroundings": parentheses, brackets, quotes, XML tags, and more.
-- [vim-sandwich](https://github.com/machakann/vim-sandwich) - A set of operator and textobject plugins to add/delete/replace surroundings of a sandwiched textobject.
-
-## 🔫 Contributing
-
-Issues and Pull Requests are greatly appreciated. If you've never contributed to an open source project before I'm more than happy to walk you through how to create a pull request.
-
-You can start by [opening an issue](https://github.com/jeffreytse/zsh-vi-mode/issues/new) describing the problem that you're looking to resolve and we'll go from there.
-
-## 🌈 License
-
-This theme is licensed under the [MIT license](https://opensource.org/licenses/mit-license.php) © Jeffrey Tse.
diff --git a/.config/zsh/config/plugins/zsh-vi-mode/zsh-vi-mode.plugin.zsh b/.config/zsh/config/plugins/zsh-vi-mode/zsh-vi-mode.plugin.zsh
deleted file mode 100644
index 7c215f4..0000000
--- a/.config/zsh/config/plugins/zsh-vi-mode/zsh-vi-mode.plugin.zsh
+++ /dev/null
@@ -1,6 +0,0 @@
-# According to the standard:
-# https://zdharma-continuum.github.io/Zsh-100-Commits-Club/Zsh-Plugin-Standard.html
-0="${ZERO:-${${0:#$ZSH_ARGZERO}:-${(%):-%N}}}"
-0="${${(M)0:#/*}:-$PWD/$0}"
-
-source ${0:h}/zsh-vi-mode.zsh
diff --git a/.config/zsh/config/plugins/zsh-vi-mode/zsh-vi-mode.zsh b/.config/zsh/config/plugins/zsh-vi-mode/zsh-vi-mode.zsh
deleted file mode 100644
index c8cce0b..0000000
--- a/.config/zsh/config/plugins/zsh-vi-mode/zsh-vi-mode.zsh
+++ /dev/null
@@ -1,3453 +0,0 @@
-# zsh-vi-mode.zsh -- A better and friendly vi(vim) mode for Zsh
-# https://github.com/jeffreytse/zsh-vi-mode
-#
-# Copyright (c) 2020 Jeffrey Tse
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-# All Settings
-# Some of these variables should be set before sourcing this file.
-#
-# ZVM_CONFIG_FUNC
-# the config function (default is `zvm_config`), if this config function
-# exists, it will be called automatically, you can do some configurations
-# in this aspect before you source this plugin.
-#
-# For example:
-#
-# ```zsh
-# function zvm_config() {
-# ZVM_LINE_INIT_MODE=$ZVM_MODE_INSERT
-# ZVM_VI_INSERT_ESCAPE_BINDKEY=jk
-# }
-#
-# source ~/zsh-vi-mode.zsh
-# ```
-#
-# ZVM_INIT_MODE
-# the plugin initial mode (default is doing the initialization when the first
-# new command line is starting. For doing the initialization instantly, you
-# can set it to `sourcing`.
-#
-# ZVM_VI_ESCAPE_BINDKEY
-# the vi escape key for all modes (default is ^[ => ), you can set it
-# to whatever you like, such as `jj`, `jk` and so on.
-#
-# ZVM_VI_INSERT_ESCAPE_BINDKEY
-# the vi escape key of insert mode (default is $ZVM_VI_ESCAPE_BINDKEY), you
-# can set it to whatever, such as `jj`, `jk` and so on.
-#
-# ZVM_VI_VISUAL_ESCAPE_BINDKEY
-# the vi escape key of visual mode (default is $ZVM_VI_ESCAPE_BINDKEY), you
-# can set it to whatever, such as `jj`, `jk` and so on.
-#
-# ZVM_VI_OPPEND_ESCAPE_BINDKEY
-# the vi escape key of operator pendding mode (default is
-# $ZVM_VI_ESCAPE_BINDKEY), you can set it to whatever, such as `jj`, `jk`
-# and so on.
-#
-# ZVM_VI_INSERT_MODE_LEGACY_UNDO:
-# using legacy undo behavior in vi insert mode
-#
-# ZVM_VI_HIGHLIGHT_FOREGROUND:
-# the behavior of highlight foreground (surrounds, visual-line, etc) in vi mode
-#
-# ZVM_VI_HIGHLIGHT_BACKGROUND:
-# the behavior of highlight background (surrounds, visual-line, etc) in vi mode
-#
-# ZVM_VI_HIGHLIGHT_EXTRASTYLE:
-# the behavior of highlight extra style (i.e. bold, underline) in vi mode
-#
-# For example:
-# ZVM_VI_HIGHLIGHT_FOREGROUND=green # Color name
-# ZVM_VI_HIGHLIGHT_FOREGROUND=#008800 # Hex value
-# ZVM_VI_HIGHLIGHT_BACKGROUND=red # Color name
-# ZVM_VI_HIGHLIGHT_BACKGROUND=#ff0000 # Hex value
-# ZVM_VI_HIGHLIGHT_EXTRASTYLE=bold,underline # bold and underline
-#
-# ZVM_VI_SURROUND_BINDKEY
-# the key binding mode for surround operating (default is 'classic')
-#
-# 1. 'classic' mode (verb->s->surround):
-# S" Add " for visual selection
-# ys" Add " for visual selection
-# cs"' Change " to '
-# ds" Delete "
-#
-# 2. 's-prefix' mode (s->verb->surround):
-# sa" Add " for visual selection
-# sd" Delete "
-# sr"' Change " to '
-#
-# How to select surround text object?
-# vi" Select the text object inside the quotes
-# va( Select the text object including the brackets
-#
-# Then you can do any operation for the selection:
-#
-# 1. Add surrounds for text object
-# vi" -> S[ or sa[ => "object" -> "[object]"
-#
-# 2. Delete/Yank/Change text object
-# di( or vi( -> d
-# ca( or va( -> c
-# yi( or vi( -> y
-#
-# ZVM_READKEY_ENGINE
-# the readkey engine for reading and processing the key events, and the
-# below engines are supported:
-# ZVM_READKEY_ENGINE_NEX (Default)
-# ZVM_READKEY_ENGINE_ZLE
-#
-# the NEX is a better engine for reading and handling the key events than
-# the Zsh's ZLE engine, currently the NEX engine is at beta stage, and
-# you can change to Zsh's ZLE engine if you want.
-#
-# ZVM_KEYTIMEOUT:
-# the key input timeout for waiting for next key (default is 0.4 seconds)
-#
-# ZVM_ESCAPE_KEYTIMEOUT:
-# the key input timeout for waiting for next key if it is beginning with
-# an escape character (default is 0.03 seconds), and this option is just
-# available for the NEX readkey engine
-#
-# ZVM_LINE_INIT_MODE
-# the setting for init mode of command line (default is empty), empty will
-# keep the last command mode, for the first command line it will be insert
-# mode, you can also set it to a specific vi mode to alway keep the mode
-# for each command line
-#
-# For example:
-# ZVM_LINE_INIT_MODE=$ZVM_MODE_INSERT
-# ZVM_LINE_INIT_MODE=$ZVM_MODE_NORMAL
-#
-# ZVM_LAZY_KEYBINDINGS:
-# the setting for lazy keybindings (default is true), and lazy keybindings
-# will postpone the keybindings of vicmd and visual keymaps to the first
-# time entering normal mode
-#
-# ZVM_NORMAL_MODE_CURSOR:
-# the prompt cursor in normal mode
-#
-# ZVM_INSERT_MODE_CURSOR:
-# the prompt cursor in insert mode
-#
-# ZVM_VISUAL_MODE_CURSOR:
-# the prompt cursor in visual mode
-#
-# ZVM_VISUAL_LINE_MODE_CURSOR:
-# the prompt cursor in visual line mode
-#
-# ZVM_OPPEND_MODE_CURSOR:
-# the prompt cursor in operator pending mode
-#
-# You can change the cursor style by below:
-# ZVM_INSERT_MODE_CURSOR=$ZVM_CURSOR_BLOCK
-#
-# and the below cursor style are supported:
-# ZVM_CURSOR_USER_DEFAULT
-# ZVM_CURSOR_BLOCK
-# ZVM_CURSOR_UNDERLINE
-# ZVM_CURSOR_BEAM
-# ZVM_CURSOR_BLINKING_BLOCK
-# ZVM_CURSOR_BLINKING_UNDERLINE
-# ZVM_CURSOR_BLINKING_BEAM
-#
-# ZVM_VI_EDITOR
-# the editor to edit your command line (default is $EDITOR)
-#
-# ZVM_TMPDIR
-# the temporary directory (default is $TMPDIR, otherwise it's /tmp)
-#
-# ZVM_TERM
-# the term for handling terminal sequences, it's important for some
-# terminal emulators to show cursor properly (default is $TERM)
-#
-# ZVM_CURSOR_STYLE_ENABLED
-# enable the cursor style feature (default is true)
-#
-
-# Avoid sourcing plugin multiple times
-command -v 'zvm_version' >/dev/null && return
-
-# Plugin information
-typeset -gr ZVM_NAME='zsh-vi-mode'
-typeset -gr ZVM_DESCRIPTION='💻 A better and friendly vi(vim) mode plugin for ZSH.'
-typeset -gr ZVM_REPOSITORY='https://github.com/jeffreytse/zsh-vi-mode'
-typeset -gr ZVM_VERSION='0.8.5'
-
-# Plugin initial status
-ZVM_INIT_DONE=false
-
-# Postpone reset prompt (i.e. postpone the widget `reset-prompt`)
-# empty (No postponing)
-# true (Enter postponing)
-# false (Trigger reset prompt)
-ZVM_POSTPONE_RESET_PROMPT=
-
-# Operator pending mode
-ZVM_OPPEND_MODE=false
-
-# Insert mode could be
-# `i` (insert)
-# `a` (append)
-# `I` (insert at the non-blank beginning of current line)
-# `A` (append at the end of current line)
-ZVM_INSERT_MODE='i'
-
-# The mode could be the below value:
-# `n` (normal)
-# `i` (insert)
-# `v` (visual)
-# `vl` (visual-line)
-ZVM_MODE=''
-
-# The keys typed to invoke this widget, as a literal string
-ZVM_KEYS=''
-
-# The region hilight information
-ZVM_REGION_HIGHLIGHT=()
-
-# Default zvm readkey engines
-ZVM_READKEY_ENGINE_NEX='nex'
-ZVM_READKEY_ENGINE_ZLE='zle'
-ZVM_READKEY_ENGINE_DEFAULT=$ZVM_READKEY_ENGINE_NEX
-
-# Default alternative character for escape characters
-ZVM_ESCAPE_SPACE='\s'
-ZVM_ESCAPE_NEWLINE='^J'
-
-# Default vi modes
-ZVM_MODE_LAST=''
-ZVM_MODE_NORMAL='n'
-ZVM_MODE_INSERT='i'
-ZVM_MODE_VISUAL='v'
-ZVM_MODE_VISUAL_LINE='vl'
-ZVM_MODE_REPLACE='r'
-
-# Default cursor styles
-ZVM_CURSOR_USER_DEFAULT='ud'
-ZVM_CURSOR_BLOCK='bl'
-ZVM_CURSOR_UNDERLINE='ul'
-ZVM_CURSOR_BEAM='be'
-ZVM_CURSOR_BLINKING_BLOCK='bbl'
-ZVM_CURSOR_BLINKING_UNDERLINE='bul'
-ZVM_CURSOR_BLINKING_BEAM='bbe'
-
-# The commands need to be repeated
-ZVM_REPEAT_MODE=false
-ZVM_REPEAT_RESET=false
-ZVM_REPEAT_COMMANDS=($ZVM_MODE_NORMAL i)
-
-##########################################
-# Initial all default settings
-
-# Default config function
-: ${ZVM_CONFIG_FUNC:='zvm_config'}
-
-# Load config by calling the config function
-if command -v "$ZVM_CONFIG_FUNC" >/dev/null; then
- $ZVM_CONFIG_FUNC
-fi
-
-# Set the readkey engine (default is NEX engine)
-: ${ZVM_READKEY_ENGINE:=$ZVM_READKEY_ENGINE_DEFAULT}
-
-# Set key input timeout (default is 0.4 seconds)
-: ${ZVM_KEYTIMEOUT:=0.4}
-
-# Set the escape key timeout (default is 0.03 seconds)
-: ${ZVM_ESCAPE_KEYTIMEOUT:=0.03}
-
-# Set keybindings mode (default is true)
-# The lazy keybindings will post the keybindings of vicmd and visual
-# keymaps to the first time entering the normal mode
-: ${ZVM_LAZY_KEYBINDINGS:=true}
-
-# All keybindings for lazy loading
-if $ZVM_LAZY_KEYBINDINGS; then
- ZVM_LAZY_KEYBINDINGS_LIST=()
-fi
-
-# Set the cursor style in defferent vi modes, the value you could use
-# the predefined value, such as $ZVM_CURSOR_BLOCK, $ZVM_CURSOR_BEAM,
-# $ZVM_CURSOR_BLINKING_BLOCK and so on.
-: ${ZVM_INSERT_MODE_CURSOR:=$ZVM_CURSOR_BEAM}
-: ${ZVM_NORMAL_MODE_CURSOR:=$ZVM_CURSOR_BLOCK}
-: ${ZVM_VISUAL_MODE_CURSOR:=$ZVM_CURSOR_BLOCK}
-: ${ZVM_VISUAL_LINE_MODE_CURSOR:=$ZVM_CURSOR_BLOCK}
-
-# Operator pending mode cursor style (default is underscore)
-: ${ZVM_OPPEND_MODE_CURSOR:=$ZVM_CURSOR_UNDERLINE}
-
-# Set the vi escape key (default is ^[ => )
-: ${ZVM_VI_ESCAPE_BINDKEY:=^[}
-: ${ZVM_VI_INSERT_ESCAPE_BINDKEY:=$ZVM_VI_ESCAPE_BINDKEY}
-: ${ZVM_VI_VISUAL_ESCAPE_BINDKEY:=$ZVM_VI_ESCAPE_BINDKEY}
-: ${ZVM_VI_OPPEND_ESCAPE_BINDKEY:=$ZVM_VI_ESCAPE_BINDKEY}
-
-# Set the line init mode (empty will keep the last mode)
-# you can also set it to others, such as $ZVM_MODE_INSERT.
-: ${ZVM_LINE_INIT_MODE:=$ZVM_MODE_LAST}
-
-: ${ZVM_VI_INSERT_MODE_LEGACY_UNDO:=false}
-: ${ZVM_VI_SURROUND_BINDKEY:=classic}
-: ${ZVM_VI_HIGHLIGHT_BACKGROUND:=#cc0000}
-: ${ZVM_VI_HIGHLIGHT_FOREGROUND:=#eeeeee}
-: ${ZVM_VI_HIGHLIGHT_EXTRASTYLE:=default}
-: ${ZVM_VI_EDITOR:=${EDITOR:-vim}}
-: ${ZVM_TMPDIR:=${TMPDIR:-/tmp}}
-
-# Set the term for handling terminal sequences, it's important for some
-# terminal emulators to show cursor properly (default is $TERM)
-: ${ZVM_TERM:=${TERM:-xterm-256color}}
-
-# Enable the cursor style feature
-: ${ZVM_CURSOR_STYLE_ENABLED:=true}
-
-# All the extra commands
-zvm_before_init_commands=()
-zvm_after_init_commands=()
-zvm_before_select_vi_mode_commands=()
-zvm_after_select_vi_mode_commands=()
-zvm_before_lazy_keybindings_commands=()
-zvm_after_lazy_keybindings_commands=()
-
-# All the handlers for switching keyword
-zvm_switch_keyword_handlers=(
- zvm_switch_number
- zvm_switch_boolean
- zvm_switch_operator
- zvm_switch_weekday
- zvm_switch_month
-)
-
-# Display version information
-function zvm_version() {
- echo -e "$ZVM_NAME $ZVM_VERSION"
- echo -e "\e[4m$ZVM_REPOSITORY\e[0m"
- echo -e "$ZVM_DESCRIPTION"
-}
-
-# The widget wrapper
-function zvm_widget_wrapper() {
- local rawfunc=$1;
- local func=$2;
- local -i retval
- $func "${@:3}"
- return retval
-}
-
-# Define widget function
-function zvm_define_widget() {
- local widget=$1
- local func=$2 || $1
- local result=($(zle -l -L "${widget}"))
-
- # Check if existing the same name
- if [[ ${#result[@]} == 4 ]]; then
- local rawfunc=${result[4]}
- local wrapper="zvm_${widget}-wrapper"
- eval "$wrapper() { zvm_widget_wrapper $rawfunc $func \"\$@\" }"
- func=$wrapper
- fi
-
- zle -N $widget $func
-}
-
-# Get the keys typed to invoke this widget, as a literal string
-function zvm_keys() {
- local keys=${ZVM_KEYS:-$KEYS}
-
- # Append the prefix of keys if it is visual or visual-line mode
- case "${ZVM_MODE}" in
- $ZVM_MODE_VISUAL)
- if [[ "$keys" != v* ]]; then
- keys="v${keys}"
- fi
- ;;
- $ZVM_MODE_VISUAL_LINE)
- if [[ "$keys" != V* ]]; then
- keys="V${keys}"
- fi
- ;;
- esac
-
- # Escape the newline and space characters, otherwise, we can't
- # get the output from subshell correctly.
- keys=${keys//$'\n'/$ZVM_ESCAPE_NEWLINE}
- keys=${keys// /$ZVM_ESCAPE_SPACE}
-
- echo $keys
-}
-
-# Find the widget on a specified bindkey
-function zvm_find_bindkey_widget() {
- local keymap=$1
- local keys=$2
- local prefix_mode=${3:-false}
- retval=()
-
- if $prefix_mode; then
- local pos=0
- local spos=3
- local prefix_keys=
-
- # Get the prefix keys
- if [[ $prefix_keys ]]; then
- prefix_keys=${prefix_keys:0:-1}
-
- # If the last key is an escape key (e.g. \", \`, \\) we still
- # need to remove the escape backslash `\`
- if [[ ${prefix_keys: -1} == '\' ]]; then
- prefix_keys=${prefix_keys:0:-1}
- fi
- fi
-
- local result=$(bindkey -M ${keymap} -p "$prefix_keys")$'\n'
-
- # Split string to array by newline
- for ((i=$spos;i<$#result;i++)); do
-
- # Save the last whitespace character of the line
- # and continue continue handling while meeting `\n`
- case "${result:$i:1}" in
- ' ') spos=$i; i=$i+1; continue;;
- [$'\n']);;
- *) continue;;
- esac
-
- # Check if it has the same prefix keys and retrieve the widgets
- if [[ "${result:$((pos+1)):$#keys}" == "$keys" ]]; then
-
- # Get the binding keys
- local k=${result:$((pos+1)):$((spos-pos-2))}
-
- # Escape spaces in key bindings (space -> $ZVM_ESCAPE_SPACE)
- k=${k// /$ZVM_ESCAPE_SPACE}
- retval+=($k ${result:$((spos+1)):$((i-spos-1))})
- fi
-
- # Save as new position
- pos=$i+1
-
- # Skip 3 characters
- # One key and quotes at least (i.e \n"_" )
- i=$i+3
- done
- else
- local result=$(bindkey -M ${keymap} "$keys")
- if [[ "${result: -14}" == ' undefined-key' ]]; then
- return
- fi
-
- # Escape spaces in key bindings (space -> $ZVM_ESCAPE_SPACE)
- for ((i=$#result;i>=0;i--)); do
-
- # Backward find the first whitespace character
- [[ "${result:$i:1}" == ' ' ]] || continue
-
- # Retrieve the keys and widget
- local k=${result:1:$i-2}
-
- # Escape spaces in key bindings (space -> $ZVM_ESCAPE_SPACE)
- k=${k// /$ZVM_ESCAPE_SPACE}
- retval+=($k ${result:$i+1})
-
- break
- done
- fi
-}
-
-# Read keys for retrieving widget
-function zvm_readkeys() {
- local keymap=$1
- local key=${2:-$(zvm_keys)}
- local keys=
- local widget=
- local result=
- local pattern=
- local timeout=
-
- while :; do
- # Keep reading key for escape character
- if [[ "$key" == $'\e' ]]; then
- while :; do
- local k=
- read -t $ZVM_ESCAPE_KEYTIMEOUT -k 1 k || break
- key="${key}${k}"
- done
- fi
-
- keys="${keys}${key}"
-
- # Handle the pattern
- if [[ -n "$key" ]]; then
- # Transform the non-printed characters
- local k=$(zvm_escape_non_printed_characters "${key}")
-
- # Escape keys
- # " -> \" It's a special character in bash syntax
- # ` -> \` It's a special character in bash syntax
- # -> ` ` It's a special character in bash syntax
- k=${k//\"/\\\"}
- k=${k//\`/\\\`}
- k=${k//$ZVM_ESCAPE_SPACE/ }
-
- pattern="${pattern}${k}"
- fi
-
- # Find out widgets that match this key pattern
- zvm_find_bindkey_widget $keymap "$pattern" true
- result=(${retval[@]})
-
- # Exit key input if there is only one widget matched
- # or no more widget matched.
- case ${#result[@]} in
- 2) key=; widget=${result[2]}; break;;
- 0) break;;
- esac
-
- # Evaluate the readkey timeout
- # Special timeout for the escape sequence
- if [[ "${keys}" == $'\e' ]]; then
- timeout=$ZVM_ESCAPE_KEYTIMEOUT
- # Check if there is any one custom escape sequence
- for ((i=1; i<=${#result[@]}; i=i+2)); do
- if [[ "${result[$i]}" =~ '^\^\[\[?[A-Z0-9]*~?\^\[' ]]; then
- timeout=$ZVM_KEYTIMEOUT
- break
- fi
- done
- else
- timeout=$ZVM_KEYTIMEOUT
- fi
-
- # Wait for reading next key, and we should save the widget
- # as the final widget if it is full matching
- key=
- if [[ "${result[1]}" == "${pattern}" ]]; then
- widget=${result[2]}
- # Get current widget as final widget when reading key timeout
- read -t $timeout -k 1 key || break
- else
- zvm_enter_oppend_mode
- read -k 1 key
- fi
- done
-
- # Exit operator pending mode
- if $ZVM_OPPEND_MODE; then
- zvm_exit_oppend_mode
- fi
-
- if [[ -z "$key" ]]; then
- retval=(${keys} $widget)
- else
- retval=(${keys:0:-$#key} $widget $key)
- fi
-}
-
-# Add key bindings
-function zvm_bindkey() {
- local keymap=$1
- local keys=$2
- local widget=$3
- local params=$4
- local key=
-
- # We should bind keys with an existing widget
- [[ -z $widget ]] && return
-
- # If lazy keybindings is enabled, we need to add to the lazy list
- if [[ ${ZVM_LAZY_KEYBINDINGS_LIST+x} && ${keymap} != viins ]]; then
- keys=${keys//\"/\\\"}
- keys=${keys//\`/\\\`}
- ZVM_LAZY_KEYBINDINGS_LIST+=(
- "${keymap} \"${keys}\" ${widget} \"${params}\""
- )
- return
- fi
-
- # Hanle the keybinding of NEX readkey engine
- if [[ $ZVM_READKEY_ENGINE == $ZVM_READKEY_ENGINE_NEX ]]; then
- # Get the first key (especially check if ctrl characters)
- if [[ $#keys -gt 1 && "${keys:0:1}" == '^' ]]; then
- key=${keys:0:2}
- else
- key=${keys:0:1}
- fi
- bindkey -M $keymap "${key}" zvm_readkeys_handler
- fi
-
- # Wrap params to a new widget
- if [[ -n $params ]]; then
- local suffix=$(zvm_string_to_hex $params)
- eval "$widget:$suffix() { $widget $params }"
- widget="$widget:$suffix"
- zvm_define_widget $widget
- fi
-
- # Bind keys with with a widget
- bindkey -M $keymap "${keys}" $widget
-}
-
-# Convert string to hexadecimal
-function zvm_string_to_hex() {
- local str=
- for ((i=1;i<=$#1;i++)); do
- str+=$(printf '%x' "'${1[$i]}")
- done
- echo "$str"
-}
-
-# Escape non-printed characters
-function zvm_escape_non_printed_characters() {
- local str=
- for ((i=0;i<$#1;i++)); do
- local c=${1:$i:1}
- if [[ "$c" < ' ' ]]; then
- local ord=$(($(printf '%d' "'$c")+64))
- c=$(printf \\$(printf '%03o' $ord))
- str="${str}^${c}"
- elif [[ "$c" == '' ]]; then
- str="${str}^?"
- elif [[ "$c" == ' ' ]]; then
- str="${str}^@"
- else
- str="${str}${c}"
- fi
- done
-
- # Escape the newline and space characters, otherwise, we can't
- # get the output from subshell correctly.
- str=${str// /$ZVM_ESCAPE_SPACE}
- str=${str//$'\n'/$ZVM_ESCAPE_NEWLINE}
-
- echo -n $str
-}
-
-# Backward remove characters of an emacs region in the line
-function zvm_backward_kill_region() {
- local bpos=$CURSOR-1 epos=$CURSOR
-
- # Backward search the boundary of current region
- for ((; bpos >= 0; bpos--)); do
- # Break when cursor is at the beginning of line
- [[ "${BUFFER:$bpos:1}" == $'\n' ]] && break
-
- # Break when cursor is at the boundary of a word region
- [[ "${BUFFER:$bpos:2}" =~ ^\ [^\ $'\n']$ ]] && break
- done
-
- bpos=$bpos+1
- CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
- CURSOR=$bpos
-}
-
-# Remove all characters between the cursor position and the
-# beginning of the line.
-function zvm_backward_kill_line() {
- BUFFER=${BUFFER:$CURSOR:$#BUFFER}
- CURSOR=0
-}
-
-# Remove all characters between the cursor position and the
-# end of the line.
-function zvm_forward_kill_line() {
- BUFFER=${BUFFER:0:$CURSOR}
-}
-
-# Remove all characters of the line.
-function zvm_kill_line() {
- local ret=($(zvm_calc_selection $ZVM_MODE_VISUAL_LINE))
- local bpos=${ret[1]} epos=${ret[2]}
- CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}$'\n'
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
- CURSOR=$bpos
-}
-
-# Remove all characters of the whole line.
-function zvm_kill_whole_line() {
- local ret=($(zvm_calc_selection $ZVM_MODE_VISUAL_LINE))
- local bpos=$ret[1] epos=$ret[2] cpos=$ret[3]
- CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}$'\n'
-
- # Adjust region range of deletion
- if (( $epos < $#BUFFER )); then
- epos=$epos+1
- fi
-
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
- CURSOR=$cpos
-}
-
-# Exchange the point and mark
-function zvm_exchange_point_and_mark() {
- cursor=$MARK
- MARK=$CURSOR CURSOR=$cursor
- zvm_highlight
-}
-
-# Open line below
-function zvm_open_line_below() {
- local i=$CURSOR
-
- # If there is a completion suffix, we should break at the
- # postion of suffix begin, otherwise, it should break when
- # forward finding out the first newline character.
- for ((; i<$#BUFFER; i++)); do
- if ((SUFFIX_ACTIVE == 1)) && ((i >= SUFFIX_BEGIN)); then
- break
- fi
- if [[ "${BUFFER[$i]}" == $'\n' ]]; then
- i=$((i-1))
- break
- fi
- done
-
- CURSOR=$i
- LBUFFER+=$'\n'
-
- zvm_reset_repeat_commands $ZVM_MODE_NORMAL o
- zvm_select_vi_mode $ZVM_MODE_INSERT
-}
-
-# Open line above
-function zvm_open_line_above() {
- local i=$CURSOR
-
- # Break when backward finding out the first newline character.
- for ((; i>0; i--)); do
- if [[ "${BUFFER[$i]}" == $'\n' ]]; then
- break
- fi
- done
-
- CURSOR=$i
- LBUFFER+=$'\n'
- CURSOR=$((CURSOR-1))
-
- zvm_reset_repeat_commands $ZVM_MODE_NORMAL O
- zvm_select_vi_mode $ZVM_MODE_INSERT
-}
-
-# Replace characters one by one (Replacing mode)
-function zvm_vi_replace() {
- if [[ $ZVM_MODE == $ZVM_MODE_NORMAL ]]; then
- local cursor=$CURSOR
- local cache=()
- local cmds=()
- local key=
-
- zvm_select_vi_mode $ZVM_MODE_REPLACE
-
- while :; do
- # Read a character for replacing
- zvm_update_cursor
-
- # Redisplay the command line, this is to be called from within
- # a user-defined widget to allow changes to become visible
- zle -R
-
- read -k 1 key
-
- # Escape key will break the replacing process, and enter key
- # will repace with a newline character.
- case $(zvm_escape_non_printed_characters $key) in
- '^['|$ZVM_VI_OPPEND_ESCAPE_BINDKEY) break;;
- '^M') key=$'\n';;
- esac
-
- # If the key is backspace, we should move backward the cursor
- if [[ $key == '' ]]; then
- # Cursor position should not be less than zero
- if ((cursor > 0)); then
- cursor=$((cursor-1))
- fi
-
- # We should recover the character when cache size is not zero
- if ((${#cache[@]} > 0)); then
- key=${cache[-1]}
-
- if [[ $key == '' ]]; then
- key=
- fi
-
- cache=(${cache[@]:0:-1})
- BUFFER[$cursor+1]=$key
-
- # Remove from commands
- cmds=(${cmds[@]:0:-1})
- fi
- else
- # If the key or the character at cursor is a newline character,
- # or the cursor is at the end of buffer, we should insert the
- # key instead of replacing with the key.
- if [[ $key == $'\n' ||
- $BUFFER[$cursor+1] == $'\n' ||
- $BUFFER[$cursor+1] == ''
- ]]; then
- cache+=('')
- LBUFFER+=$key
- else
- cache+=(${BUFFER[$cursor+1]})
- BUFFER[$cursor+1]=$key
- fi
-
- cursor=$((cursor+1))
-
- # Push to commands
- cmds+=($key)
- fi
-
- # Update next cursor position
- CURSOR=$cursor
-
- zle redisplay
- done
-
- # The cursor position should go back one character after
- # exiting the replace mode
- zle vi-backward-char
-
- zvm_select_vi_mode $ZVM_MODE_NORMAL
- zvm_reset_repeat_commands $ZVM_MODE R $cmds
- elif [[ $ZVM_MODE == $ZVM_MODE_VISUAL ]]; then
- zvm_enter_visual_mode V
- zvm_vi_change
- elif [[ $ZVM_MODE == $ZVM_MODE_VISUAL_LINE ]]; then
- zvm_vi_change
- fi
-}
-
-# Replace characters in one time
-function zvm_vi_replace_chars() {
- local cmds=()
- local key=
-
- # Read a character for replacing
- zvm_enter_oppend_mode
-
- # Redisplay the command line, this is to be called from within
- # a user-defined widget to allow changes to become visible
- zle redisplay
- zle -R
-
- read -k 1 key
-
- zvm_exit_oppend_mode
-
- # Escape key will break the replacing process
- case $(zvm_escape_non_printed_characters $key) in
- $ZVM_VI_OPPEND_ESCAPE_BINDKEY)
- zvm_exit_visual_mode
- return
- esac
-
- if [[ $ZVM_MODE == $ZVM_MODE_NORMAL ]]; then
- cmds+=($key)
- BUFFER[$CURSOR+1]=$key
- else
- local ret=($(zvm_calc_selection))
- local bpos=${ret[1]} epos=${ret[2]}
- for ((bpos=bpos+1; bpos<=epos; bpos++)); do
- # Newline character is no need to be replaced
- if [[ $BUFFER[$bpos] == $'\n' ]]; then
- cmds+=($'\n')
- continue
- fi
-
- cmds+=($key)
- BUFFER[$bpos]=$key
- done
- zvm_exit_visual_mode
- fi
-
- # Reset the repeat commands
- zvm_reset_repeat_commands $ZVM_MODE r $cmds
-}
-
-# Substitute characters of selection
-function zvm_vi_substitute() {
- # Substitute one character in normal mode
- if [[ $ZVM_MODE == $ZVM_MODE_NORMAL ]]; then
- BUFFER="${BUFFER:0:$CURSOR}${BUFFER:$((CURSOR+1))}"
- zvm_reset_repeat_commands $ZVM_MODE c 0 1
- zvm_select_vi_mode $ZVM_MODE_INSERT
- else
- zvm_vi_change
- fi
-}
-
-# Substitute all characters of a line
-function zvm_vi_substitute_whole_line() {
- zvm_select_vi_mode $ZVM_MODE_VISUAL_LINE false
- zvm_vi_substitute
-}
-
-# Check if cursor is at an empty line
-function zvm_is_empty_line() {
- local cursor=${1:-$CURSOR}
- if [[ ${BUFFER:$cursor:1} == $'\n' &&
- ${BUFFER:$((cursor-1)):1} == $'\n' ]]; then
- return
- fi
- return 1
-}
-
-# Get the beginning and end position of selection
-function zvm_selection() {
- local bpos= epos=
- if (( MARK > CURSOR )) ; then
- bpos=$CURSOR epos=$((MARK+1))
- else
- bpos=$MARK epos=$((CURSOR+1))
- fi
- echo $bpos $epos
-}
-
-# Calculate the region of selection
-function zvm_calc_selection() {
- local ret=($(zvm_selection))
- local bpos=${ret[1]} epos=${ret[2]} cpos=
-
- # Save the current cursor position
- cpos=$bpos
-
- # Check if it is visual-line mode
- if [[ "${1:-$ZVM_MODE}" == $ZVM_MODE_VISUAL_LINE ]]; then
-
- # Extend the selection to whole line
- for ((bpos=$bpos-1; $bpos>0; bpos--)); do
- if [[ "${BUFFER:$bpos:1}" == $'\n' ]]; then
- bpos=$((bpos+1))
- break
- fi
- done
- for ((epos=$epos-1; $epos<$#BUFFER; epos++)); do
- if [[ "${BUFFER:$epos:1}" == $'\n' ]]; then
- break
- fi
- done
-
- # The begin position must not be less than zero
- if (( bpos < 0 )); then
- bpos=0
- fi
-
- ###########################################
- # Calculate the new cursor position, here we consider that
- # the selection will be delected.
-
- # Calculate the indent of current cursor line
- for ((cpos=$((CURSOR-1)); $cpos>=0; cpos--)); do
- [[ "${BUFFER:$cpos:1}" == $'\n' ]] && break
- done
-
- local indent=$((CURSOR-cpos-1))
-
- # If the selection includes the last line, the cursor
- # will move up to above line. Otherwise the cursor will
- # keep in the same line.
-
- local hpos= # Line head position
- local rpos= # Reference position
-
- if (( $epos < $#BUFFER )); then
- # Get the head position of next line
- hpos=$((epos+1))
- rpos=$bpos
- else
- # Get the head position of above line
- for ((hpos=$((bpos-2)); $hpos>0; hpos--)); do
- if [[ "${BUFFER:$hpos:1}" == $'\n' ]]; then
- break
- fi
- done
- if (( $hpos < -1 )); then
- hpos=-1
- fi
- hpos=$((hpos+1))
- rpos=$hpos
- fi
-
- # Calculate the cursor postion, the indent must be
- # less than the line characters.
- for ((cpos=$hpos; $cpos<$#BUFFER; cpos++)); do
- if [[ "${BUFFER:$cpos:1}" == $'\n' ]]; then
- break
- fi
- if (( $hpos + $indent <= $cpos )); then
- break
- fi
- done
-
- cpos=$((rpos+cpos-hpos))
- fi
-
- echo $bpos $epos $cpos
-}
-
-# Yank characters of the marked region
-function zvm_yank() {
- local ret=($(zvm_calc_selection $1))
- local bpos=$ret[1] epos=$ret[2] cpos=$ret[3]
- CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}
- if [[ ${1:-$ZVM_MODE} == $ZVM_MODE_VISUAL_LINE ]]; then
- CUTBUFFER=${CUTBUFFER}$'\n'
- fi
- CURSOR=$bpos MARK=$epos
-}
-
-# Up case of the visual selection
-function zvm_vi_up_case() {
- local ret=($(zvm_selection))
- local bpos=${ret[1]} epos=${ret[2]}
- local content=${BUFFER:$bpos:$((epos-bpos))}
- BUFFER="${BUFFER:0:$bpos}${(U)content}${BUFFER:$epos}"
- zvm_exit_visual_mode
-}
-
-# Down case of the visual selection
-function zvm_vi_down_case() {
- local ret=($(zvm_selection))
- local bpos=${ret[1]} epos=${ret[2]}
- local content=${BUFFER:$bpos:$((epos-bpos))}
- BUFFER="${BUFFER:0:$bpos}${(L)content}${BUFFER:$epos}"
- zvm_exit_visual_mode
-}
-
-# Opposite case of the visual selection
-function zvm_vi_opp_case() {
- local ret=($(zvm_selection))
- local bpos=${ret[1]} epos=${ret[2]}
- local content=${BUFFER:$bpos:$((epos-bpos))}
- for ((i=1; i<=$#content; i++)); do
- if [[ ${content[i]} =~ [A-Z] ]]; then
- content[i]=${(L)content[i]}
- elif [[ ${content[i]} =~ [a-z] ]]; then
- content[i]=${(U)content[i]}
- fi
- done
- BUFFER="${BUFFER:0:$bpos}${content}${BUFFER:$epos}"
- zvm_exit_visual_mode
-}
-
-# Yank characters of the visual selection
-function zvm_vi_yank() {
- zvm_yank
- zvm_exit_visual_mode
-}
-
-# Put cutbuffer after the cursor
-function zvm_vi_put_after() {
- local head= foot=
- local content=${CUTBUFFER}
- local offset=1
-
- if [[ ${content: -1} == $'\n' ]]; then
- local pos=${CURSOR}
-
- # Find the end of current line
- for ((; $pos<$#BUFFER; pos++)); do
- if [[ ${BUFFER:$pos:1} == $'\n' ]]; then
- pos=$pos+1
- break
- fi
- done
-
- # Special handling if cursor at an empty line
- if zvm_is_empty_line; then
- head=${BUFFER:0:$pos}
- foot=${BUFFER:$pos}
- else
- head=${BUFFER:0:$pos}
- foot=${BUFFER:$pos}
- if [[ $pos == $#BUFFER ]]; then
- content=$'\n'${content:0:-1}
- pos=$pos+1
- fi
- fi
-
- offset=0
- BUFFER="${head}${content}${foot}"
- CURSOR=$pos
- else
- # Special handling if cursor at an empty line
- if zvm_is_empty_line; then
- head="${BUFFER:0:$((CURSOR-1))}"
- foot="${BUFFER:$CURSOR}"
- else
- head="${BUFFER:0:$CURSOR}"
- foot="${BUFFER:$((CURSOR+1))}"
- fi
-
- BUFFER="${head}${BUFFER:$CURSOR:1}${content}${foot}"
- CURSOR=$CURSOR+$#content
- fi
-
- # Reresh display and highlight buffer
- zvm_highlight clear
- zvm_highlight custom $(($#head+$offset)) $(($#head+$#content+$offset))
-}
-
-# Put cutbuffer before the cursor
-function zvm_vi_put_before() {
- local head= foot=
- local content=${CUTBUFFER}
-
- if [[ ${content: -1} == $'\n' ]]; then
- local pos=$CURSOR
-
- # Find the beginning of current line
- for ((; $pos>0; pos--)); do
- if [[ "${BUFFER:$pos:1}" == $'\n' ]]; then
- pos=$pos+1
- break
- fi
- done
-
- # Check if it is an empty line
- if zvm_is_empty_line; then
- head=${BUFFER:0:$((pos-1))}
- foot=$'\n'${BUFFER:$pos}
- pos=$((pos-1))
- else
- head=${BUFFER:0:$pos}
- foot=${BUFFER:$pos}
- fi
-
- BUFFER="${head}${content}${foot}"
- CURSOR=$pos
- else
- head="${BUFFER:0:$CURSOR}"
- foot="${BUFFER:$((CURSOR+1))}"
- BUFFER="${head}${content}${BUFFER:$CURSOR:1}${foot}"
- CURSOR=$CURSOR+$#content
- CURSOR=$((CURSOR-1))
- fi
-
- # Reresh display and highlight buffer
- zvm_highlight clear
- zvm_highlight custom $#head $(($#head+$#content))
-}
-
-# Delete characters of the visual selection
-function zvm_vi_delete() {
- local ret=($(zvm_calc_selection))
- local bpos=$ret[1] epos=$ret[2] cpos=$ret[3]
-
- CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}
-
- # Check if it is visual line mode
- if [[ $ZVM_MODE == $ZVM_MODE_VISUAL_LINE ]]; then
- if (( $epos < $#BUFFER )); then
- epos=$epos+1
- elif (( $bpos > 0 )); then
- bpos=$bpos-1
- fi
- CUTBUFFER=${CUTBUFFER}$'\n'
- fi
-
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
- CURSOR=$cpos
-
- zvm_exit_visual_mode ${1:-true}
-}
-
-# Yank characters of the visual selection
-function zvm_vi_change() {
- local ret=($(zvm_calc_selection))
- local bpos=$ret[1] epos=$ret[2]
-
- CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}
-
- # Check if it is visual line mode
- if [[ $ZVM_MODE == $ZVM_MODE_VISUAL_LINE ]]; then
- CUTBUFFER=${CUTBUFFER}$'\n'
- fi
-
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
- CURSOR=$bpos
-
- # Return when it's repeating mode
- $ZVM_REPEAT_MODE && return
-
- # Reset the repeat commands
- if [[ $ZVM_MODE != $ZVM_MODE_NORMAL ]]; then
- local npos=0 ncount=0 ccount=0
- # Count the amount of newline character and the amount of
- # characters after the last newline character.
- while :; do
- # Forward find the last newline character's position
- npos=$(zvm_substr_pos $CUTBUFFER $'\n' $npos)
- if [[ $npos == -1 ]]; then
- if (($ncount == 0)); then
- ccount=$#CUTBUFFER
- fi
- break
- fi
- npos=$((npos+1))
- ncount=$(($ncount + 1))
- ccount=$(($#CUTBUFFER - $npos))
- done
- zvm_reset_repeat_commands $ZVM_MODE c $ncount $ccount
- fi
-
- zvm_exit_visual_mode false
- zvm_select_vi_mode $ZVM_MODE_INSERT
-}
-
-# Change characters from cursor to the end of current line
-function zvm_vi_change_eol() {
- local bpos=$CURSOR epos=$CURSOR
-
- # Find the end of current line
- for ((; $epos<$#BUFFER; epos++)); do
- if [[ "${BUFFER:$epos:1}" == $'\n' ]]; then
- break
- fi
- done
-
- CUTBUFFER=${BUFFER:$bpos:$((epos-bpos))}
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
-
- zvm_reset_repeat_commands $ZVM_MODE c 0 $#CUTBUFFER
- zvm_select_vi_mode $ZVM_MODE_INSERT
-}
-
-# Default handler for unhandled key events
-function zvm_default_handler() {
- local keys=$(zvm_keys)
- local extra_keys=$1
-
- # Exit vi mode if keys is the escape keys
- case $(zvm_escape_non_printed_characters "$keys") in
- '^['|$ZVM_VI_INSERT_ESCAPE_BINDKEY)
- zvm_exit_insert_mode
- ZVM_KEYS=${extra_keys}
- return
- ;;
- [vV]'^['|[vV]$ZVM_VI_VISUAL_ESCAPE_BINDKEY)
- zvm_exit_visual_mode
- ZVM_KEYS=${extra_keys}
- return
- ;;
- esac
-
- case "$KEYMAP" in
- vicmd)
- case "$keys" in
- [vV]c) zvm_vi_change;;
- [vV]d) zvm_vi_delete;;
- [vV]y) zvm_vi_yank;;
- [vV]S) zvm_change_surround S;;
- [cdyvV]*) zvm_range_handler "${keys}${extra_keys}";;
- *)
- for ((i=0;i<$#keys;i++)) do
- zvm_navigation_handler ${keys:$i:1}
- zvm_highlight
- done
- ;;
- esac
- ;;
- viins|main)
- if [[ "${keys:0:1}" =~ [a-zA-Z0-9\ ] ]]; then
- zvm_self_insert "${keys:0:1}"
- zle redisplay
- ZVM_KEYS="${keys:1}${extra_keys}"
- return
- elif [[ "${keys:0:1}" == $'\e' ]]; then
- zvm_exit_insert_mode
- ZVM_KEYS="${keys:1}${extra_keys}"
- return
- fi
- ;;
- visual)
- ;;
- esac
-
- ZVM_KEYS=
-}
-
-# Read keys for retrieving and executing a widget
-function zvm_readkeys_handler() {
- local keymap=${1}
- local keys=${2:-$KEYS}
- local key=
- local widget=
-
- # Get the keymap if keymap is empty
- if [[ -z $keymap ]]; then
- case "$ZVM_MODE" in
- $ZVM_MODE_INSERT) keymap=viins;;
- $ZVM_MODE_NORMAL) keymap=vicmd;;
- $ZVM_MODE_VISUAL|$ZVM_MODE_VISUAL_LINE) keymap=visual;;
- esac
- fi
-
- # Read keys and retrieve the widget
- zvm_readkeys $keymap $keys
- keys=${retval[1]}
- widget=${retval[2]}
- key=${retval[3]}
-
- # Escape space in keys
- keys=${keys//$ZVM_ESCAPE_SPACE/ }
- key=${key//$ZVM_ESCAPE_SPACE/ }
-
- ZVM_KEYS="${keys}"
-
- # If the widget is current handler, we should call the default handler
- if [[ "${widget}" == "${funcstack[1]}" ]]; then
- widget=
- fi
-
- # If the widget isn't matched, we should call the default handler
- if [[ -z ${widget} ]]; then
- zle zvm_default_handler "$key"
-
- # Push back to the key input stack
- if [[ -n "$ZVM_KEYS" ]]; then
- zle -U "$ZVM_KEYS"
- fi
- else
- zle $widget
- fi
-
- ZVM_KEYS=
-}
-
-# Find and move cursor to next character
-function zvm_find_and_move_cursor() {
- local char=$1
- local count=${2:-1}
- local forward=${3:-true}
- local skip=${4:-false}
- local cursor=$CURSOR
-
- [[ -z $char ]] && return 1
-
- # Find the specific character
- while :; do
- if $forward; then
- cursor=$((cursor+1))
- ((cursor > $#BUFFER)) && break
- else
- cursor=$((cursor-1))
- ((cursor < 0)) && break
- fi
- if [[ ${BUFFER[$cursor+1]} == $char ]]; then
- count=$((count-1))
- fi
- ((count == 0)) && break
- done
-
- [[ $count > 0 ]] && return 1
-
- # Skip the character
- if $skip; then
- if $forward; then
- cursor=$((cursor-1))
- else
- cursor=$((cursor+1))
- fi
- fi
-
- CURSOR=$cursor
-}
-
-# Handle the navigation action
-function zvm_navigation_handler() {
- # Return if no keys provided
- [[ -z $1 ]] && return 1
-
- local keys=$1
- local count=
- local cmd=
-
- # Retrieve the calling command
- if [[ $keys =~ '^([1-9][0-9]*)?([fFtT].?)$' ]]; then
- count=${match[1]:-1}
-
- # The length of keys must be 2
- if (( ${#match[2]} < 2)); then
- zvm_enter_oppend_mode
-
- read -k 1 cmd
- keys+=$cmd
-
- case "$(zvm_escape_non_printed_characters ${keys[-1]})" in
- $ZVM_VI_OPPEND_ESCAPE_BINDKEY) return 1;;
- esac
-
- zvm_exit_oppend_mode
- fi
-
- local forward=true
- local skip=false
-
- [[ ${keys[-2]} =~ '[FT]' ]] && forward=false
- [[ ${keys[-2]} =~ '[tT]' ]] && skip=true
-
- cmd=(zvm_find_and_move_cursor ${keys[-1]} $count $forward $skip)
- count=1
- else
- count=${keys:0:-1}
- case ${keys: -1} in
- '^') cmd=(zle vi-first-non-blank);;
- '$') cmd=(zle vi-end-of-line);;
- ' ') cmd=(zle vi-forward-char);;
- '0') cmd=(zle vi-digit-or-beginning-of-line);;
- 'h') cmd=(zle vi-backward-char);;
- 'j') cmd=(zle down-line-or-history);;
- 'k') cmd=(zle up-line-or-history);;
- 'l') cmd=(zle vi-forward-char);;
- 'w') cmd=(zle vi-forward-word);;
- 'W') cmd=(zle vi-forward-blank-word);;
- 'e') cmd=(zle vi-forward-word-end);;
- 'E') cmd=(zle vi-forward-blank-word-end);;
- 'b') cmd=(zle vi-backward-word);;
- 'B') cmd=(zle vi-backward-blank-word);;
- esac
- fi
-
- # Check widget if the widget is empty
- if [[ -z $cmd ]]; then
- return 0
- fi
-
- # Check if keys includes the count
- if [[ ! $count =~ ^[0-9]+$ ]]; then
- count=1
- fi
-
- # Call the widget, we can not use variable `i`, since
- # some widgets will affect the variable `i`, and it
- # will cause an infinite loop.
- local init_cursor=$CURSOR
- local last_cursor=$CURSOR
- local exit_code=0
- for ((c=0; c `word1`
- # c2[we] -> `word1 word2`
- # ve -> `word1`
- # v2e -> `word1 word2`
- # vw -> `word1 w`
- # v2w -> `word1 word2 w`
- # [dy]e -> `word1`
- # [dy]2e -> `word1 word2`
- # [dy]w -> `word1 `
- # [dy]2w -> `word1 word2 `
- # [cdyv]iw -> `word1`
- # [cdyv]aw -> `word1 `
- # [cdyv]2iw -> `word1 `
- # [cdyv]2aw -> `word1 word2 `
- #
- # 2. SAMPLE: `a bb c dd`, CURSOR: at `a`
- #
- # cw -> `a`
- # c2w -> `a bb`
- # ce -> `a bb`
- # c2e -> `a bb c`
- #
- # 3. SAMPLE: ` .foo. bar. baz.`, CURSOR: at `f`
- #
- # c[WE] -> `foo.`
- # c2[WE] -> `foo. bar.`
- # vE -> `foo.`
- # v2E -> `foo. bar.`
- # vW -> `foo. b`
- # v2W -> `foo. bar. b`
- # d2W -> `foo. bar. b`
- # [dy]E -> `foo.`
- # [dy]2E -> `foo. bar.`
- # [dy]W -> `foo. `
- # [dy]2W -> `foo. bar. `
- # [cdyv]iW -> `.foo.`
- # [cdyv]aW -> `.foo. `
- # [cdyv]2iW -> `.foo. `
- # [cdyv]2aW -> `.foo. bar. `
- #
- # 4. SAMPLE: ` .foo.bar.baz.`, CURSOR: at `r`
- #
- # [cdy]b -> `ba`
- # [cdy]B -> `.foo.ba`
- # vb -> `bar`
- # vB -> `.foo.bar`
- # vFf -> `foo.bar`
- # vTf -> `oo.bar`
- # [cdyv]fz -> `r.baz`
- # [cdy]Ff -> `foo.ba`
- # [cdyv]tz -> `r.ba`
- # [cdy]Tf -> `oo.ba`
- #
-
- # Pre navigation handling
- local navkey=
-
- if [[ $keys =~ '^c([1-9][0-9]*)?[ia][wW]$' ]]; then
- count=${match[1]:-1}
- navkey=${keys: -2}
- elif [[ $keys =~ '^[cdy]([1-9][0-9]*)?[ia][eE]$' ]]; then
- navkey=
- elif [[ $keys =~ '^c([1-9][0-9]*)?w$' ]]; then
- zle vi-backward-char
- count=${match[1]:-1}
- navkey='e'
- elif [[ $keys =~ '^c([1-9][0-9]*)?W$' ]]; then
- zle vi-backward-blank-char
- count=${match[1]:-1}
- navkey='E'
- elif [[ $keys =~ '^c([1-9][0-9]*)?e$' ]]; then
- count=${match[1]:-1}
- navkey='e'
- elif [[ $keys =~ '^c([1-9][0-9]*)?E$' ]]; then
- count=${match[1]:-1}
- navkey='E'
- elif [[ $keys =~ '^[cdy]([1-9][0-9]*)?[bB]$' ]]; then
- MARK=$((MARK-1))
- count=${match[1]:-1}
- navkey=${keys: -1}
- elif [[ $keys =~ '^[cdy]([1-9][0-9]*)?([FT].?)$' ]]; then
- MARK=$((MARK-1))
- count=${match[1]:-1}
- navkey=${match[2]}
- elif [[ $keys =~ '^[cdy]([1-9][0-9]*)?j$' ]]; then
- # Exit if there is no line below
- count=${match[1]:-1}
- for ((i=$((CURSOR+1)); i<=$#BUFFER; i++)); do
- [[ ${BUFFER[$i]} == $'\n' ]] && navkey='j'
- done
- elif [[ $keys =~ '^[cdy]([1-9][0-9]*)?k$' ]]; then
- # Exit if there is no line above
- count=${match[1]:-1}
- for ((i=$((CURSOR+1)); i>0; i--)); do
- [[ ${BUFFER[$i]} == $'\n' ]] && navkey='k'
- done
- elif [[ $keys =~ '^[cdy]([1-9][0-9]*)?h$' ]]; then
- MARK=$((MARK-1))
- count=${match[1]:-1}
- navkey='h'
-
- # Exit if the cursor is at the beginning of a line
- if ((MARK < 0)); then
- navkey=
- elif [[ ${BUFFER[$MARK+1]} == $'\n' ]]; then
- navkey=
- fi
- elif [[ $keys =~ '^[cdy]([1-9][0-9]*)?l$' ]]; then
- count=${match[1]:-1}
- count=$((count-1))
- navkey=${count}l
- elif [[ $keys =~ '^.([1-9][0-9]*)?([^0-9]+)$' ]]; then
- count=${match[1]:-1}
- navkey=${match[2]}
- else
- navkey=
- fi
-
- # Handle navigation
- case $navkey in
- '') exit_code=1;;
- *[ia][wW])
- local widget=
- local mark=
-
- # At least 1 time
- if [[ -z $count ]]; then
- count=1
- fi
-
- # Retrieve the widget
- case ${navkey: -2} in
- iw) widget=select-in-word;;
- aw) widget=select-a-word;;
- iW) widget=select-in-blank-word;;
- aW) widget=select-a-blank-word;;
- esac
-
- # Execute the widget for `count` times, and
- # save the `mark` position of the first time
- for ((c=0; c= $#BUFFER)); then
- break
- fi
- done
-
- MARK=$mark
- CURSOR=$((CURSOR-1))
- ;;
- *)
- local retval=
-
- # Prevent some actions(e.g. w, e) from affecting the auto
- # suggestion suffix
- BUFFER+=$'\0'
-
- if zvm_navigation_handler "${count}${navkey}"; then
- keys="${keys[1]}${retval}"
- else
- exit_code=1
- fi
-
- BUFFER[-1]=''
- ;;
- esac
-
- # Check if there is no range selected
- if [[ $exit_code != 0 ]]; then
- zvm_exit_visual_mode
- return
- fi
-
- # Post navigation handling
- if [[ $keys =~ '^[cdy]([1-9][0-9]*)?[ia][wW]$' ]]; then
- cursor=$MARK
- elif [[ $keys =~ '[dy]([1-9][0-9]*)?[wW]' ]]; then
- CURSOR=$((CURSOR-1))
- # If the CURSOR is at the newline character, we should
- # move backward a character
- if [[ "${BUFFER:$CURSOR:1}" == $'\n' ]]; then
- CURSOR=$((CURSOR-1))
- fi
- else
- cursor=$CURSOR
- fi
-
- # Handle operation
- case "${keys}" in
- c*) zvm_vi_change; cursor=;;
- d*) zvm_vi_delete; cursor=;;
- y*) zvm_vi_yank;;
- [vV]*) cursor=;;
- esac
-
- # Reset the repeat commands when it's changing or deleting
- if $ZVM_REPEAT_MODE; then
- zvm_exit_visual_mode false
- elif [[ $keys =~ '^[cd].*' ]]; then
- cmds+=($keys)
- zvm_reset_repeat_commands $cmds
- fi
-
- # Change the cursor position if the cursor is not null
- if [[ ! -z $cursor ]]; then
- CURSOR=$cursor
- fi
-}
-
-# Edit command line in EDITOR
-function zvm_vi_edit_command_line() {
- # Create a temporary file and save the BUFFER to it
- local tmp_file=$(mktemp ${ZVM_TMPDIR}/zshXXXXXX)
-
- # Some users may config the noclobber option to prevent from
- # overwriting existing files with the > operator, we should
- # use >! operator to ignore the noclobber.
- echo "$BUFFER" >! "$tmp_file"
-
- # Edit the file with the specific editor, in case of
- # the warning about input not from a terminal (e.g.
- # vim), we should tell the editor input is from the
- # terminal and not from standard input.
- "${(@Q)${(z)${ZVM_VI_EDITOR}}}" $tmp_file =0")
- local step=$($forward && echo 'i++' || echo 'i--')
- for (($init;$condition;$step)); do
- if [[ ${1:$i:$slen} == "$2" ]]; then
- pos=$i
- break
- fi
- done
- echo $pos
-}
-
-# Parse surround from keys
-function zvm_parse_surround_keys() {
- local keys=${1:-${$(zvm_keys)//$ZVM_ESCAPE_SPACE/ }}
- local action=
- local surround=
- case "${keys}" in
- vS*) action=S; surround=${keys:2};;
- vsa*) action=a; surround=${keys:3};;
- vys*) action=y; surround=${keys:3};;
- s[dr]*) action=${keys:1:1}; surround=${keys:2};;
- [acd]s*) action=${keys:0:1}; surround=${keys:2};;
- [cdvy][ia]*) action=${keys:0:2}; surround=${keys:2};;
- esac
- echo $action ${surround// /$ZVM_ESCAPE_SPACE}
-}
-
-# Move around code structure (e.g. (..), {..})
-function zvm_move_around_surround() {
- local slen=
- local bpos=-1
- local epos=-1
- for ((i=$CURSOR;i>=0;i--)); do
- # Check if it's one of the surrounds
- for s in {\',\",\`,\(,\[,\{,\<}; do
- slen=${#s}
- if [[ ${BUFFER:$i:$slen} == "$s" ]]; then
- bpos=$i
- break
- fi
- done
- if (($bpos == -1)); then
- continue
- fi
- # Search the nearest surround
- local ret=($(zvm_search_surround "$s"))
- if [[ -z ${ret[@]} ]]; then
- continue
- fi
- bpos=${ret[1]}
- epos=${ret[2]}
- # Move between the openning and close surrounds
- if (( $CURSOR > $((bpos-1)) )) && (( $CURSOR < $((bpos+slen)) )); then
- CURSOR=$epos
- else
- CURSOR=$bpos
- fi
- break
- done
-}
-
-# Match the surround pair from the part
-function zvm_match_surround() {
- local bchar=${1// /$ZVM_ESCAPE_SPACE}
- local echar=$bchar
- case $bchar in
- '(') echar=')';;
- '[') echar=']';;
- '{') echar='}';;
- '<') echar='>';;
- ')') bchar='(';echar=')';;
- ']') bchar='[';echar=']';;
- '}') bchar='{';echar='}';;
- '>') bchar='<';echar='>';;
- esac
- echo $bchar $echar
-}
-
-# Search surround from the string
-function zvm_search_surround() {
- local ret=($(zvm_match_surround "$1"))
- local bchar=${${ret[1]//$ZVM_ESCAPE_SPACE/ }:- }
- local echar=${${ret[2]//$ZVM_ESCAPE_SPACE/ }:- }
- local bpos=$(zvm_substr_pos $BUFFER $bchar $CURSOR false)
- local epos=$(zvm_substr_pos $BUFFER $echar $CURSOR true)
- if [[ $bpos == $epos ]]; then
- epos=$(zvm_substr_pos $BUFFER $echar $((CURSOR+1)) true)
- if [[ $epos == -1 ]]; then
- epos=$(zvm_substr_pos $BUFFER $echar $((CURSOR-1)) false)
- if [[ $epos != -1 ]]; then
- local tmp=$epos; epos=$bpos; bpos=$tmp
- fi
- fi
- fi
- if [[ $bpos == -1 ]] || [[ $epos == -1 ]]; then
- return
- fi
- echo $bpos $epos $bchar $echar
-}
-
-# Select surround and highlight it in visual mode
-function zvm_select_surround() {
- local ret=($(zvm_parse_surround_keys))
- local action=${ret[1]}
- local surround=${ret[2]//$ZVM_ESCAPE_SPACE/ }
- ret=($(zvm_search_surround ${surround}))
- if [[ ${#ret[@]} == 0 ]]; then
- zvm_exit_visual_mode
- return
- fi
- local bpos=${ret[1]}
- local epos=${ret[2]}
- if [[ ${action:1:1} == 'i' ]]; then
- ((bpos++))
- else
- ((epos++))
- fi
- MARK=$bpos; CURSOR=$epos-1
-
- # refresh current mode for prompt redraw
- zle reset-prompt
-}
-
-# Change surround in vicmd or visual mode
-function zvm_change_surround() {
- local ret=($(zvm_parse_surround_keys))
- local action=${1:-${ret[1]}}
- local surround=${2:-${ret[2]//$ZVM_ESCAPE_SPACE/ }}
- local bpos=${3} epos=${4}
- local is_appending=false
- case $action in
- S|y|a) is_appending=true;;
- esac
- if $is_appending; then
- if [[ -z $bpos && -z $epos ]]; then
- ret=($(zvm_selection))
- bpos=${ret[1]} epos=${ret[2]}
- fi
- else
- ret=($(zvm_search_surround "$surround"))
- (( ${#ret[@]} )) || return
- bpos=${ret[1]} epos=${ret[2]}
- zvm_highlight custom $bpos $(($bpos+1))
- zvm_highlight custom $epos $(($epos+1))
- fi
- local key=
- case $action in
- c|r)
- zvm_enter_oppend_mode
- read -k 1 key
- zvm_exit_oppend_mode
- ;;
- S|y|a)
- if [[ -z $surround ]]; then
- zvm_enter_oppend_mode
- read -k 1 key
- zvm_exit_oppend_mode
- else
- key=$surround
- fi
- if [[ $ZVM_MODE == $ZVM_MODE_VISUAL ]]; then
- zle visual-mode
- fi
- ;;
- esac
-
- # Check if it is ESCAPE key ( or ZVM_VI_ESCAPE_BINDKEY)
- case "$key" in
- $'\e'|"${ZVM_VI_ESCAPE_BINDKEY//\^\[/$'\e'}")
- zvm_highlight clear
- return
- esac
-
- # Start changing surround
- ret=($(zvm_match_surround "$key"))
- local bchar=${${ret[1]//$ZVM_ESCAPE_SPACE/ }:-$key}
- local echar=${${ret[2]//$ZVM_ESCAPE_SPACE/ }:-$key}
- local value=$($is_appending && echo 0 || echo 1 )
- local head=${BUFFER:0:$bpos}
- local body=${BUFFER:$((bpos+value)):$((epos-(bpos+value)))}
- local foot=${BUFFER:$((epos+value))}
- BUFFER="${head}${bchar}${body}${echar}${foot}"
-
- # Clear highliht
- zvm_highlight clear
-
- case $action in
- S|y|a) zvm_select_vi_mode $ZVM_MODE_NORMAL;;
- esac
-}
-
-# Change surround text object
-function zvm_change_surround_text_object() {
- local ret=($(zvm_parse_surround_keys))
- local action=${ret[1]}
- local surround=${ret[2]//$ZVM_ESCAPE_SPACE/ }
- ret=($(zvm_search_surround "${surround}"))
- if [[ ${#ret[@]} == 0 ]]; then
- zvm_select_vi_mode $ZVM_MODE_NORMAL
- return
- fi
- local bpos=${ret[1]}
- local epos=${ret[2]}
- if [[ ${action:1:1} == 'i' ]]; then
- ((bpos++))
- else
- ((epos++))
- fi
- CUTBUFFER=${BUFFER:$bpos:$(($epos-$bpos))}
- case ${action:0:1} in
- c)
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
- CURSOR=$bpos
- zvm_select_vi_mode $ZVM_MODE_INSERT
- ;;
- d)
- BUFFER="${BUFFER:0:$bpos}${BUFFER:$epos}"
- CURSOR=$bpos
- ;;
- esac
-}
-
-# Repeat last change
-function zvm_repeat_change() {
- ZVM_REPEAT_MODE=true
-
- local cmd=${ZVM_REPEAT_COMMANDS[2]}
-
- # Handle repeat command
- case $cmd in
- [aioAIO]) zvm_repeat_insert;;
- c) zvm_repeat_vi_change;;
- [cd]*) zvm_repeat_range_change;;
- R) zvm_repeat_replace;;
- r) zvm_repeat_replace_chars;;
- *) zle vi-repeat-change;;
- esac
-
- zle redisplay
-
- ZVM_REPEAT_MODE=false
-}
-
-# Repeat inserting characters
-function zvm_repeat_insert() {
- local cmd=${ZVM_REPEAT_COMMANDS[2]}
- local cmds=(${ZVM_REPEAT_COMMANDS[3,-1]})
-
- # Pre-handle the command
- case $cmd in
- a) CURSOR+=1;;
- o)
- zle vi-backward-char
- zle vi-end-of-line
- LBUFFER+=$'\n'
- ;;
- A)
- zle vi-end-of-line
- CURSOR=$((CURSOR+1))
- ;;
- I) zle vi-first-non-blank;;
- O)
- zle vi-digit-or-beginning-of-line
- LBUFFER+=$'\n'
- CURSOR=$((CURSOR-1))
- ;;
- esac
-
- # Insert characters
- for ((i=1; i<=${#cmds[@]}; i++)); do
- cmd="${cmds[$i]}"
-
- # Hanlde the backspace command
- if [[ $cmd == '' ]]; then
- if (($#LBUFFER > 0)); then
- LBUFFER=${LBUFFER:0:-1}
- fi
- continue
- fi
-
- # The length of character should be 1
- if (($#cmd == 1)); then
- LBUFFER+=$cmd
- fi
- done
-}
-
-# Repeat changing visual characters
-function zvm_repeat_vi_change() {
- local mode=${ZVM_REPEAT_COMMANDS[1]}
- local cmds=(${ZVM_REPEAT_COMMANDS[3,-1]})
-
- # Backward move cursor to the beginning of line
- if [[ $mode == $ZVM_MODE_VISUAL_LINE ]]; then
- zle vi-digit-or-beginning-of-line
- fi
-
- local ncount=${cmds[1]}
- local ccount=${cmds[2]}
- local pos=$CURSOR epos=$CURSOR
-
- # Forward expand the characters to the Nth newline character
- for ((i=0; i<$ncount; i++)); do
- pos=$(zvm_substr_pos $BUFFER $'\n' $pos)
- if [[ $pos == -1 ]]; then
- epos=$#BUFFER
- break
- fi
- pos=$((pos+1))
- epos=$pos
- done
-
- # Forward expand the remaining characters
- for ((i=0; i<$ccount; i++)); do
- local char=${BUFFER[$epos+i]}
- if [[ $char == $'\n' || $char == '' ]]; then
- ccount=$i
- break
- fi
- done
-
- epos=$((epos+ccount))
- RBUFFER=${RBUFFER:$((epos-CURSOR))}
-}
-
-# Repeat changing a range of characters
-function zvm_repeat_range_change() {
- local cmd=${ZVM_REPEAT_COMMANDS[2]}
-
- # Remove characters
- zvm_range_handler $cmd
-
- # Insert characters
- zvm_repeat_insert
-}
-
-# Repeat replacing
-function zvm_repeat_replace() {
- local cmds=(${ZVM_REPEAT_COMMANDS[3,-1]})
- local cmd=
- local cursor=$CURSOR
-
- for ((i=1; i<=${#cmds[@]}; i++)); do
- cmd="${cmds[$i]}"
-
- # If the cmd or the character at cursor is a newline character,
- # or the cursor is at the end of buffer, we should insert the
- # cmd instead of replacing with the cmd.
- if [[ $cmd == $'\n' ||
- $BUFFER[$cursor+1] == $'\n' ||
- $BUFFER[$cursor+1] == ''
- ]]; then
- LBUFFER+=$cmd
- else
- BUFFER[$cursor+1]=$cmd
- fi
-
- cursor=$((cursor+1))
- CURSOR=$cursor
- done
-
- # The cursor position should go back one character after
- # exiting the replace mode
- zle vi-backward-char
-}
-
-# Repeat replacing characters
-function zvm_repeat_replace_chars() {
- local mode=${ZVM_REPEAT_COMMANDS[1]}
- local cmds=(${ZVM_REPEAT_COMMANDS[3,-1]})
- local cmd=
-
- # Replacment of visual mode should move backward cursor to the
- # begin of current line, and replacing to the end of last line.
- if [[ $mode == $ZVM_MODE_VISUAL_LINE ]]; then
- zle vi-digit-or-beginning-of-line
- cmds+=($'\n')
- fi
-
- local cursor=$((CURSOR+1))
-
- for ((i=1; i<=${#cmds[@]}; i++)); do
- cmd="${cmds[$i]}"
-
- # If we meet a newline character in the buffer, we should keep
- # stop replacing, util we meet next newline character command.
- if [[ ${BUFFER[$cursor]} == $'\n' ]]; then
- if [[ $cmd == $'\n' ]]; then
- cursor=$((cursor+1))
- fi
- continue
- fi
-
- # A newline character command should keep replacing with last
- # character, until we meet a newline character in the buffer,
- # then we use next command.
- if [[ $cmd == $'\n' ]]; then
- i=$((i-1))
- cmd="${cmds[$i]}"
- fi
-
- # The length of character should be 1
- if (($#cmd == 1)); then
- BUFFER[$cursor]="${cmd}"
- fi
-
- cursor=$((cursor+1))
-
- # Break when it reaches the end
- if ((cursor > $#BUFFER)); then
- break
- fi
- done
-}
-
-# Select a word under the cursor
-function zvm_select_in_word() {
- local cursor=${1:-$CURSOR}
- local buffer=${2:-$BUFFER}
- local bpos=$cursor epos=$cursor
- local pattern='[0-9a-zA-Z_]'
-
- if ! [[ "${buffer:$cursor:1}" =~ $pattern ]]; then
- pattern="[^${pattern:1:-1} ]"
- fi
-
- for ((; $bpos>=0; bpos--)); do
- [[ "${buffer:$bpos:1}" =~ $pattern ]] || break
- done
- for ((; $epos<$#buffer; epos++)); do
- [[ "${buffer:$epos:1}" =~ $pattern ]] || break
- done
-
- bpos=$((bpos+1))
-
- # The ending position must be greater than 0
- if (( epos > 0 )); then
- epos=$((epos-1))
- fi
-
- echo $bpos $epos
-}
-
-# Switch keyword
-function zvm_switch_keyword() {
- local bpos= epos= cpos=$CURSOR
-
- # Cursor position cases:
- #
- # 1. Cursor on symbol:
- # 2+2 => +
- # 2-2 => -
- # 2 + 2 => +
- # 2 +2 => +2
- # 2 -2 => -2
- # 2 -a => -a
- #
- # 2. Cursor on number or alpha:
- # 2+2 => +2
- # 2-2 => -2
- # 2 + 2 => 2
- # 2 +2 => +2
- # 2 -2 => -2
- # 2 -a => -a
-
- # If cursor is on the `+` or `-`, we need to check if it is a
- # number with a sign or an operator, only the number needs to
- # forward the cursor.
- if [[ ${BUFFER:$cpos:2} =~ [+-][0-9] ]]; then
- if [[ $cpos == 0 || ${BUFFER:$((cpos-1)):1} =~ [^0-9] ]]; then
- cpos=$((cpos+1))
- fi
-
- # If cursor is on the `+` or `-`, we need to check if it is a
- # short option, only the short option needs to forward the cursor.
- elif [[ ${BUFFER:$cpos:2} =~ [+-][a-zA-Z] ]]; then
- if [[ $cpos == 0 || ${BUFFER:$((cpos-1)):1} == ' ' ]]; then
- cpos=$((cpos+1))
- fi
- fi
-
- local result=($(zvm_select_in_word $cpos))
- bpos=${result[1]} epos=$((${result[2]}+1))
-
- # Move backward the cursor
- if [[ $bpos != 0 && ${BUFFER:$((bpos-1)):1} == [+-] ]]; then
- bpos=$((bpos-1))
- fi
-
- local word=${BUFFER:$bpos:$((epos-bpos))}
- local keys=$(zvm_keys)
-
- if [[ $keys == '' ]]; then
- local increase=true
- else
- local increase=false
- fi
-
- # Execute extra commands
- for handler in $zvm_switch_keyword_handlers; do
- if ! zvm_exist_command ${handler}; then
- continue
- fi
-
- result=($($handler $word $increase));
-
- if (( $#result == 0 )); then
- continue
- fi
-
- epos=$(( bpos + ${result[3]} ))
- bpos=$(( bpos + ${result[2]} ))
-
- if (( cpos < bpos )) || (( cpos >= epos )); then
- continue
- fi
-
- BUFFER="${BUFFER:0:$bpos}${result[1]}${BUFFER:$epos}"
- CURSOR=$((bpos + ${#result[1]} - 1))
-
- zle reset-prompt
- return
- done
-}
-
-# Switch number keyword
-function zvm_switch_number {
- local word=$1
- local increase=${2:-true}
- local result= bpos= epos=
-
- # Hexadecimal
- if [[ $word =~ [^0-9]?(0[xX][0-9a-fA-F]*) ]]; then
- local number=${match[1]}
- local prefix=${number:0:2}
- bpos=$((mbegin-1)) epos=$mend
-
- # Hexadecimal cases:
- #
- # 1. Increment:
- # 0xDe => 0xdf
- # 0xdE => 0xDF
- # 0xde0 => 0xddf
- # 0xffffffffffffffff => 0x0000000000000000
- # 0X9 => 0XA
- # 0Xdf => 0Xe0
- #
- # 2. Decrement:
- # 0xdE0 => 0xDDF
- # 0xffFf0 => 0xfffef
- # 0xfffF0 => 0xFFFEF
- # 0x0 => 0xffffffffffffffff
- # 0X0 => 0XFFFFFFFFFFFFFFFF
- # 0Xf => 0Xe
-
- local lower=true
- if [[ $number =~ [A-Z][0-9]*$ ]]; then
- lower=false
- fi
-
- # Fix the number truncated after 15 digits issue
- if (( $#number > 17 )); then
- local d=$(($#number - 15))
- local h=${number:0:$d}
- number="0x${number:$d}"
- fi
-
- local p=$(($#number - 2))
-
- if $increase; then
- if (( $number == 0x${(l:15::f:)} )); then
- h=$(([##16]$h+1))
- h=${h: -1}
- number=${(l:15::0:)}
- else
- h=${h:2}
- number=$(([##16]$number + 1))
- fi
- else
- if (( $number == 0 )); then
- if (( ${h:-0} == 0 )); then
- h=f
- else
- h=$(([##16]$h-1))
- h=${h: -1}
- fi
- number=${(l:15::f:)}
- else
- h=${h:2}
- number=$(([##16]$number - 1))
- fi
- fi
-
- # Padding with zero
- if (( $#number < $p )); then
- number=${(l:$p::0:)number}
- fi
-
- result="${h}${number}"
-
- # Transform the case
- if $lower; then
- result="${(L)result}"
- fi
-
- result="${prefix}${result}"
-
- # Binary
- elif [[ $word =~ [^0-9]?(0[bB][01]*) ]]; then
- # Binary cases:
- #
- # 1. Increment:
- # 0b1 => 0b10
- # 0x1111111111111111111111111111111111111111111111111111111111111111 =>
- # 0x0000000000000000000000000000000000000000000000000000000000000000
- # 0B0 => 0B1
- #
- # 2. Decrement:
- # 0b1 => 0b0
- # 0b100 => 0b011
- # 0B010 => 0B001
- # 0b0 =>
- # 0x1111111111111111111111111111111111111111111111111111111111111111
-
- local number=${match[1]}
- local prefix=${number:0:2}
- bpos=$((mbegin-1)) epos=$mend
-
- # Fix the number truncated after 63 digits issue
- if (( $#number > 65 )); then
- local d=$(($#number - 63))
- local h=${number:0:$d}
- number="0b${number:$d}"
- fi
-
- local p=$(($#number - 2))
-
- if $increase; then
- if (( $number == 0b${(l:63::1:)} )); then
- h=$(([##2]$h+1))
- h=${h: -1}
- number=${(l:63::0:)}
- else
- h=${h:2}
- number=$(([##2]$number + 1))
- fi
- else
- if (( $number == 0b0 )); then
- if (( ${h:-0} == 0 )); then
- h=1
- else
- h=$(([##2]$h-1))
- h=${h: -1}
- fi
- number=${(l:63::1:)}
- else
- h=${h:2}
- number=$(([##2]$number - 1))
- fi
- fi
-
- # Padding with zero
- if (( $#number < $p )); then
- number=${(l:$p::0:)number}
- fi
-
- result="${prefix}${number}"
-
- # Decimal
- elif [[ $word =~ ([-+]?[0-9]+) ]]; then
- # Decimal cases:
- #
- # 1. Increment:
- # 0 => 1
- # 99 => 100
- #
- # 2. Decrement:
- # 0 => -1
- # 10 => 9
- # aa1230xa => aa1231xa
- # aa1230bb => aa1231bb
- # aa123a0bb => aa124a0bb
-
- local number=${match[1]}
- bpos=$((mbegin-1)) epos=$mend
-
- if $increase; then
- result=$(($number + 1))
- else
- result=$(($number - 1))
- fi
-
- # Check if need the plus sign prefix
- if [[ ${word:$bpos:1} == '+' ]]; then
- result="+${result}"
- fi
- fi
-
- if [[ $result ]]; then
- echo $result $bpos $epos
- fi
-}
-
-# Switch boolean keyword
-function zvm_switch_boolean() {
- local word=$1
- local increase=$2
- local result=
- local bpos=0 epos=$#word
-
- # Remove option prefix
- if [[ $word =~ (^[+-]{0,2}) ]]; then
- local prefix=${match[1]}
- bpos=$mend
- word=${word:$bpos}
- fi
-
- case ${(L)word} in
- true) result=false;;
- false) result=true;;
- yes) result=no;;
- no) result=yes;;
- on) result=off;;
- off) result=on;;
- y) result=n;;
- n) result=y;;
- t) result=f;;
- f) result=t;;
- *) return;;
- esac
-
- # Transform the case
- if [[ $word =~ ^[A-Z]+$ ]]; then
- result=${(U)result}
- elif [[ $word =~ ^[A-Z] ]]; then
- result=${(U)result:0:1}${result:1}
- fi
-
- echo $result $bpos $epos
-}
-
-# Switch weekday keyword
-function zvm_switch_weekday() {
- local word=$1
- local increase=$2
- local result=${(L)word}
- local weekdays=(
- sunday
- monday
- tuesday
- wednesday
- thursday
- friday
- saturday
- )
-
- local i=1
-
- for ((; i<=${#weekdays[@]}; i++)); do
- if [[ ${weekdays[i]:0:$#result} == ${result} ]]; then
- result=${weekdays[i]}
- break
- fi
- done
-
- # Return if no match
- if (( i > ${#weekdays[@]} )); then
- return
- fi
-
- if $increase; then
- if (( i == ${#weekdays[@]} )); then
- i=1
- else
- i=$((i+1))
- fi
- else
- if (( i == 1 )); then
- i=${#weekdays[@]}
- else
- i=$((i-1))
- fi
- fi
-
- # Abbreviation
- if (( $#result == $#word )); then
- result=${weekdays[i]}
- else
- result=${weekdays[i]:0:$#word}
- fi
-
- # Transform the case
- if [[ $word =~ ^[A-Z]+$ ]]; then
- result=${(U)result}
- elif [[ $word =~ ^[A-Z] ]]; then
- result=${(U)result:0:1}${result:1}
- fi
-
- echo $result 0 $#word
-}
-
-# Switch operator keyword
-function zvm_switch_operator() {
- local word=$1
- local increase=$2
- local result=
-
- case ${(L)word} in
- '&&') result='||';;
- '||') result='&&';;
- '++') result='--';;
- '--') result='++';;
- '==') result='!=';;
- '!=') result='==';;
- '===') result='!==';;
- '!==') result='===';;
- '+') result='-';;
- '-') result='*';;
- '*') result='/';;
- '/') result='+';;
- 'and') result='or';;
- 'or') result='and';;
- *) return;;
- esac
-
- # Transform the case
- if [[ $word =~ ^[A-Z]+$ ]]; then
- result=${(U)result}
- elif [[ $word =~ ^[A-Z] ]]; then
- result=${(U)result:0:1}${result:1}
- fi
-
- # Since the `echo` command can not print the character
- # `-`, here we use `printf` command alternatively.
- printf "%s 0 $#word" "${result}"
-}
-
-# Switch month keyword
-function zvm_switch_month() {
- local word=$1
- local increase=$2
- local result=${(L)word}
- local months=(
- january
- february
- march
- april
- may
- june
- july
- august
- september
- october
- november
- december
- )
-
- local i=1
-
- for ((; i<=${#months[@]}; i++)); do
- if [[ ${months[i]:0:$#result} == ${result} ]]; then
- result=${months[i]}
- break
- fi
- done
-
- # Return if no match
- if (( i > ${#months[@]} )); then
- return
- fi
-
- if $increase; then
- if (( i == ${#months[@]} )); then
- i=1
- else
- i=$((i+1))
- fi
- else
- if (( i == 1 )); then
- i=${#months[@]}
- else
- i=$((i-1))
- fi
- fi
-
- # Abbreviation
- if (( $#result == $#word )); then
- result=${months[i]}
- else
- result=${months[i]:0:$#word}
- fi
-
- # Transform the case
- if [[ $word =~ ^[A-Z]+$ ]]; then
- result=${(U)result}
- elif [[ $word =~ ^[A-Z] ]]; then
- result=${(U)result:0:1}${result:1}
- fi
-
- echo $result 0 $#word
-}
-
-# Highlight content
-function zvm_highlight() {
- local opt=${1:-mode}
- local region=()
- local redraw=false
-
- # Hanlde region by the option
- case "$opt" in
- mode)
- case "$ZVM_MODE" in
- $ZVM_MODE_VISUAL|$ZVM_MODE_VISUAL_LINE)
- local ret=($(zvm_calc_selection))
- local bpos=$((ret[1])) epos=$((ret[2]))
- local bg=$ZVM_VI_HIGHLIGHT_BACKGROUND
- local fg=$ZVM_VI_HIGHLIGHT_FOREGROUND
- local es=$ZVM_VI_HIGHLIGHT_EXTRASTYLE
- region=("$bpos $epos fg=$fg,bg=$bg,$es")
- ;;
- esac
- redraw=true
- ;;
- custom)
- local bpos=$2 epos=$3
- local bg=${4:-$ZVM_VI_HIGHLIGHT_BACKGROUND}
- local fg=${5:-$ZVM_VI_HIGHLIGHT_FOREGROUND}
- local es=${6:-$ZVM_VI_HIGHLIGHT_EXTRASTYLE}
- region=("${ZVM_REGION_HIGHLIGHT[@]}")
- region+=("$bpos $epos fg=$fg,bg=$bg,$es")
- redraw=true
- ;;
- clear)
- zle redisplay
- redraw=true
- ;;
- redraw) redraw=true;;
- esac
-
- # Update region highlight
- if (( $#region > 0 )) || [[ "$opt" == 'clear' ]]; then
-
- # Remove old region highlight
- local rawhighlight=()
- for ((i=1; i<=${#region_highlight[@]}; i++)); do
- local raw=true
- local spl=(${(@s/ /)region_highlight[i]})
- local pat="${spl[1]} ${spl[2]}"
- for ((j=1; j<=${#ZVM_REGION_HIGHLIGHT[@]}; j++)); do
- if [[ "$pat" == "${ZVM_REGION_HIGHLIGHT[j]:0:$#pat}" ]]; then
- raw=false
- break
- fi
- done
- if $raw; then
- rawhighlight+=("${region_highlight[i]}")
- fi
- done
-
- # Assign new region highlight
- ZVM_REGION_HIGHLIGHT=("${region[@]}")
- region_highlight=("${rawhighlight[@]}" "${ZVM_REGION_HIGHLIGHT[@]}")
- fi
-
- # Check if we need to refresh the region highlight
- if $redraw; then
- zle -R
- fi
-}
-
-# Enter the visual mode
-function zvm_enter_visual_mode() {
- local mode=
- local last_mode=$ZVM_MODE
- local last_region=
-
- # Exit the visual mode
- case $last_mode in
- $ZVM_MODE_VISUAL|$ZVM_MODE_VISUAL_LINE)
- last_region=($MARK $CURSOR)
- zvm_exit_visual_mode
- ;;
- esac
-
- case "${1:-$(zvm_keys)}" in
- v) mode=$ZVM_MODE_VISUAL;;
- V) mode=$ZVM_MODE_VISUAL_LINE;;
- *) mode=$last_mode;;
- esac
-
- # We should just exit the visual mdoe if current mode
- # is the same with last visual mode
- if [[ $last_mode == $mode ]]; then
- return
- fi
-
- zvm_select_vi_mode $mode
-
- # Recover the region when changing to another visual mode
- if [[ -n $last_region ]]; then
- MARK=$last_region[1]
- CURSOR=$last_region[2]
- zle redisplay
- fi
-}
-
-# Exit the visual mode
-function zvm_exit_visual_mode() {
- case "$ZVM_MODE" in
- $ZVM_MODE_VISUAL) zle visual-mode;;
- $ZVM_MODE_VISUAL_LINE) zle visual-line-mode;;
- esac
- zvm_highlight clear
- zvm_select_vi_mode $ZVM_MODE_NORMAL ${1:-true}
-}
-
-# Enter the vi insert mode
-function zvm_enter_insert_mode() {
- local keys=${1:-$(zvm_keys)}
-
- if [[ $keys == 'i' ]]; then
- ZVM_INSERT_MODE='i'
- elif [[ $keys == 'a' ]]; then
- ZVM_INSERT_MODE='a'
- if ! zvm_is_empty_line; then
- CURSOR=$((CURSOR+1))
- fi
- fi
-
- zvm_reset_repeat_commands $ZVM_MODE_NORMAL $ZVM_INSERT_MODE
- zvm_select_vi_mode $ZVM_MODE_INSERT
-}
-
-# Exit the vi insert mode
-function zvm_exit_insert_mode() {
- ZVM_INSERT_MODE=
- zvm_select_vi_mode $ZVM_MODE_NORMAL
-}
-
-# Enter the vi operator pending mode
-function zvm_enter_oppend_mode() {
- ZVM_OPPEND_MODE=true
- ${1:-true} && zvm_update_cursor
-}
-
-# Exit the vi operator pending mode
-function zvm_exit_oppend_mode() {
- ZVM_OPPEND_MODE=false
- ${1:-true} && zvm_update_cursor
-}
-
-# Insert at the beginning of the line
-function zvm_insert_bol() {
- ZVM_INSERT_MODE='I'
- zle vi-first-non-blank
- zvm_select_vi_mode $ZVM_MODE_INSERT
- zvm_reset_repeat_commands $ZVM_MODE_NORMAL $ZVM_INSERT_MODE
-}
-
-# Append at the end of the line
-function zvm_append_eol() {
- ZVM_INSERT_MODE='A'
- zle vi-end-of-line
- CURSOR=$((CURSOR+1))
- zvm_select_vi_mode $ZVM_MODE_INSERT
- zvm_reset_repeat_commands $ZVM_MODE_NORMAL $ZVM_INSERT_MODE
-}
-
-# Self insert content to cursor position
-function zvm_self_insert() {
- local keys=${1:-$KEYS}
-
- # Update the autosuggestion
- if [[ ${POSTDISPLAY:0:$#keys} == $keys ]]; then
- POSTDISPLAY=${POSTDISPLAY:$#keys}
- else
- POSTDISPLAY=
- fi
-
- LBUFFER+=${keys}
-}
-
-# Reset the repeat commands
-function zvm_reset_repeat_commands() {
- ZVM_REPEAT_RESET=true
- ZVM_REPEAT_COMMANDS=($@)
-}
-
-# Select vi mode
-function zvm_select_vi_mode() {
- local mode=$1
- local reset_prompt=${2:-true}
-
- # Check if current mode is the same with the new mode
- if [[ $mode == "$ZVM_MODE" ]]; then
- zvm_update_cursor
- mode=
- fi
-
- zvm_exec_commands 'before_select_vi_mode'
-
- # Some plugins would reset the prompt when we select the
- # keymap, so here we postpone executing reset-prompt.
- zvm_postpone_reset_prompt true
-
- # Exit operator pending mode
- if $ZVM_OPPEND_MODE; then
- zvm_exit_oppend_mode false
- fi
-
- case $mode in
- $ZVM_MODE_NORMAL)
- ZVM_MODE=$ZVM_MODE_NORMAL
- zvm_update_cursor
- zle vi-cmd-mode
- ;;
- $ZVM_MODE_INSERT)
- ZVM_MODE=$ZVM_MODE_INSERT
- zvm_update_cursor
- zle vi-insert
- ;;
- $ZVM_MODE_VISUAL)
- ZVM_MODE=$ZVM_MODE_VISUAL
- zvm_update_cursor
- zle visual-mode
- ;;
- $ZVM_MODE_VISUAL_LINE)
- ZVM_MODE=$ZVM_MODE_VISUAL_LINE
- zvm_update_cursor
- zle visual-line-mode
- ;;
- $ZVM_MODE_REPLACE)
- ZVM_MODE=$ZVM_MODE_REPLACE
- zvm_enter_oppend_mode
- ;;
- esac
-
- # This aspect provides you a moment to do something, such as
- # update the cursor, prompt and so on.
- zvm_exec_commands 'after_select_vi_mode'
-
- # Stop and trigger reset-prompt
- $reset_prompt && zvm_postpone_reset_prompt false true
-
- # Start the lazy keybindings when the first time entering the
- # normal mode, when the mode is the same as last mode, we get
- # empty value for $mode.
- if [[ $mode == $ZVM_MODE_NORMAL ]] &&
- (( $#ZVM_LAZY_KEYBINDINGS_LIST > 0 )); then
-
- zvm_exec_commands 'before_lazy_keybindings'
-
- # Here we should unset the list for normal keybindings
- local list=("${ZVM_LAZY_KEYBINDINGS_LIST[@]}")
- unset ZVM_LAZY_KEYBINDINGS_LIST
-
- for r in "${list[@]}"; do
- eval "zvm_bindkey ${r}"
- done
-
- zvm_exec_commands 'after_lazy_keybindings'
- fi
-}
-
-# Postpone reset prompt
-function zvm_postpone_reset_prompt() {
- local toggle=$1
- local force=$2
-
- if $toggle; then
- ZVM_POSTPONE_RESET_PROMPT=true
- else
- if [[ $ZVM_POSTPONE_RESET_PROMPT == false || $force ]]; then
- ZVM_POSTPONE_RESET_PROMPT=
- zle reset-prompt
- else
- ZVM_POSTPONE_RESET_PROMPT=
- fi
- fi
-}
-
-# Reset prompt
-function zvm_reset_prompt() {
- # Return if postponing is enabled
- if [[ -n $ZVM_POSTPONE_RESET_PROMPT ]]; then
- ZVM_POSTPONE_RESET_PROMPT=false
- return
- fi
-
- local -i retval
- if [[ -z "$rawfunc" ]]; then
- zle .reset-prompt -- "$@"
- else
- $rawfunc -- "$@"
- fi
-
- return retval
-}
-
-# Undo action in vi insert mode
-#
-# CTRL-U Remove all characters between the cursor position and
-# the beginning of the line. Previous versions of vim
-# deleted all characters on the line.
-function zvm_viins_undo() {
- if [[ $ZVM_VI_INS_LEGACY_UNDO ]]; then
- zvm_kill_line
- else
- zvm_backward_kill_line
- fi
-}
-
-function zvm_set_cursor() {
- # Term of vim isn't supported
- if [[ -n $VIMRUNTIME ]]; then
- return
- fi
-
- echo -ne "$1"
-}
-
-# Get the escape sequence of cursor style
-function zvm_cursor_style() {
- local style=${(L)1}
- local term=${2:-$ZVM_TERM}
-
- case $term in
- # For xterm and rxvt and their derivatives use the same escape
- # sequences as the VT520 terminal. And screen, konsole, alacritty
- # and st implement a superset of VT100 and VT100, they support
- # 256 colors the same way xterm does.
- xterm*|rxvt*|screen*|tmux*|konsole*|alacritty*|st*)
- case $style in
- $ZVM_CURSOR_BLOCK) style='\e[2 q';;
- $ZVM_CURSOR_UNDERLINE) style='\e[4 q';;
- $ZVM_CURSOR_BEAM) style='\e[6 q';;
- $ZVM_CURSOR_BLINKING_BLOCK) style='\e[1 q';;
- $ZVM_CURSOR_BLINKING_UNDERLINE) style='\e[3 q';;
- $ZVM_CURSOR_BLINKING_BEAM) style='\e[5 q';;
- $ZVM_CURSOR_USER_DEFAULT) style='\e[0 q';;
- esac
- ;;
- *) style='\e[0 q';;
- esac
-
- # Restore default cursor color
- if [[ $style == '\e[0 q' ]]; then
- local old_style=
-
- case $ZVM_MODE in
- $ZVM_MODE_INSERT) old_style=$ZVM_INSERT_MODE_CURSOR;;
- $ZVM_MODE_NORMAL) old_style=$ZVM_NORMAL_MODE_CURSOR;;
- $ZVM_MODE_OPPEND) old_style=$ZVM_OPPEND_MODE_CURSOR;;
- esac
-
- if [[ $old_style =~ '\e\][0-9]+;.+\a' ]]; then
- style=$style'\e\e]112\a'
- fi
- fi
-
- echo $style
-}
-
-# Update the cursor according current vi mode
-function zvm_update_cursor() {
-
- # Check if we need to update the cursor style
- $ZVM_CURSOR_STYLE_ENABLED || return
-
- local mode=$1
- local shape=
-
- # Check if it is operator pending mode
- if $ZVM_OPPEND_MODE; then
- mode=opp
- shape=$(zvm_cursor_style $ZVM_OPPEND_MODE_CURSOR)
- fi
-
- # Get cursor shape by the mode
- case "${mode:-$ZVM_MODE}" in
- $ZVM_MODE_NORMAL)
- shape=$(zvm_cursor_style $ZVM_NORMAL_MODE_CURSOR)
- ;;
- $ZVM_MODE_INSERT)
- shape=$(zvm_cursor_style $ZVM_INSERT_MODE_CURSOR)
- ;;
- $ZVM_MODE_VISUAL)
- shape=$(zvm_cursor_style $ZVM_VISUAL_MODE_CURSOR)
- ;;
- $ZVM_MODE_VISUAL_LINE)
- shape=$(zvm_cursor_style $ZVM_VISUAL_LINE_MODE_CURSOR)
- ;;
- esac
-
- if [[ $shape ]]; then
- zvm_set_cursor $shape
- fi
-}
-
-# Updates highlight region
-function zvm_update_highlight() {
- case "$ZVM_MODE" in
- $ZVM_MODE_VISUAL|$ZVM_MODE_VISUAL_LINE)
- zvm_highlight
- ;;
- esac
-}
-
-# Updates repeat commands
-function zvm_update_repeat_commands() {
- # We don't need to update the repeat commands if current
- # mode is already the repeat mode.
- $ZVM_REPEAT_MODE && return
-
- # We don't need to update the repeat commands if it is
- # reseting the repeat commands.
- if $ZVM_REPEAT_RESET; then
- ZVM_REPEAT_RESET=false
- return
- fi
-
- # We update the repeat commands when it's the insert mode
- [[ $ZVM_MODE == $ZVM_MODE_INSERT ]] || return
-
- local char=$KEYS
-
- # If current key is an arrow key, we should do something
- if [[ "$KEYS" =~ '\[[ABCD]' ]]; then
- # If last key is also an arrow key, we just replace it
- if [[ ${ZVM_REPEAT_COMMANDS[-1]} =~ '\[[ABCD]' ]]; then
- ZVM_REPEAT_COMMANDS=(${ZVM_REPEAT_COMMANDS[@]:0:-1})
- fi
- else
- # If last command is arrow key movement, we should reset
- # the repeat commands with i(nsert) command
- if [[ ${ZVM_REPEAT_COMMANDS[-1]} =~ '\[[ABCD]' ]]; then
- zvm_reset_repeat_commands $ZVM_MODE_NORMAL i
- fi
- char=${BUFFER[$CURSOR]}
- fi
-
- # If current key is backspace key, we should remove last
- # one, until it has only the mode and inital command
- if [[ "$KEYS" == '' ]]; then
- if ((${#ZVM_REPEAT_COMMANDS[@]} > 2)) &&
- [[ ${ZVM_REPEAT_COMMANDS[-1]} != '' ]]; then
- ZVM_REPEAT_COMMANDS=(${ZVM_REPEAT_COMMANDS[@]:0:-1})
- elif (($#LBUFFER > 0)); then
- ZVM_REPEAT_COMMANDS+=($KEYS)
- fi
- else
- ZVM_REPEAT_COMMANDS+=($char)
- fi
-}
-
-# Updates editor information when line pre redraw
-function zvm_zle-line-pre-redraw() {
- # Fix cursor style is not updated in tmux environment, when
- # there are one more panel in the same window, the program
- # in other panel could change the cursor shape, we need to
- # update cursor style when line is redrawing.
- if [[ -n $TMUX ]]; then
- zvm_update_cursor
- # Fix display is not updated in the terminal of IntelliJ IDE.
- # We should update display only when the last widget isn't a
- # completion widget
- [[ $LASTWIDGET =~ 'complet' ]] || zle redisplay
- fi
- zvm_update_highlight
- zvm_update_repeat_commands
-}
-
-# Start every prompt in the correct vi mode
-function zvm_zle-line-init() {
- # Save last mode
- local mode=${ZVM_MODE:-$ZVM_MODE_INSERT}
-
- # It's neccessary to set to insert mode when line init
- # and we don't need to reset prompt.
- zvm_select_vi_mode $ZVM_MODE_INSERT false
-
- # Select line init mode and reset prompt
- case ${ZVM_LINE_INIT_MODE:-$mode} in
- $ZVM_MODE_INSERT) zvm_select_vi_mode $ZVM_MODE_INSERT;;
- *) zvm_select_vi_mode $ZVM_MODE_NORMAL;;
- esac
-}
-
-# Restore the user default cursor style after prompt finish
-function zvm_zle-line-finish() {
- # When we start a program (e.g. vim, bash, etc.) from the
- # command line, the cursor style is inherited by other
- # programs, so that we need to reset the cursor style to
- # default before executing a command and set the custom
- # style again when the command exits. This way makes any
- # other interactive CLI application would not be affected
- # by it.
- local shape=$(zvm_cursor_style $ZVM_CURSOR_USER_DEFAULT)
- zvm_set_cursor $shape
-}
-
-# Initialize vi-mode for widgets, keybindings, etc.
-function zvm_init() {
- # Check if it has been initalized
- if $ZVM_INIT_DONE; then
- return;
- fi
-
- # Mark plugin initial status
- ZVM_INIT_DONE=true
-
- zvm_exec_commands 'before_init'
-
- # Correct the readkey engine
- case $ZVM_READKEY_ENGINE in
- $ZVM_READKEY_ENGINE_NEX|$ZVM_READKEY_ENGINE_ZLE);;
- *)
- echo -n "Warning: Unsupported readkey engine! "
- echo "ZVM_READKEY_ENGINE=$ZVM_READKEY_ENGINE"
- ZVM_READKEY_ENGINE=$ZVM_READKEY_ENGINE_DEFAULT
- ;;
- esac
-
- # Reduce ESC delay (zle default is 0.4 seconds)
- # Set to 0.01 second delay for taking over the key input processing
- case $ZVM_READKEY_ENGINE in
- $ZVM_READKEY_ENGINE_NEX) KEYTIMEOUT=1;;
- $ZVM_READKEY_ENGINE_ZLE) KEYTIMEOUT=$(($ZVM_KEYTIMEOUT*100));;
- esac
-
- # Create User-defined widgets
- zvm_define_widget zvm_default_handler
- zvm_define_widget zvm_readkeys_handler
- zvm_define_widget zvm_backward_kill_region
- zvm_define_widget zvm_backward_kill_line
- zvm_define_widget zvm_forward_kill_line
- zvm_define_widget zvm_kill_line
- zvm_define_widget zvm_viins_undo
- zvm_define_widget zvm_select_surround
- zvm_define_widget zvm_change_surround
- zvm_define_widget zvm_move_around_surround
- zvm_define_widget zvm_change_surround_text_object
- zvm_define_widget zvm_enter_insert_mode
- zvm_define_widget zvm_exit_insert_mode
- zvm_define_widget zvm_enter_visual_mode
- zvm_define_widget zvm_exit_visual_mode
- zvm_define_widget zvm_enter_oppend_mode
- zvm_define_widget zvm_exit_oppend_mode
- zvm_define_widget zvm_exchange_point_and_mark
- zvm_define_widget zvm_open_line_below
- zvm_define_widget zvm_open_line_above
- zvm_define_widget zvm_insert_bol
- zvm_define_widget zvm_append_eol
- zvm_define_widget zvm_self_insert
- zvm_define_widget zvm_vi_replace
- zvm_define_widget zvm_vi_replace_chars
- zvm_define_widget zvm_vi_substitute
- zvm_define_widget zvm_vi_substitute_whole_line
- zvm_define_widget zvm_vi_change
- zvm_define_widget zvm_vi_change_eol
- zvm_define_widget zvm_vi_delete
- zvm_define_widget zvm_vi_yank
- zvm_define_widget zvm_vi_put_after
- zvm_define_widget zvm_vi_put_before
- zvm_define_widget zvm_vi_up_case
- zvm_define_widget zvm_vi_down_case
- zvm_define_widget zvm_vi_opp_case
- zvm_define_widget zvm_vi_edit_command_line
- zvm_define_widget zvm_repeat_change
- zvm_define_widget zvm_switch_keyword
-
- # Override standard widgets
- zvm_define_widget zle-line-pre-redraw zvm_zle-line-pre-redraw
-
- # Ensure the correct cursor style when an interactive program
- # (e.g. vim, bash, etc.) starts and exits
- zvm_define_widget zle-line-init zvm_zle-line-init
- zvm_define_widget zle-line-finish zvm_zle-line-finish
-
- # Override reset-prompt widget
- zvm_define_widget reset-prompt zvm_reset_prompt
-
- # All Key bindings
- # Emacs-like bindings
- # Normal editing
- zvm_bindkey viins '^A' beginning-of-line
- zvm_bindkey viins '^E' end-of-line
- zvm_bindkey viins '^B' backward-char
- zvm_bindkey viins '^F' forward-char
- zvm_bindkey viins '^K' zvm_forward_kill_line
- zvm_bindkey viins '^W' backward-kill-word
- zvm_bindkey viins '^U' zvm_viins_undo
- zvm_bindkey viins '^Y' yank
- zvm_bindkey viins '^_' undo
-
- # Mode agnostic editing
- zvm_bindkey viins '^[[H' beginning-of-line
- zvm_bindkey vicmd '^[[H' beginning-of-line
- zvm_bindkey viins '^[[F' end-of-line
- zvm_bindkey vicmd '^[[F' end-of-line
- zvm_bindkey viins '^[[3~' delete-char
- zvm_bindkey vicmd '^[[3~' delete-char
-
- # History search
- zvm_bindkey viins '^R' history-incremental-search-backward
- zvm_bindkey viins '^S' history-incremental-search-forward
- zvm_bindkey viins '^P' up-line-or-history
- zvm_bindkey viins '^N' down-line-or-history
-
- # Insert mode
- zvm_bindkey vicmd 'i' zvm_enter_insert_mode
- zvm_bindkey vicmd 'a' zvm_enter_insert_mode
- zvm_bindkey vicmd 'I' zvm_insert_bol
- zvm_bindkey vicmd 'A' zvm_append_eol
-
- # Other key bindings
- zvm_bindkey vicmd 'v' zvm_enter_visual_mode
- zvm_bindkey vicmd 'V' zvm_enter_visual_mode
- zvm_bindkey visual 'o' zvm_exchange_point_and_mark
- zvm_bindkey vicmd 'o' zvm_open_line_below
- zvm_bindkey vicmd 'O' zvm_open_line_above
- zvm_bindkey vicmd 'r' zvm_vi_replace_chars
- zvm_bindkey vicmd 'R' zvm_vi_replace
- zvm_bindkey vicmd 's' zvm_vi_substitute
- zvm_bindkey vicmd 'S' zvm_vi_substitute_whole_line
- zvm_bindkey vicmd 'C' zvm_vi_change_eol
- zvm_bindkey visual 'c' zvm_vi_change
- zvm_bindkey visual 'd' zvm_vi_delete
- zvm_bindkey visual 'y' zvm_vi_yank
- zvm_bindkey vicmd 'p' zvm_vi_put_after
- zvm_bindkey vicmd 'P' zvm_vi_put_before
- zvm_bindkey visual 'U' zvm_vi_up_case
- zvm_bindkey visual 'u' zvm_vi_down_case
- zvm_bindkey visual '~' zvm_vi_opp_case
- zvm_bindkey visual 'v' zvm_vi_edit_command_line
- zvm_bindkey vicmd '.' zvm_repeat_change
-
- zvm_bindkey vicmd '^A' zvm_switch_keyword
- zvm_bindkey vicmd '^X' zvm_switch_keyword
-
- # Keybindings for escape key and some specials
- local exit_oppend_mode_widget=
- local exit_insert_mode_widget=
- local exit_visual_mode_widget=
- local default_handler_widget=
-
- case $ZVM_READKEY_ENGINE in
- $ZVM_READKEY_ENGINE_NEX)
- exit_oppend_mode_widget=zvm_readkeys_handler
- exit_insert_mode_widget=zvm_readkeys_handler
- exit_visual_mode_widget=zvm_readkeys_handler
- ;;
- $ZVM_READKEY_ENGINE_ZLE)
- exit_insert_mode_widget=zvm_exit_insert_mode
- exit_visual_mode_widget=zvm_exit_visual_mode
- default_handler_widget=zvm_default_handler
- ;;
- esac
-
- # Bind custom escape key
- zvm_bindkey vicmd "$ZVM_VI_OPPEND_ESCAPE_BINDKEY" $exit_oppend_mode_widget
- zvm_bindkey viins "$ZVM_VI_INSERT_ESCAPE_BINDKEY" $exit_insert_mode_widget
- zvm_bindkey visual "$ZVM_VI_VISUAL_ESCAPE_BINDKEY" $exit_visual_mode_widget
-
- # Bind the default escape key if the escape key is not the default
- case "$ZVM_VI_OPPEND_ESCAPE_BINDKEY" in
- '^['|'\e') ;;
- *) zvm_bindkey vicmd '^[' $exit_oppend_mode_widget;;
- esac
- case "$ZVM_VI_INSERT_ESCAPE_BINDKEY" in
- '^['|'\e') ;;
- *) zvm_bindkey viins '^[' $exit_insert_mode_widget;;
- esac
- case "$ZVM_VI_VISUAL_ESCAPE_BINDKEY" in
- '^['|'\e') ;;
- *) zvm_bindkey visual '^[' $exit_visual_mode_widget;;
- esac
-
- # Bind and overwrite original y/d/c of vicmd
- for c in {y,d,c}; do
- zvm_bindkey vicmd "$c" $default_handler_widget
- done
-
- # Surround text-object
- # Enable surround text-objects (quotes, brackets)
- local surrounds=()
-
- # Append brackets
- for s in ${(s..)^:-'()[]{}<>'}; do
- surrounds+=($s)
- done
-
- # Append quotes
- for s in {\',\",\`,\ ,'^['}; do
- surrounds+=($s)
- done
-
- # Append for escaping visual mode
- if $is_custom_escape_key; then
- surrounds+=("$ZVM_VI_ESCAPE_BINDKEY")
- fi
-
- # Surround key bindings
- for s in $surrounds; do
- for c in {a,i}${s}; do
- zvm_bindkey visual "$c" zvm_select_surround
- done
- for c in {c,d,y}{a,i}${s}; do
- zvm_bindkey vicmd "$c" zvm_change_surround_text_object
- done
- if [[ $ZVM_VI_SURROUND_BINDKEY == 's-prefix' ]]; then
- for c in s{d,r}${s}; do
- zvm_bindkey vicmd "$c" zvm_change_surround
- done
- for c in sa${s}; do
- zvm_bindkey visual "$c" zvm_change_surround
- done
- else
- for c in {d,c}s${s}; do
- zvm_bindkey vicmd "$c" zvm_change_surround
- done
- for c in {S,ys}${s}; do
- zvm_bindkey visual "$c" zvm_change_surround
- done
- fi
- done
-
- # Moving around surrounds
- zvm_bindkey vicmd '%' zvm_move_around_surround
-
- # Fix BACKSPACE was stuck in zsh
- # Since normally '^?' (backspace) is bound to vi-backward-delete-char
- zvm_bindkey viins '^?' backward-delete-char
-
- # Enable vi keymap
- bindkey -v
-
- zvm_exec_commands 'after_init'
-}
-
-# Check if a command is existed
-function zvm_exist_command() {
- command -v "$1" >/dev/null
-}
-
-# Execute commands
-function zvm_exec_commands() {
- local commands="zvm_${1}_commands"
- commands=(${(P)commands})
-
- # Execute the default command
- if zvm_exist_command "zvm_$1"; then
- eval "zvm_$1" ${@:2}
- fi
-
- # Execute extra commands
- for cmd in $commands; do
- if zvm_exist_command ${cmd}; then
- cmd="$cmd ${@:2}"
- fi
- eval $cmd
- done
-}
-
-# Initialize this plugin according to the mode
-case $ZVM_INIT_MODE in
- sourcing) zvm_init;;
- *) precmd_functions+=(zvm_init);;
-esac
-