aboutsummaryrefslogtreecommitdiff
path: root/.config/emacs/lisp/evil
diff options
context:
space:
mode:
Diffstat (limited to '.config/emacs/lisp/evil')
-rw-r--r--.config/emacs/lisp/evil/.dir-locals.el3
-rw-r--r--.config/emacs/lisp/evil/.gitattributes1
-rw-r--r--.config/emacs/lisp/evil/.github/ISSUE_TEMPLATE.md29
-rw-r--r--.config/emacs/lisp/evil/.github/workflows/test.yml58
-rw-r--r--.config/emacs/lisp/evil/.gitignore27
-rw-r--r--.config/emacs/lisp/evil/.readthedocs.yaml17
-rw-r--r--.config/emacs/lisp/evil/CHANGES.org56
-rw-r--r--.config/emacs/lisp/evil/CONTRIBUTING.md56
-rw-r--r--.config/emacs/lisp/evil/COPYING674
-rw-r--r--.config/emacs/lisp/evil/Eask57
-rw-r--r--.config/emacs/lisp/evil/Makefile80
-rw-r--r--.config/emacs/lisp/evil/README.md83
-rw-r--r--.config/emacs/lisp/evil/doc/Makefile20
-rw-r--r--.config/emacs/lisp/evil/doc/front.pngbin0 -> 3258 bytes
-rw-r--r--.config/emacs/lisp/evil/doc/logo.pngbin0 -> 2147 bytes
-rw-r--r--.config/emacs/lisp/evil/doc/logo.svg110
-rw-r--r--.config/emacs/lisp/evil/doc/make.bat35
-rw-r--r--.config/emacs/lisp/evil/doc/requirements.txt2
-rw-r--r--.config/emacs/lisp/evil/doc/source/_ext/elisp.py289
-rw-r--r--.config/emacs/lisp/evil/doc/source/conf.py85
-rw-r--r--.config/emacs/lisp/evil/doc/source/extension.rst146
-rw-r--r--.config/emacs/lisp/evil/doc/source/faq.rst118
-rw-r--r--.config/emacs/lisp/evil/doc/source/hooks.rst16
-rw-r--r--.config/emacs/lisp/evil/doc/source/index.rst21
-rw-r--r--.config/emacs/lisp/evil/doc/source/indices.rst6
-rw-r--r--.config/emacs/lisp/evil/doc/source/internals.rst36
-rw-r--r--.config/emacs/lisp/evil/doc/source/keymaps.rst145
-rw-r--r--.config/emacs/lisp/evil/doc/source/license.rst447
-rw-r--r--.config/emacs/lisp/evil/doc/source/overview.rst117
-rw-r--r--.config/emacs/lisp/evil/doc/source/settings.rst199
-rw-r--r--.config/emacs/lisp/evil/evil-command-window.el191
-rw-r--r--.config/emacs/lisp/evil/evil-commands.el5288
-rw-r--r--.config/emacs/lisp/evil/evil-common.el3843
-rw-r--r--.config/emacs/lisp/evil/evil-core.el1322
-rw-r--r--.config/emacs/lisp/evil/evil-development.el50
-rw-r--r--.config/emacs/lisp/evil/evil-digraphs.el1735
-rw-r--r--.config/emacs/lisp/evil/evil-ex.el940
-rw-r--r--.config/emacs/lisp/evil/evil-integration.el468
-rw-r--r--.config/emacs/lisp/evil/evil-jumps.el358
-rw-r--r--.config/emacs/lisp/evil/evil-keybindings.el124
-rw-r--r--.config/emacs/lisp/evil/evil-macros.el772
-rw-r--r--.config/emacs/lisp/evil/evil-maps.el686
-rw-r--r--.config/emacs/lisp/evil/evil-repeat.el641
-rw-r--r--.config/emacs/lisp/evil/evil-search.el1249
-rw-r--r--.config/emacs/lisp/evil/evil-states.el930
-rw-r--r--.config/emacs/lisp/evil/evil-test-helpers.el416
-rw-r--r--.config/emacs/lisp/evil/evil-tests.el10130
-rw-r--r--.config/emacs/lisp/evil/evil-types.el465
-rw-r--r--.config/emacs/lisp/evil/evil-vars.el2121
-rw-r--r--.config/emacs/lisp/evil/evil.el158
-rwxr-xr-x.config/emacs/lisp/evil/scripts/evil-extract-docstrings41
-rwxr-xr-x.config/emacs/lisp/evil/scripts/evil-release-stable52
-rwxr-xr-x.config/emacs/lisp/evil/scripts/evilupdate177
53 files changed, 35090 insertions, 0 deletions
diff --git a/.config/emacs/lisp/evil/.dir-locals.el b/.config/emacs/lisp/evil/.dir-locals.el
new file mode 100644
index 0000000..d79ba71
--- /dev/null
+++ b/.config/emacs/lisp/evil/.dir-locals.el
@@ -0,0 +1,3 @@
+;; Don't use tabs for el files
+((emacs-lisp-mode .
+ ((indent-tabs-mode . nil))))
diff --git a/.config/emacs/lisp/evil/.gitattributes b/.config/emacs/lisp/evil/.gitattributes
new file mode 100644
index 0000000..b362cfa
--- /dev/null
+++ b/.config/emacs/lisp/evil/.gitattributes
@@ -0,0 +1 @@
+*.el diff=lisp
diff --git a/.config/emacs/lisp/evil/.github/ISSUE_TEMPLATE.md b/.config/emacs/lisp/evil/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..53cbe14
--- /dev/null
+++ b/.config/emacs/lisp/evil/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,29 @@
+<!-- Replace every comment and delete this line -->
+# Issue type
+
+<!-- Pick one of the following, delete the rest -->
+- Bug report
+- Enhancement request
+- Question
+- Other
+
+# Environment
+
+Emacs version: <!-- M-x emacs-version -->
+Operating System: <!-- Name and version, e.g. Windows 10, macOS Sierra, Debian Jessie -->
+Evil version: <!-- M-x evil-version -->
+Evil installation type: <!-- MELPA, MELPA stable, NonGNU ELPA, Quelpa, El-Get, manual -->
+Graphical/Terminal: <!-- Whether you're running Emacs in a terminal emulator or under X -->
+Tested in a `make emacs` session (see [CONTRIBUTING.md](https://github.com/emacs-evil/evil/blob/master/CONTRIBUTING.md#bug-reports)): <!-- Yes / No -->
+
+# Reproduction steps
+- Start Emacs
+<!-- Minimal list of steps to reproduce the bug, preferably using `make emacs`: https://github.com/emacs-evil/evil/blob/master/CONTRIBUTING.md#bug-reports -->
+
+# Expected behavior
+<!-- Describe how it should behave -->
+
+# Actual behavior
+<!-- Describe how it does behave -->
+
+# Further notes
diff --git a/.config/emacs/lisp/evil/.github/workflows/test.yml b/.config/emacs/lisp/evil/.github/workflows/test.yml
new file mode 100644
index 0000000..d73cf73
--- /dev/null
+++ b/.config/emacs/lisp/evil/.github/workflows/test.yml
@@ -0,0 +1,58 @@
+name: CI
+
+on: [push, pull_request]
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ continue-on-error: ${{ matrix.experimental }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ emacs-version:
+ - 26.3
+ - 27.2
+ - 28.2
+ - 29.4
+ experimental: [false]
+ include:
+ - os: ubuntu-latest
+ emacs-version: snapshot
+ experimental: true
+ - os: macos-latest
+ emacs-version: snapshot
+ experimental: true
+ exclude:
+ - os: macos-latest
+ emacs-version: 26.3
+ - os: macos-latest
+ emacs-version: 27.2
+
+ steps:
+ - uses: jcs090218/setup-emacs@master
+ with:
+ version: ${{ matrix.emacs-version }}
+
+ - uses: actions/checkout@v4
+
+ - name: Print emacs version
+ run: |
+ emacs --version
+
+ - uses: emacs-eask/setup-eask@master
+ with:
+ version: 'snapshot'
+
+ - name: Run tests
+ run: |
+ make test
+
+ - name: Print results
+ if: ${{ always() }}
+ run: |
+ cat test-results.txt
diff --git a/.config/emacs/lisp/evil/.gitignore b/.config/emacs/lisp/evil/.gitignore
new file mode 100644
index 0000000..c5b19d7
--- /dev/null
+++ b/.config/emacs/lisp/evil/.gitignore
@@ -0,0 +1,27 @@
+*.elc
+*.cp
+*.ky
+*.pg
+*.tp
+.depend
+/evil-autoloads.el
+/evil-pkg.el
+test-results.txt
+typescript
+
+/doc/dir
+/doc/*.aux
+/doc/*.fn
+/doc/*.fns
+/doc/*.info
+/doc/*.log
+/doc/*.toc
+/doc/*.vr
+/doc/*.vrs
+/doc/docstringdb.json
+/doc/build/*/
+!/doc/build/texinfo/evil.texi
+*.pyc
+
+/.eask
+/dist
diff --git a/.config/emacs/lisp/evil/.readthedocs.yaml b/.config/emacs/lisp/evil/.readthedocs.yaml
new file mode 100644
index 0000000..f4b346b
--- /dev/null
+++ b/.config/emacs/lisp/evil/.readthedocs.yaml
@@ -0,0 +1,17 @@
+version: 2
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.12"
+ apt_packages: [emacs-nox]
+ jobs:
+ pre_build:
+ - scripts/evil-extract-docstrings
+
+sphinx:
+ configuration: doc/source/conf.py
+
+python:
+ install:
+ - requirements: doc/requirements.txt
diff --git a/.config/emacs/lisp/evil/CHANGES.org b/.config/emacs/lisp/evil/CHANGES.org
new file mode 100644
index 0000000..102c6ab
--- /dev/null
+++ b/.config/emacs/lisp/evil/CHANGES.org
@@ -0,0 +1,56 @@
+* Changes and New Features in Evil
+
+** News in 1.0.7
+
+ * Fix #319.
+
+** News in 1.0.6
+
+ * Fix bug induced in emacs trunk due to changed behaviour of
+ `overriding-terminal-local-map` (fixes #309).
+
+** News in 1.0.5
+
+ * Fix bug in `show-paren-mode` due to variable renaming in latest
+ emacs.
+
+ * Fix bug in isearch module due to variable renaming in latest
+ emacs.
+
+** News in 1.0.4
+
+ * Undo one restriction when <c> argument is read in operator state.
+
+** News in 1.0.3
+
+ * Fix `evil-delete-backward-word` at first non-blank in a line.
+
+** News in 1.0.2
+
+ * Fix #290.
+
+** News in 1.0.1
+
+*** Improvements
+
+ * An ELPA package built by =make elpa= contains COPYING file.
+
+ * Bind =[tab]= like =\t= in =evil-ex-completion-map=, so that it
+ cannot be overwritten by a =[tab]= binding in the parent keymap
+ =minibuffer-local-completion-map=.
+
+ * Improve worst case performance of internal functions
+ =evil-in-string-p=, =evil-string-beginning= and
+ =evil-string-end=. This functions are used, e.g., in certain text
+ objects to detect whether point is within a string.
+
+ * Update authors list.
+
+*** Fixes
+
+ * The interactive code =<state>= is fixed and used correctly in
+ =evil-ex-set-initial-state=.
+
+ * =evil-ex-global= always generates a single undo-step.
+
+ * Resolved issues: #249, #250, #253 and #257.
diff --git a/.config/emacs/lisp/evil/CONTRIBUTING.md b/.config/emacs/lisp/evil/CONTRIBUTING.md
new file mode 100644
index 0000000..913a5e2
--- /dev/null
+++ b/.config/emacs/lisp/evil/CONTRIBUTING.md
@@ -0,0 +1,56 @@
+# Bug reports
+
+Bug reports and feature requests should be made on the
+[issue tracker](https://github.com/emacs-evil/evil/issues) here on github.
+
+**Before** sending a bug report, please take note of the following comments.
+
+1. Please provide a full description of the configuration of your
+ system. This includes
+
+ - Emacs version,
+ - Evil version (e.g., the hash in the git repository),
+ - Whether you use Emacs/Evil in X mode or in terminal mode,
+ - Whether you use Emacs/Evil in terminal mode with some terminal multiplexer
+ like **tmux** or **screen** (and see below).
+
+2. Test the bug in a clean Emacs environment without any additional
+ packages loaded (besides Evil itself). You can easily get such an
+ environment by executing either `make emacs` (for X) or `make
+ terminal` (for terminal mode) in Evil's source directory. If your
+ bug is related to some other package, try to load only this package
+ from the clean environment after using `M-x package-initialize`
+ first.
+
+3. If you've just updated your Evil from the repository, **do not forget to
+ recompile** Evil by executing `make` in Evil's source directory.
+
+4. If possible, try to give a minimal example how to reproduce the error
+ starting from a fresh Emacs. The minimal example could be some buffer content
+ and a sequence of key-strokes that show up the error.
+
+5. If the bug you want to report is related to the behavior of some commands or
+ motions, please note the following. One goal of Evil is to get a behavior as
+ close to **Vim** as possible unless there is a good reason not to do so. The
+ reason is that many users come from Vim or use both, Vim and Evil, and we
+ want to keep the number of annoying differences between both as small as
+ possible, especially in common commands. In case you get an unexpected
+ behavior, please compare the behavior with plain Vim (i.e., without any
+ customization), if there's a difference please file the bug with a
+ description of this difference (and possibly a reference to Vim's
+ documentation). If you realize that both, Vim and Evil, behave the same but
+ you want a different behavior, you may make a **feature request** for some
+ customization option (but the default behavior will probably not be changed
+ in favor for Vim compatibility). Evil already contains several customization
+ options and sometimes the desired changes can be achieved as easily as
+ redefining some key-bindings.
+
+# Pull Requests
+
+1. Please follow the
+ [Emacs Lisp Style Guide](https://github.com/bbatsov/emacs-lisp-style-guide/)
+2. When in doubt, adhere to the style conventions in the source code,
+ but don't be afraid of suggesting code enhancements in case you
+ encounter suboptimal code.
+3. If your pull requests adds a feature or fixes a regression, add
+ tests covering it to `evil-tests.el`.
diff --git a/.config/emacs/lisp/evil/COPYING b/.config/emacs/lisp/evil/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/.config/emacs/lisp/evil/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/.config/emacs/lisp/evil/Eask b/.config/emacs/lisp/evil/Eask
new file mode 100644
index 0000000..77bf0c7
--- /dev/null
+++ b/.config/emacs/lisp/evil/Eask
@@ -0,0 +1,57 @@
+;; -*- mode: eask; lexical-binding: t -*-
+
+(package "evil"
+ "1.15.0"
+ "Extensible vi layer")
+
+(website-url "https://github.com/emacs-evil/evil")
+(keywords "emulations")
+
+(package-file "evil.el")
+(files "evil-*.el" '(:exclude "*-tests.el" "*-pkg.el"))
+
+(script "test" "echo \"Error: no test specified\" && exit 1")
+
+(source 'gnu)
+(source 'melpa)
+
+(depends-on "emacs" "24.1")
+(depends-on "cl-lib")
+(depends-on "goto-chg")
+(depends-on "nadvice")
+
+(setq network-security-level 'low) ; see https://github.com/jcs090218/setup-emacs-windows/issues/156#issuecomment-932956432
+
+(eask-defcommand test
+ "Basic tests."
+ (require 'evil-tests)
+ (evil-tests-initialize nil nil))
+
+(eask-defcommand terminal
+ "Load Evil in a terminal Emacs and run all tests."
+ (require 'evil-tests)
+ (evil-tests-initialize nil nil t))
+
+(eask-defcommand profiler
+ "Run all tests with profiler."
+ (require 'evil-tests)
+ (evil-mode 1)
+ (evil-tests-initialize nil t))
+
+(eask-defcommand indent
+ "Re-indent all Evil code."
+ (setq vc-handled-backends nil)
+ (dolist (file (eask-package-el-files)) (load file))
+ (dolist (buffer (reverse (buffer-list)))
+ (when (buffer-file-name buffer)
+ (set-buffer buffer)
+ (message "Indenting %s" (current-buffer))
+ (setq-default indent-tabs-mode nil)
+ (untabify (point-min) (point-max))
+ (indent-region (point-min) (point-max))
+ (delete-trailing-whitespace)
+ (untabify (point-min) (point-max))
+ (goto-char (point-min))
+ (while (re-search-forward "\\n\\\\{3,\\\\}" nil t)
+ (replace-match "\\n\\n"))
+ (when (buffer-modified-p) (save-buffer 0)))))
diff --git a/.config/emacs/lisp/evil/Makefile b/.config/emacs/lisp/evil/Makefile
new file mode 100644
index 0000000..6dd8f25
--- /dev/null
+++ b/.config/emacs/lisp/evil/Makefile
@@ -0,0 +1,80 @@
+EMACS ?= emacs
+SED ?= sed
+FILES = $(filter-out evil-test-helpers.el evil-tests.el evil-pkg.el,$(wildcard evil*.el))
+VERSION := $(shell $(SED) -n '/^;\+ \+Version: *\(.*\)/{s//\1/p;q}' evil.el)
+PROFILER =
+TAG =
+EASK ?= eask
+
+ELCFILES = $(FILES:.el=.elc)
+
+.PHONY: all compile docstrings doc clean tests test emacs term terminal profiler indent elpa version
+
+# Byte-compile Evil.
+all: compile
+
+compile:
+ $(EASK) compile
+
+# Documentation.
+docstrings:
+ @$(EMACS) --script scripts/evil-extract-docstrings
+
+doc: docstrings
+ @$(MAKE) -C doc texinfo
+
+info: doc
+ @$(MAKE) -C doc info
+
+# Delete byte-compiled files etc.
+clean:
+ $(EASK) clean all
+
+# Run tests.
+# The TAG variable may specify a test tag or a test name:
+# make test TAG=repeat
+# This will only run tests pertaining to the repeat system.
+test:
+ $(EASK) run command test
+
+# Byte-compile Evil and run all tests.
+tests: compile
+ $(EASK) run command test
+ $(EASK) clean elc
+ rm -f .depend
+
+# Load Evil in a fresh instance of Emacs and run all tests.
+emacs:
+ $(EMACS) -Q -L . -l evil-tests.el \
+ --eval "(evil-mode 1)" \
+ --eval "(evil-tests-initialize '(${TAG}) '(${PROFILER}) t)"
+
+# Load Evil in a terminal Emacs and run all tests.
+term terminal:
+ $(EASK) run command terminal
+
+# Run all tests with profiler.
+profiler:
+ $(EASK) run command profiler
+
+# Re-indent all Evil code.
+# Loads Evil into memory in order to indent macros properly.
+# Also removes trailing whitespace, tabs and extraneous blank lines.
+indent: clean
+ $(EASK) run command indent
+
+evil-pkg.el: evil.el
+ $(EMACS) --batch -l package $^ \
+ --eval "(package-generate-description-file (package-buffer-info) \"$@\")"
+
+# Create an ELPA package.
+elpa: evil-pkg.el
+ $(EASK) package
+
+# Change the version using make VERSION=x.y.z
+version:
+ @$(EMACS) --script scripts/evilupdate "${VERSION}"
+
+# Change the version using make VERSION=x.y.z, but do not post to the newsgroup
+nversion:
+ @$(EMACS) --script scripts/evilupdate nonews "${VERSION}"
diff --git a/.config/emacs/lisp/evil/README.md b/.config/emacs/lisp/evil/README.md
new file mode 100644
index 0000000..b753ef5
--- /dev/null
+++ b/.config/emacs/lisp/evil/README.md
@@ -0,0 +1,83 @@
+![An extensible vi layer for Emacs](https://raw.githubusercontent.com/emacs-evil/evil/master/doc/logo.png)
+
+[![Build status](https://github.com/emacs-evil/evil/actions/workflows/test.yml/badge.svg)](https://github.com/emacs-evil/evil/actions/workflows/test.yml)
+[![MELPA](https://melpa.org/packages/evil-badge.svg)](https://melpa.org/#/evil)
+[![MELPA Stable](https://stable.melpa.org/packages/evil-badge.svg)](https://stable.melpa.org/#/evil)
+[![NonGNU ELPA](http://elpa.nongnu.org/nongnu/evil.svg)](http://elpa.nongnu.org/nongnu/evil.html)
+[![Documentation Status](https://readthedocs.org/projects/evil/badge/?version=latest)](https://evil.readthedocs.io/en/latest/?badge=latest)
+[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
+
+Evil is an **e**xtensible **vi** **l**ayer
+for [Emacs](http://www.gnu.org/software/emacs/). It emulates the main features
+of [Vim](http://www.vim.org/), and provides facilities for writing custom
+extensions. Also see our page on [EmacsWiki](http://emacswiki.org/emacs/Evil).
+
+# Installation
+
+See the
+[official documentation](https://evil.readthedocs.io/en/latest/overview.html#installation-via-package-el)
+for installation instructions. We recommend using *package.el*.
+
+As a quickstart, you can add the following code to your Emacs init
+file.
+
+```elisp
+;; Set up package.el to work with MELPA
+(require 'package)
+(add-to-list 'package-archives
+ '("melpa" . "https://melpa.org/packages/"))
+(package-initialize)
+(package-refresh-contents)
+
+;; Download Evil
+(unless (package-installed-p 'evil)
+ (package-install 'evil))
+
+;; Enable Evil
+(require 'evil)
+(evil-mode 1)
+```
+
+## Dependencies
+
+* Evil requires Emacs 24.1 or later.
+
+* Evil requires any of the following for `C-r`:
+ * `undo-redo` from Emacs 28
+ * The [undo-tree] package (available via GNU ELPA)
+ * The [undo-fu] package (available via MELPA and NonGNU ELPA)
+
+* For the motions `g;` `g,` and for the last-change-register `.`, Evil
+ requires the [goto-chg.el](https://github.com/emacs-evil/goto-chg)
+ package (available via MELPA and NonGNU ELPA), which provides the
+ functions `goto-last-change` and `goto-last-change-reverse`.
+
+* For Emacs 24.1 and 24.2 Evil also requires
+ [cl-lib](https://elpa.gnu.org/packages/cl-lib.html).
+
+# Documentation
+
+The latest version of the documentation is readable online
+[here](https://evil.readthedocs.io/en/latest/index.html). It is also
+available as
+[PDF](https://evil.readthedocs.io/_/downloads/en/stable/pdf/) and
+as [EPUB](https://evil.readthedocs.io/_/downloads/en/stable/epub/).
+
+# Mailing list
+
+Evil is discussed at the
+[gmane.emacs.vim-emulation](http://lists.ourproject.org/cgi-bin/mailman/listinfo/implementations-list)
+mailing list.
+
+# IRC
+
+Visit us on `irc.libera.chat #evil-mode`.
+
+# Contribution
+
+See
+[CONTRIBUTING.md](https://github.com/emacs-evil/evil/blob/master/CONTRIBUTING.md)
+for guidelines for issues and pull requests.
+
+[undo-tree]: https://gitlab.com/tsc25/undo-tree
+[undo-fu]: https://codeberg.org/ideasman42/emacs-undo-fu
diff --git a/.config/emacs/lisp/evil/doc/Makefile b/.config/emacs/lisp/evil/doc/Makefile
new file mode 100644
index 0000000..d0c3cbf
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/.config/emacs/lisp/evil/doc/front.png b/.config/emacs/lisp/evil/doc/front.png
new file mode 100644
index 0000000..f79a67e
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/front.png
Binary files differ
diff --git a/.config/emacs/lisp/evil/doc/logo.png b/.config/emacs/lisp/evil/doc/logo.png
new file mode 100644
index 0000000..842a49d
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/logo.png
Binary files differ
diff --git a/.config/emacs/lisp/evil/doc/logo.svg b/.config/emacs/lisp/evil/doc/logo.svg
new file mode 100644
index 0000000..ff833c2
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/logo.svg
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="127.82534"
+ height="62.426407"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.0 r9654"
+ sodipodi:docname="evil.svg"
+ inkscape:export-filename="/home/vegard/evil.png"
+ inkscape:export-xdpi="150"
+ inkscape:export-ydpi="150">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.2069466"
+ inkscape:cx="173.13654"
+ inkscape:cy="12.652914"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1680"
+ inkscape:window-height="998"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ fit-margin-left="10"
+ fit-margin-top="10"
+ fit-margin-right="10"
+ fit-margin-bottom="10"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-165.00893,-164.53963)">
+ <rect
+ style="fill:#000000"
+ id="rect2991"
+ width="30.809652"
+ height="42.426407"
+ x="175.00893"
+ y="174.53963" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
+ x="178.15302"
+ y="209.50504"
+ id="text2985"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan2987"
+ x="178.15302"
+ y="209.50504"
+ style="font-weight:bold;letter-spacing:5.28999996px;-inkscape-font-specification:Ubuntu Bold"><tspan
+ style="letter-spacing:6.60000228999999994px;fill:#ffffff"
+ id="tspan2989">E</tspan><tspan
+ style="fill:#333333"
+ id="tspan2995">VIL</tspan></tspan></text>
+ <g
+ style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
+ id="text2997"
+ transform="matrix(0.89694705,0.44213798,-0.44213798,0.89694705,260.2961,-122.4502)">
+ <path
+ d="m 144.8919,272.13985 c 0.57684,-0.24621 1.4908,-0.78829 1.94103,-1.23149 0.46429,-0.46428 0.81251,-0.98134 1.04466,-1.55116 0.23214,-0.5698 0.33721,-0.99165 0.33722,-1.62479 0.0155,-0.43449 -0.28674,-1.22826 -0.57298,-1.8313 -0.26496,-0.55821 -0.52007,-1.02571 -0.52007,-1.02571 l -1.99277,2.29588 0.22983,-5.91917 5.5976,0.45081 -2.34283,1.96492 c 0,0 0.49752,1.04212 0.73633,1.68916 0.23881,0.64704 0.58739,1.34614 0.66973,2.19566 0.0366,0.62546 -0.16181,1.70241 -0.4854,2.4903 -0.33767,0.79493 -0.81956,1.50544 -1.44564,2.13152 -0.59093,0.58389 -1.53465,1.17717 -2.35067,1.54297"
+ style="fill:#333333"
+ id="path3002"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccscsccccczcccc" />
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+ x="309.28571"
+ y="111.6479"
+ id="text3011"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3013"
+ x="309.28571"
+ y="111.6479" /></text>
+ </g>
+</svg>
diff --git a/.config/emacs/lisp/evil/doc/make.bat b/.config/emacs/lisp/evil/doc/make.bat
new file mode 100644
index 0000000..6247f7e
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/.config/emacs/lisp/evil/doc/requirements.txt b/.config/emacs/lisp/evil/doc/requirements.txt
new file mode 100644
index 0000000..4e09d9c
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/requirements.txt
@@ -0,0 +1,2 @@
+Sphinx==7.3.7
+sphinx-rtd-theme==2.0.0
diff --git a/.config/emacs/lisp/evil/doc/source/_ext/elisp.py b/.config/emacs/lisp/evil/doc/source/_ext/elisp.py
new file mode 100644
index 0000000..ab82105
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/_ext/elisp.py
@@ -0,0 +1,289 @@
+import re
+from os import path
+import json
+
+from sphinx import addnodes
+from sphinx.domains import Domain, ObjType, Index
+from sphinx.domains.std import StandardDomain
+from sphinx.directives import ObjectDescription
+from sphinx.roles import XRefRole
+from sphinx.util.nodes import make_refnode
+
+
+with open(path.join(path.dirname(__file__), '..', '..', 'docstringdb.json')) as f:
+ DATA = json.load(f)
+
+
+re_evilcode = re.compile(r"‘(evil-[^’]*)’")
+re_code = re.compile(r"‘([^:][^ ’]*)’")
+re_kwd = re.compile(r"‘(:[^’]*)’")
+re_item = re.compile(r"([^\n])\n- ")
+re_sexp = re.compile(r"\([A-Z \-\.‘’\[\]]+\)|[A-Z\-]+")
+re_capitals = re.compile(r"[A-Z\-]+")
+re_nonspace = re.compile(r"[^ ]")
+re_signature = re.compile(r'\(fn (.*)\)')
+
+emphasis = [
+ 'thing-at-point',
+]
+
+def emacs_is_local(var):
+ return DATA[var]['local']
+
+def emacs_default_value(var):
+ default = DATA[var]['default']
+ tp = DATA[var]['default-type']
+ if tp == 'string':
+ rep = repr(default)[1:-1]
+ return f'"{rep}"'
+ return str(default)
+
+def process_docstring(docstring, capitals=None):
+ # Remove explicit signature
+ docstring = re_signature.sub('', docstring)
+
+ # Add code blocks to indented sections
+ def blockified_lines(lines):
+ in_block = False
+ for line in lines:
+ try:
+ indented = next(re_nonspace.finditer(line)).start(0) >= 4
+ except StopIteration:
+ indented = None
+ if indented is True and not in_block:
+ yield '.. code-block:: elisp'
+ yield ''
+ in_block = True
+ elif indented is False:
+ in_block = False
+ yield line
+ docstring = '\n'.join(blockified_lines(docstring.split('\n')))
+
+ # Substitute `evil-alpha' with :elisp:ref:`evil-alpha`
+ docstring = re_evilcode.sub(r':elisp:ref:`\1`', docstring)
+
+ # Substitute `alpha' with ``alpha``
+ docstring = re_code.sub(r'``\1``', docstring)
+
+ # Substitute `:alpha' with ``alpha``
+ docstring = re_kwd.sub(r'``\1``', docstring)
+
+ # Add empty line between list items
+ docstring = re_item.sub(r'\1\n\n- ', docstring)
+
+ if capitals is None:
+ capitals = []
+ else:
+ capitals = list(capitals)
+
+ # Find things that look like sexps
+ def substitute_sexp(match):
+ s = match.group(0)
+ if re_capitals.match(s):
+ if s in capitals:
+ return f'*{s}*'
+ return s
+ else:
+ capitals.extend(re_capitals.findall(s))
+ return f'``{s}``'
+ docstring = re_sexp.sub(substitute_sexp, docstring)
+
+ # Italicize some words
+ for s in emphasis:
+ docstring = docstring.replace(s, f'*{s}*')
+
+ return docstring
+
+def emacs_variable_docstring(var):
+ docstring = DATA[var]['var-docstring']
+ return process_docstring(docstring)
+
+def emacs_function_docstring(var):
+ docstring = DATA[var]['fn-docstring']
+ return process_docstring(docstring, capitals=emacs_argnames(var))
+
+def emacs_argnames(var):
+ arglist = emacs_arglist(var)
+ return re_capitals.findall(arglist)
+
+def emacs_arglist(var):
+ docstring = DATA[var]['fn-docstring']
+ match = re_signature.search(docstring)
+ if match:
+ return match.group(1)
+
+ arglist = [arg.upper() for arg in DATA[var]['arglist']]
+ state = None
+ ret = ''
+ for arg in arglist:
+ if arg in ('&REST', '&OPTIONAL'):
+ if state == '&OPTIONAL':
+ ret += ']'
+ state = arg
+ ret += ' ['
+ continue
+ ret += ('' if state in ('&REST', '&OPTIONAL') else ' ') + arg
+ if state == '&OPTIONAL':
+ state += '-CONT'
+ if state is not None and state.startswith('&OPTIONAL'):
+ ret += ']'
+ if state == '&REST':
+ ret += '...]'
+ return ret
+
+
+class AbstractElisp(ObjectDescription):
+
+ def add_target_and_index(self, name, sig, signode):
+ anchor = f'elispobj-{sig}'
+ signode['ids'].append(anchor)
+
+ objs = self.env.domaindata['elisp']['objects']
+ objs[sig] = {
+ 'docname': self.env.docname,
+ 'anchor': f'elispobj-{sig}',
+ 'type': self.object_type,
+ }
+
+
+class AbstractVariable(AbstractElisp):
+ object_type = 'variable'
+
+ def handle_signature(self, sig, signode):
+ signode += addnodes.desc_annotation(sig, sig)
+ return sig
+
+ def run(self):
+ extra = []
+
+ default = self.default_value()
+ if default:
+ extra.append(f'Default: ``{default}``')
+ if self.is_buffer_local():
+ extra.append('buffer-local')
+
+ self.content.data.extend(['', ', '.join(extra)])
+ retval = super().run()
+ return retval
+
+
+class Variable(AbstractVariable):
+ required_arguments = 1
+ optional_arguments = 2
+
+ def default_value(self):
+ try:
+ return self.arguments[1]
+ except IndexError:
+ return None
+
+ def is_buffer_local(self):
+ return 'bufloc' in self.arguments[1:]
+
+
+class AutoVariable(AbstractVariable):
+ required_arguments = 1
+
+ def is_buffer_local(self):
+ return emacs_is_local(self.arguments[0])
+
+ def default_value(self):
+ return emacs_default_value(self.arguments[0])
+
+ def run(self):
+ docstring = emacs_variable_docstring(self.arguments[0])
+ self.content.data.extend(docstring.split('\n'))
+ return super().run()
+
+
+class AutoFunction(AbstractElisp):
+ required_arguments = 1
+
+ @property
+ def object_type(self):
+ return 'macro' if DATA[self.arguments[0]]['macrop'] else 'function'
+
+ def handle_signature(self, sig, signode):
+ args = emacs_arglist(sig)
+ signode += addnodes.desc_annotation(sig, f'({sig} {args})')
+ return sig
+
+ def run(self):
+ docstring = emacs_function_docstring(self.arguments[0])
+ self.content.data.extend(docstring.split('\n'))
+ return super().run()
+
+
+class ElispIndex(Index):
+ name = 'index'
+ localname = 'Emacs lisp functions and variables'
+ shortname = 'Elisp'
+
+ def generate(self, docnames=None):
+ index = {}
+ for name, item in self.domain.data['objects'].items():
+ if name.startswith('evil-'):
+ letter = name[5].upper()
+ else:
+ letter = name[0].upper()
+ index.setdefault(letter, []).append((
+ name,
+ 0,
+ item['docname'],
+ item['anchor'],
+ item['type'],
+ '',
+ '',
+ ))
+
+ index = {k: sorted(v, key=lambda k: k[0].lower()) for k, v in index.items()}
+ index = list(index.items())
+ index = sorted(index, key=lambda k: k[0])
+ return index, True
+
+
+class Elisp(Domain):
+ name = 'elisp'
+ label = 'Emacs lisp'
+
+ object_types = {
+ 'variable': ObjType('variable', 'variable', 'obj'),
+ 'autovariable': ObjType('autovariable', 'autovariable', 'obj'),
+ 'autofunction': ObjType('autofunction', 'autofunction', 'obj'),
+ }
+
+ directives = {
+ 'variable': Variable,
+ 'autovariable': AutoVariable,
+ 'autofunction': AutoFunction,
+ }
+
+ roles = {
+ 'ref': XRefRole(),
+ }
+
+ initial_data = {
+ 'objects': {},
+ }
+
+ indices = {
+ ElispIndex,
+ }
+
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
+ obj = self.data['objects'].get(target, None)
+ if obj is None:
+ return None
+ return make_refnode(builder, fromdocname, obj['docname'], obj['anchor'], contnode, obj['anchor'])
+
+
+def setup(app):
+ app.add_domain(Elisp)
+ StandardDomain.initial_data['labels']['elispindex'] = ('elisp-index', '', 'Emacs lisp functions and variables')
+ StandardDomain.initial_data['anonlabels']['elispindex'] = ('elisp-index', '')
+
+ return {
+ 'version': '0.1',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
diff --git a/.config/emacs/lisp/evil/doc/source/conf.py b/.config/emacs/lisp/evil/doc/source/conf.py
new file mode 100644
index 0000000..5b1b6f5
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/conf.py
@@ -0,0 +1,85 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+#
+
+import os, sys
+sys.path.append(os.path.abspath("./_ext"))
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'Evil'
+copyright = '2011-2019, Eivind Fonn, Frank Fischer, Vegard Øye'
+author = 'Eivind Fonn, Frank Fischer, Vegard Øye'
+
+# The full version, including alpha/beta/rc tags
+release = '1.15.0'
+
+master_doc = 'index'
+
+
+latex_elements = {
+ 'fontpkg': r'\usepackage{palatino} \usepackage{inconsolata}',
+ 'maketitle': r"""
+ \newcommand\sphinxbackoftitlepage{{
+ Copyright {copyright}.
+
+ \begin{{quote}}
+ Permission is granted to copy, distribute and/or modify this
+ document under the terms of the GNU Free Documentation License,
+ Version 1.3 or any later version published by the Free Software
+ Foundation; with no Invariant Sections, no Front-Cover Texts,
+ and no Back-Cover Texts. A copy of the license is included in
+ the section entitled ``GNU Free Documentation License''.
+ \end{{quote}}
+
+ The Evil team thanks everyone at gmane.emacs.vim-emulation for
+ their feedback and contributions.
+ }}
+ \sphinxmaketitle
+ """.format(copyright=copyright),
+}
+
+
+texinfo_documents = [
+ (master_doc, 'evil', 'Evil documentation', author, 'evil',
+ 'Extensible vi layer for Emacs', 'Emacs'),
+]
+
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'elisp',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = []
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'sphinx_rtd_theme'
diff --git a/.config/emacs/lisp/evil/doc/source/extension.rst b/.config/emacs/lisp/evil/doc/source/extension.rst
new file mode 100644
index 0000000..444502f
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/extension.rst
@@ -0,0 +1,146 @@
+Extension
+=========
+
+The main functionality of Evil is implemented in terms of reusable
+macros. Package writers can use these to define new commands.
+
+
+Motions
+-------
+
+A *motion* is a command which moves the cursor, such as :kbd:`w` or
+:kbd:`e`. Motions are defined with the macro
+:elisp:ref:`evil-define-motion`. Motions not defined in this way
+should be declared with :elisp:ref:`evil-declare-motion`.
+
+.. elisp:autofunction:: evil-declare-motion
+
+.. elisp:autofunction:: evil-define-motion
+
+For example, this is a motion that moves the cursor forward by a
+number of characters:
+
+.. code-block:: elisp
+
+ (evil-define-motion foo-forward (count)
+ "Move to the right by COUNT characters."
+ :type inclusive
+ (forward-char (or count 1)))
+
+The *type* of a motion determines how it works when used together with
+an operator. Inclusive motions include the endpoint in the range
+being operated on, while exclusive motions do not. Line motions
+extend the whole range to linewise positions, effectively behaving as
+if the endpoint were really at the end of the line. Blockwise ranges
+behave as a "rectangle" on screen rather than a contiguous range of
+characters.
+
+
+Operators
+---------
+
+An operator is a command that acts on the text moved over by a motion,
+such as :kbd:`c` (change), :kbd:`d` (delete) or :kbd:`y` (yank or
+copy, not to be confused with "yank" in Emacs terminology which means
+*paste*).
+
+.. elisp:autofunction:: evil-define-operator
+
+For example, this is an operator that performs ROT13 encryption on the
+text under consideration:
+
+.. code-block:: elisp
+
+ (evil-define-operator evil-rot13 (beg end)
+ "ROT13 encrypt text."
+ (rot13-region beg end))
+
+Binding this to :kbd:`g?` (where it is by default) will cause a key
+sequence such as :kbd:`g?w` to encrypt from the current cursor to the
+end of the word.
+
+
+Text objects
+------------
+
+Text objects are like motions in that they define a range over which
+an operator may act. Unlike motions, text objects can set both a
+beginning and an endpoint. In visual state, text objects alter both
+ends of the selection.
+
+Text objects are not directly usable in normal state. Instead, they
+are bound in the two keymaps ``evil-inner-text-ojects-map`` and
+``evil-outer-text-objects-map``, which are available in visual and
+operator-pending state under the keys :kbd:`i` and :kbd:`a`
+respectively.
+
+.. elisp:autofunction:: evil-define-text-object
+
+For example, this is a text object which selects the next three
+characters after the current location:
+
+.. code-block:: elisp
+
+ (evil-define-text-object foo (count)
+ "Select three characters."
+ (list (point) (+ 3 (point))))
+
+For convenience, Evil provides several functions returning a list of
+positions which can be used for defining text objects. All of them
+follow the convention that a positive *count* selects text after the
+current location, while negative *count* selects text before it.
+
+.. note::
+
+ The *thingatpt* library is used quite extensively in Evil to define
+ text objects, and this dependency leaks through in the following
+ functions. A *thing* in this context is any symbol for which there
+ is a function called ``forward-THING`` [#thing]_ which moves past a
+ number of *things*.
+
+.. elisp:autofunction:: evil-select-inner-object
+
+.. elisp:autofunction:: evil-select-an-object
+
+.. elisp:autofunction:: evil-select-paren
+
+
+Range types
+-----------
+
+A *type* is a transformation acting on a pair of buffer positions.
+Evil defines the types ``inclusive``, ``line``, ``block`` and
+``exclusive``, which are used for motion ranges and visual selection.
+New types may be defined with the macro *evil-define-type*.
+
+.. elisp:autofunction:: evil-define-type
+
+
+States
+------
+
+States are defined with the macro :elisp:ref:`evil-define-state`,
+which takes care to define the necessary hooks, keymaps and variables,
+as well as a toggle function ``evil-NAME-state`` and a predicate
+function ``evil-NAME-state-p`` for checking whether the state is
+active.
+
+.. elisp:autofunction:: evil-define-state
+
+For example:
+
+.. code-block:: elisp
+
+ (evil-define-state test
+ "Test state."
+ :tag " <T> "
+ (message (if (evil-test-state-p)
+ "Enabling test state."
+ "Disabling test state.")))
+
+
+.. rubric:: Footnotes
+
+.. [#thing] There are many more ways that a *thing* can be defined,
+ but the definition of ``forward-THING`` is perhaps the most
+ straightforward way to go about it.
diff --git a/.config/emacs/lisp/evil/doc/source/faq.rst b/.config/emacs/lisp/evil/doc/source/faq.rst
new file mode 100644
index 0000000..d389df0
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/faq.rst
@@ -0,0 +1,118 @@
+Frequently Asked Questions
+==========================
+
+Problems with the escape key in the terminal
+--------------------------------------------
+
+A common problem when using Evil in terminal mode is a certain delay
+after pressing the escape key. Even more, when pressing the escape key
+followed quickly by another key the command is recognized as
+:kbd:`M-<key>` instead of two separate keys: :kbd:`ESC` followed by
+:kbd:`<key>`. In fact, it is perfectly valid to simulate
+:kbd:`M-<key>` by pressing :kbd:`ESC <key>` quickly (but see below).
+
+The reason for this is that in terminal mode a key sequence involving
+the meta key (or alt key) always generates a so called "escape
+sequence", i.e. a sequence of two events sent to Emacs, the first
+being :kbd:`ESC` and the second the key pressed simultaneously. The
+problem is that pressing the escape key itself also generates the
+:kbd:`ESC` event. Thus, if Emacs (and therefore Evil) receives an
+:kbd:`ESC` event there is no way to tell whether the escape key has
+been pressed (and no further event will arrive) or a :kbd:`M-<key>`
+combination has been pressed (and the :kbd:`<key>` event will arrive
+soon). In order to distinguish both situations Evil does the
+following. After receiving an :kbd:`ESC` event Evil waits for a short
+time period (specified by the variable :elisp:ref:`evil-esc-delay`
+which defaults to 0.01 seconds) for another event. If no other event
+arrives Evil assumes that the plain escape key has been pressed,
+otherwise it assumes a :kbd:`M-<key>` combination has been pressed and
+combines the :kbd:`ESC` event with the second one. Because a
+:kbd:`M-<key>` sequence usually generates both events in very quick
+succession, 0.01 seconds are usually enough and the delay is hardly
+noticeable by the user.
+
+If you use a terminal multiplexer like *tmux* or *screen* the
+situation may be worse. These multiplexers have exactly the same
+problem recognizing :kbd:`M-<key>` sequences and often introduce their
+own delay for the :kbd:`ESC` key. There is no way for Evil to
+influence this delay. In order to reduce it you must reconfigure your
+terminal multiplexer.
+
+Note that this problem should not arise when using Evil in graphical
+mode. The reason is that in this case the escape key itself generates
+a different command, namely ``escape`` (a symbol) and hence Evil can
+distinguish whether the escape key or a :kbd:`M-<key>` combination has
+been pressed. But this also implies that pressing :kbd:`ESC` followed
+by <key> cannot be used to simulate :kbd:`M-<key>` in graphical mode!
+
+
+Underscore is not a word character
+----------------------------------
+
+An underscore ``_`` is a word character in Vim. This means that word
+motions like :kbd:`w` skip over underlines in a sequence of letters as
+if it was a letter itself. In contrast, in Evil the underscore is
+often a non-word character like operators, e.g. ``+``.
+
+The reason is that Evil uses Emacs' definition of a word and this
+definition does often not include the underscore. In Emacs word
+characters are determined by the syntax-class of the buffer. The
+syntax-class usually depends on the major-mode of this buffer. This
+has the advantage that the definition of a "word" may be adapted to
+the particular type of document being edited. Evil uses Emacs'
+definition and does not simply use Vim's definition in order to be
+consistent with other Emacs functions. For example, word characters
+are exactly those characters that are matched by the regular
+expression character class ``[:word:]``.
+
+If you would be satisfied by having the :kbd:`*` and :kbd:`#` searches
+use symbols instead of words, this can be achieved by setting the
+:elisp:ref:`evil-symbol-word-search` variable to ``t``.
+
+If you want the underscore to be recognised as word character for other
+motions, you can modify its entry in the syntax-table:
+
+.. code-block:: elisp
+
+ (modify-syntax-entry ?_ "w")
+
+This gives the underscore the 'word' syntax class. You can use a
+mode-hook to modify the syntax-table in all buffers of some mode,
+e.g.:
+
+.. code-block:: elisp
+
+ (add-hook 'c-mode-common-hook
+ (lambda () (modify-syntax-entry ?_ "w")))
+
+This gives the underscore the word syntax-class in all C-like buffers.
+
+Similarly to Emacs' definition of a word, the definition of a "symbol" is also
+dependent on the syntax-class of the buffer, which often includes the
+underscore. The default text objects keymap associates kbd::`o` with the symbol
+object, making kbd::`cio` a good alternative to Vim's kbd::`ciw`, for example.
+The following will swap between the word and symbol objects in the keymap:
+
+.. code-block:: elisp
+
+ (define-key evil-outer-text-objects-map "w" 'evil-a-symbol)
+ (define-key evil-inner-text-objects-map "w" 'evil-inner-symbol)
+ (define-key evil-outer-text-objects-map "o" 'evil-a-word)
+ (define-key evil-inner-text-objects-map "o" 'evil-inner-word)
+
+This will not change the motion keys, however. One way to make word motions
+operate as symbol motions is to alias the ``evil-word`` *thing* [#thingatpt]_ to
+the ``evil-symbol`` thing:
+
+.. code-block:: elisp
+
+ (defalias 'forward-evil-word 'forward-evil-symbol)
+
+
+.. rubric:: Footnotes
+
+.. [#thingatpt] Many of Evil's text objects and motions are defined in
+ terms of the *thingatpt* library, which in this case are defined
+ entirely in terms of ``forward-THING`` functions. Thus aliasing
+ one to another should make all motions and text objects implemented
+ in terms of that *thing* behave the same.
diff --git a/.config/emacs/lisp/evil/doc/source/hooks.rst b/.config/emacs/lisp/evil/doc/source/hooks.rst
new file mode 100644
index 0000000..28ade72
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/hooks.rst
@@ -0,0 +1,16 @@
+Hooks
+=====
+
+A *hook* is a list of functions that are executed when certain events
+happen. Hooks are modified with the Emacs function ``add-hook``.
+Evil provides entry and exit hooks for all its states. For example,
+when switching from normal state to insert state, all functions in
+``evil-normal-state-exit-hook`` and ``evil-insert-state-entry-hook``
+are executed.
+
+It is guaranteed that the exit hook will be executed before the entry
+hook on all state switches.
+
+During the hook execution, the variables ``evil-next-state`` and
+``evil-previous-state`` contain information about the states being
+switched to and from, respectively.
diff --git a/.config/emacs/lisp/evil/doc/source/index.rst b/.config/emacs/lisp/evil/doc/source/index.rst
new file mode 100644
index 0000000..95da7b7
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/index.rst
@@ -0,0 +1,21 @@
+.. Evil documentation master file, created by
+ sphinx-quickstart on Thu Dec 12 10:34:49 2019.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Evil
+====
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents
+
+ overview
+ settings
+ keymaps
+ hooks
+ extension
+ faq
+ internals
+ license
+ indices
diff --git a/.config/emacs/lisp/evil/doc/source/indices.rst b/.config/emacs/lisp/evil/doc/source/indices.rst
new file mode 100644
index 0000000..46f687e
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/indices.rst
@@ -0,0 +1,6 @@
+.. only:: html
+
+ Index
+ =====
+
+ - :ref:`elispindex`
diff --git a/.config/emacs/lisp/evil/doc/source/internals.rst b/.config/emacs/lisp/evil/doc/source/internals.rst
new file mode 100644
index 0000000..9984f7c
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/internals.rst
@@ -0,0 +1,36 @@
+Internals
+=========
+
+Command properties
+------------------
+
+Evil defines *command properties* to store information about commands
+[#command]_, such as whether they should be repeated. A command
+property is a ``:keyword`` with an associated value, e.g.
+``:repeat nil``.
+
+.. elisp:autofunction:: evil-add-command-properties
+
+.. elisp:autofunction:: evil-set-command-properties
+
+.. elisp:autofunction:: evil-get-command-properties
+
+.. elisp:autofunction:: evil-get-command-property
+
+.. elisp:autofunction:: evil-define-command
+
+
+For setting repeat properties, use the following functions:
+
+.. elisp:autofunction:: evil-declare-repeat
+
+.. elisp:autofunction:: evil-declare-not-repeat
+
+.. elisp:autofunction:: evil-declare-change-repeat
+
+
+.. rubric:: Footnotes
+
+.. [#command] In this context, a *command* may mean any Evil motion,
+ text object, operator or indeed other Emacs commands, which have
+ not been defined through the Evil machinery.
diff --git a/.config/emacs/lisp/evil/doc/source/keymaps.rst b/.config/emacs/lisp/evil/doc/source/keymaps.rst
new file mode 100644
index 0000000..36f8141
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/keymaps.rst
@@ -0,0 +1,145 @@
+.. _chapter-keymaps:
+
+Keymaps
+=======
+
+Evil's key bindings are stored in a number of different keymaps. Each
+state has a *global keymap*, where the default bindings for that state
+are stored. They are named ``evil-normal-state-map``,
+``evil-insert-state-map``, and so on. The bindings in these maps are
+visible in all buffers currently in the corresponding state.
+
+These keymaps function like ordinary Emacs keymaps and may be modified
+using the Emacs function ``define-key``:
+
+.. code-block:: elisp
+
+ (define-key evil-normal-state-map (kbd "w") 'some-function)
+
+This binds the key :kbd:`w` to the command ``some-function`` in normal
+state. The use of ``kbd`` is optional for simple key sequences, like
+this one, but recommended in general.
+
+Most of Evil's bindings are defined in the file ``evil-maps.el``.
+
+To facilitate shared keybindings between states, some states may
+activate keybindings from other states as well. For example, motion
+state bindings are visible in normal and visual state, and normal
+state bindings are also visible in visual state.
+
+Each state also has a *buffer-local keymap* which is specific to the
+current buffer, and which takes precedence over the global keymap.
+These maps are most suitably modified by a mode hook. They are named
+``evil-normal-state-local-map``, ``evil-insert-state-local-map``, and
+so on.
+
+.. code-block:: elisp
+
+ (add-hook 'some-mode-hook
+ (lambda ()
+ (define-key evil-normal-state-local-map
+ (kbd "w") 'some-function)))
+
+For convenience, the functions :elisp:ref:`evil-global-set-key` and
+:elisp:ref:`evil-local-set-key` are available for setting global and
+local state keys.
+
+.. elisp:autofunction:: evil-global-set-key
+
+.. elisp:autofunction:: evil-local-set-key
+
+The above examples could therefore have been written as follows:
+
+.. code-block:: elisp
+
+ (evil-global-set-key 'normal (kbd "w") 'some-function)
+
+ (add-hook 'some-mode-hook
+ (lambda ()
+ (evil-local-set-key 'normal (kbd "w") 'some-function)))
+
+
+evil-define-key
+---------------
+
+Evil provides the macro :elisp:ref:`evil-define-key` for adding state
+bindings to ordinary keymaps. It is quite powerful, and is the
+preferred method for fine-tuning bindings to activate in specific
+circumstances.
+
+.. elisp:autofunction:: evil-define-key
+
+There follows a brief overview of the main functions of this macro.
+
+- Define a binding in a given state
+
+ .. code-block:: elisp
+
+ (evil-define-key 'state 'global (kbd "key") 'target)
+
+- Define a binding in a given state in the current buffer
+
+ .. code-block:: elisp
+
+ (evil-define-key 'state 'local (kbd "key") 'target)
+
+- Define a binding in a given state under the *foo-mode* major mode.
+
+ .. code-block:: elisp
+
+ (evil-define-key 'state foo-mode-map (kbd "key") 'target)
+
+ Note that ``foo-mode-map`` is unquoted, and that this form is safe
+ before ``foo-mode-map`` is loaded.
+
+- Define a binding in a given state under the *bar-mode* minor mode.
+
+ .. code-block:: elisp
+
+ (evil-define-key 'state 'bar-mode (kbd "key") 'target)
+
+ Note that ``bar-mode`` is quoted, and that this form is safe before
+ ``bar-mode`` is loaded.
+
+
+The macro :elisp:ref:`evil-define-key` can be used to augment existing
+modes with state bindings, as well as creating packages with custom
+bindings. For example, the following will create a minor mode
+``foo-mode`` with normal state bindings for the keys :kbd:`w` and
+:kbd:`e`:
+
+.. code-block:: elisp
+
+ (define-minor-mode foo-mode
+ "Foo mode."
+ :keymap (make-sparse-keymap))
+
+ (evil-define-key 'normal 'foo-mode "w" 'bar)
+ (evil-define-key 'normal 'foo-mode "e" 'baz)
+
+This minor mode can then be enabled in any buffers where the custom
+bindings are desired:
+
+.. code-block:: elisp
+
+ (add-hook 'text-mode-hook 'foo-mode) ; enable alongside text-mode
+
+
+Leader keys
+-----------
+
+Evil supports a simple implementation of Vim's *leader* keys. To bind
+a function to a leader key you can use the expression ``<leader>`` in
+a key mapping, e.g.
+
+.. code-block:: elisp
+
+ (evil-define-key 'normal 'global (kbd "<leader>fs") 'save-buffer)
+
+Likewise, you can use the expression ``<localleader>`` to mimic Vim's
+local leader, which is designed for mode-specific key bindings.
+
+You can use the function :elisp:ref:`evil-set-leader` to designate
+which key acts as the leader and the local leader.
+
+.. elisp:autofunction:: evil-set-leader
diff --git a/.config/emacs/lisp/evil/doc/source/license.rst b/.config/emacs/lisp/evil/doc/source/license.rst
new file mode 100644
index 0000000..39d6701
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/license.rst
@@ -0,0 +1,447 @@
+The GNU Free Documentation License
+==================================
+
+Version 1.3, 3 November 2008
+
+ Copyright (c) 2000, 2001, 2002, 2007, 2008 Free Software
+ Foundation, Inc. http://fsf.org/
+
+ Everyone is permitted to copy and distribute verbatim copies of
+ this license document, but changing it is not allowed.
+
+
+0. PREAMBLE
+
+ The purpose of this License is to make a manual, textbook, or other
+ functional and useful document *free* in the sense of freedom: to
+ assure everyone the effective freedom to copy and redistribute it,
+ with or without modifying it, either commercially or
+ noncommercially. Secondarily, this License preserves for the
+ author and publisher a way to get credit for their work, while not
+ being considered responsible for modifications made by others.
+
+ This License is a kind of "copyleft", which means that derivative
+ works of the document must themselves be free in the same sense.
+ It complements the GNU General Public License, which is a copyleft
+ license designed for free software.
+
+ We have designed this License in order to use it for manuals for
+ free software, because free software needs free documentation: a
+ free program should come with manuals providing the same freedoms
+ that the software does. But this License is not limited to
+ software manuals; it can be used for any textual work, regardless
+ of subject matter or whether it is published as a printed book. We
+ recommend this License principally for works whose purpose is
+ instruction or reference.
+
+1. APPLICABILITY AND DEFINITIONS
+
+ This License applies to any manual or other work, in any medium,
+ that contains a notice placed by the copyright holder saying it can
+ be distributed under the terms of this License. Such a notice
+ grants a world-wide, royalty-free license, unlimited in duration,
+ to use that work under the conditions stated herein. The
+ "Document", below, refers to any such manual or work. Any member
+ of the public is a licensee, and is addressed as "you". You accept
+ the license if you copy, modify or distribute the work in a way
+ requiring permission under copyright law.
+
+ A "Modified Version" of the Document means any work containing the
+ Document or a portion of it, either copied verbatim, or with
+ modifications and/or translated into another language.
+
+ A "Secondary Section" is a named appendix or a front-matter section
+ of the Document that deals exclusively with the relationship of the
+ publishers or authors of the Document to the Document's overall
+ subject (or to related matters) and contains nothing that could
+ fall directly within that overall subject. (Thus, if the Document
+ is in part a textbook of mathematics, a Secondary Section may not
+ explain any mathematics.) The relationship could be a matter of
+ historical connection with the subject or with related matters, or
+ of legal, commercial, philosophical, ethical or political position
+ regarding them.
+
+ The "Invariant Sections" are certain Secondary Sections whose
+ titles are designated, as being those of Invariant Sections, in the
+ notice that says that the Document is released under this License.
+ If a section does not fit the above definition of Secondary then it
+ is not allowed to be designated as Invariant. The Document may
+ contain zero Invariant Sections. If the Document does not identify
+ any Invariant Sections then there are none.
+
+ The "Cover Texts" are certain short passages of text that are
+ listed, as Front-Cover Texts or Back-Cover Texts, in the notice
+ that says that the Document is released under this License. A
+ Front-Cover Text may be at most 5 words, and a Back-Cover Text may
+ be at most 25 words.
+
+ A "Transparent" copy of the Document means a machine-readable copy,
+ represented in a format whose specification is available to the
+ general public, that is suitable for revising the document
+ straightforwardly with generic text editors or (for images composed
+ of pixels) generic paint programs or (for drawings) some widely
+ available drawing editor, and that is suitable for input to text
+ formatters or for automatic translation to a variety of formats
+ suitable for input to text formatters. A copy made in an otherwise
+ Transparent file format whose markup, or absence of markup, has
+ been arranged to thwart or discourage subsequent modification by
+ readers is not Transparent. An image format is not Transparent if
+ used for any substantial amount of text. A copy that is not
+ "Transparent" is called "Opaque".
+
+ Examples of suitable formats for Transparent copies include plain
+ ASCII without markup, Texinfo input format, LaTeX input format,
+ SGML or XML using a publicly available DTD, and standard-conforming
+ simple HTML, PostScript or PDF designed for human modification.
+ Examples of transparent image formats include PNG, XCF and JPG.
+ Opaque formats include proprietary formats that can be read and
+ edited only by proprietary word processors, SGML or XML for which
+ the DTD and/or processing tools are not generally available, and
+ the machine-generated HTML, PostScript or PDF produced by some word
+ processors for output purposes only.
+
+ The "Title Page" means, for a printed book, the title page itself,
+ plus such following pages as are needed to hold, legibly, the
+ material this License requires to appear in the title page. For
+ works in formats which do not have any title page as such, "Title
+ Page" means the text near the most prominent appearance of the
+ work's title, preceding the beginning of the body of the text.
+
+ The "publisher" means any person or entity that distributes copies
+ of the Document to the public.
+
+ A section "Entitled XYZ" means a named subunit of the Document
+ whose title either is precisely XYZ or contains XYZ in parentheses
+ following text that translates XYZ in another language. (Here XYZ
+ stands for a specific section name mentioned below, such as
+ "Acknowledgements", "Dedications", "Endorsements", or "History".)
+ To "Preserve the Title" of such a section when you modify the
+ Document means that it remains a section "Entitled XYZ" according
+ to this definition.
+
+ The Document may include Warranty Disclaimers next to the notice
+ which states that this License applies to the Document. These
+ Warranty Disclaimers are considered to be included by reference in
+ this License, but only as regards disclaiming warranties: any other
+ implication that these Warranty Disclaimers may have is void and
+ has no effect on the meaning of this License.
+
+2. VERBATIM COPYING
+
+ You may copy and distribute the Document in any medium, either
+ commercially or noncommercially, provided that this License, the
+ copyright notices, and the license notice saying this License
+ applies to the Document are reproduced in all copies, and that you
+ add no other conditions whatsoever to those of this License. You
+ may not use technical measures to obstruct or control the reading
+ or further copying of the copies you make or distribute. However,
+ you may accept compensation in exchange for copies. If you
+ distribute a large enough number of copies you must also follow the
+ conditions in section 3.
+
+ You may also lend copies, under the same conditions stated above,
+ and you may publicly display copies.
+
+3. COPYING IN QUANTITY
+
+ If you publish printed copies (or copies in media that commonly
+ have printed covers) of the Document, numbering more than 100, and
+ the Document's license notice requires Cover Texts, you must
+ enclose the copies in covers that carry, clearly and legibly, all
+ these Cover Texts: Front-Cover Texts on the front cover, and
+ Back-Cover Texts on the back cover. Both covers must also clearly
+ and legibly identify you as the publisher of these copies. The
+ front cover must present the full title with all words of the title
+ equally prominent and visible. You may add other material on the
+ covers in addition. Copying with changes limited to the covers, as
+ long as they preserve the title of the Document and satisfy these
+ conditions, can be treated as verbatim copying in other respects.
+
+ If the required texts for either cover are too voluminous to fit
+ legibly, you should put the first ones listed (as many as fit
+ reasonably) on the actual cover, and continue the rest onto
+ adjacent pages.
+
+ If you publish or distribute Opaque copies of the Document
+ numbering more than 100, you must either include a machine-readable
+ Transparent copy along with each Opaque copy, or state in or with
+ each Opaque copy a computer-network location from which the general
+ network-using public has access to download using public-standard
+ network protocols a complete Transparent copy of the Document, free
+ of added material. If you use the latter option, you must take
+ reasonably prudent steps, when you begin distribution of Opaque
+ copies in quantity, to ensure that this Transparent copy will
+ remain thus accessible at the stated location until at least one
+ year after the last time you distribute an Opaque copy (directly or
+ through your agents or retailers) of that edition to the public.
+
+ It is requested, but not required, that you contact the authors of
+ the Document well before redistributing any large number of copies,
+ to give them a chance to provide you with an updated version of the
+ Document.
+
+4. MODIFICATIONS
+
+ You may copy and distribute a Modified Version of the Document
+ under the conditions of sections 2 and 3 above, provided that you
+ release the Modified Version under precisely this License, with the
+ Modified Version filling the role of the Document, thus licensing
+ distribution and modification of the Modified Version to whoever
+ possesses a copy of it. In addition, you must do these things in
+ the Modified Version:
+
+ A. Use in the Title Page (and on the covers, if any) a title
+ distinct from that of the Document, and from those of previous
+ versions (which should, if there were any, be listed in the
+ History section of the Document). You may use the same title as
+ a previous version if the original publisher of that version
+ gives permission.
+
+ B. List on the Title Page, as authors, one or more persons or
+ entities responsible for authorship of the modifications in the
+ Modified Version, together with at least five of the principal
+ authors of the Document (all of its principal authors, if it has
+ fewer than five), unless they release you from this requirement.
+
+ C. State on the Title page the name of the publisher of the
+ Modified Version, as the publisher.
+
+ D. Preserve all the copyright notices of the Document.
+
+ E. Add an appropriate copyright notice for your modifications
+ adjacent to the other copyright notices.
+
+ F. Include, immediately after the copyright notices, a license
+ notice giving the public permission to use the Modified Version
+ under the terms of this License, in the form shown in the
+ Addendum below.
+
+ G. Preserve in that license notice the full lists of Invariant
+ Sections and required Cover Texts given in the Document's
+ license notice.
+
+ H. Include an unaltered copy of this License.
+
+ I. Preserve the section Entitled "History", Preserve its Title, and
+ add to it an item stating at least the title, year, new authors,
+ and publisher of the Modified Version as given on the Title
+ Page. If there is no section Entitled "History" in the
+ Document, create one stating the title, year, authors, and
+ publisher of the Document as given on its Title Page, then add
+ an item describing the Modified Version as stated in the
+ previous sentence.
+
+ J. Preserve the network location, if any, given in the Document for
+ public access to a Transparent copy of the Document, and
+ likewise the network locations given in the Document for
+ previous versions it was based on. These may be placed in the
+ "History" section. You may omit a network location for a work
+ that was published at least four years before the Document
+ itself, or if the original publisher of the version it refers to
+ gives permission.
+
+ K. For any section Entitled "Acknowledgements" or "Dedications",
+ Preserve the Title of the section, and preserve in the section
+ all the substance and tone of each of the contributor
+ acknowledgements and/or dedications given therein.
+
+ L. Preserve all the Invariant Sections of the Document, unaltered
+ in their text and in their titles. Section numbers or the
+ equivalent are not considered part of the section titles.
+
+ M. Delete any section Entitled "Endorsements". Such a section may
+ not be included in the Modified Version.
+
+ N. Do not retitle any existing section to be Entitled
+ "Endorsements" or to conflict in title with any Invariant
+ Section.
+
+ O. Preserve any Warranty Disclaimers.
+
+ If the Modified Version includes new front-matter sections or
+ appendices that qualify as Secondary Sections and contain no
+ material copied from the Document, you may at your option designate
+ some or all of these sections as invariant. To do this, add their
+ titles to the list of Invariant Sections in the Modified Version's
+ license notice. These titles must be distinct from any other
+ section titles.
+
+ You may add a section Entitled "Endorsements", provided it contains
+ nothing but endorsements of your Modified Version by various
+ parties---for example, statements of peer review or that the text
+ has been approved by an organization as the authoritative
+ definition of a standard.
+
+ You may add a passage of up to five words as a Front-Cover Text,
+ and a passage of up to 25 words as a Back-Cover Text, to the end of
+ the list of Cover Texts in the Modified Version. Only one passage
+ of Front-Cover Text and one of Back-Cover Text may be added by (or
+ through arrangements made by) any one entity. If the Document
+ already includes a cover text for the same cover, previously added
+ by you or by arrangement made by the same entity you are acting on
+ behalf of, you may not add another; but you may replace the old
+ one, on explicit permission from the previous publisher that added
+ the old one.
+
+ The author(s) and publisher(s) of the Document do not by this
+ License give permission to use their names for publicity for or to
+ assert or imply endorsement of any Modified Version.
+
+5. COMBINING DOCUMENTS
+
+ You may combine the Document with other documents released under
+ this License, under the terms defined in section 4 above for
+ modified versions, provided that you include in the combination all
+ of the Invariant Sections of all of the original documents,
+ unmodified, and list them all as Invariant Sections of your
+ combined work in its license notice, and that you preserve all
+ their Warranty Disclaimers.
+
+ The combined work need only contain one copy of this License, and
+ multiple identical Invariant Sections may be replaced with a single
+ copy. If there are multiple Invariant Sections with the same name
+ but different contents, make the title of each such section unique
+ by adding at the end of it, in parentheses, the name of the
+ original author or publisher of that section if known, or else a
+ unique number. Make the same adjustment to the section titles in
+ the list of Invariant Sections in the license notice of the
+ combined work.
+
+ In the combination, you must combine any sections Entitled
+ "History" in the various original documents, forming one section
+ Entitled "History"; likewise combine any sections Entitled
+ "Acknowledgements", and any sections Entitled "Dedications". You
+ must delete all sections Entitled "Endorsements."
+
+6. COLLECTIONS OF DOCUMENTS
+
+ You may make a collection consisting of the Document and other
+ documents released under this License, and replace the individual
+ copies of this License in the various documents with a single copy
+ that is included in the collection, provided that you follow the
+ rules of this License for verbatim copying of each of the documents
+ in all other respects.
+
+ You may extract a single document from such a collection, and
+ distribute it individually under this License, provided you insert
+ a copy of this License into the extracted document, and follow this
+ License in all other respects regarding verbatim copying of that
+ document.
+
+7. AGGREGATION WITH INDEPENDENT WORKS
+
+ A compilation of the Document or its derivatives with other
+ separate and independent documents or works, in or on a volume of a
+ storage or distribution medium, is called an "aggregate" if the
+ copyright resulting from the compilation is not used to limit the
+ legal rights of the compilation's users beyond what the individual
+ works permit. When the Document is included in an aggregate, this
+ License does not apply to the other works in the aggregate which
+ are not themselves derivative works of the Document.
+
+ If the Cover Text requirement of section 3 is applicable to these
+ copies of the Document, then if the Document is less than one half
+ of the entire aggregate, the Document's Cover Texts may be placed
+ on covers that bracket the Document within the aggregate, or the
+ electronic equivalent of covers if the Document is in electronic
+ form. Otherwise they must appear on printed covers that bracket
+ the whole aggregate.
+
+8. TRANSLATION
+
+ Translation is considered a kind of modification, so you may
+ distribute translations of the Document under the terms of
+ section 4. Replacing Invariant Sections with translations requires
+ special permission from their copyright holders, but you may
+ include translations of some or all Invariant Sections in addition
+ to the original versions of these Invariant Sections. You may
+ include a translation of this License, and all the license notices
+ in the Document, and any Warranty Disclaimers, provided that you
+ also include the original English version of this License and the
+ original versions of those notices and disclaimers. In case of a
+ disagreement between the translation and the original version of
+ this License or a notice or disclaimer, the original version will
+ prevail.
+
+ If a section in the Document is Entitled "Acknowledgements",
+ "Dedications", or "History", the requirement (section 4) to
+ Preserve its Title (section 1) will typically require changing the
+ actual title.
+
+9. TERMINATION
+
+ You may not copy, modify, sublicense, or distribute the Document
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense, or distribute it is void,
+ and will automatically terminate your rights under this License.
+
+ However, if you cease all violation of this License, then your
+ license from a particular copyright holder is reinstated (a)
+ provisionally, unless and until the copyright holder explicitly and
+ finally terminates your license, and (b) permanently, if the
+ copyright holder fails to notify you of the violation by some
+ reasonable means prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+ reinstated permanently if the copyright holder notifies you of the
+ violation by some reasonable means, this is the first time you have
+ received notice of violation of this License (for any work) from
+ that copyright holder, and you cure the violation prior to 30 days
+ after your receipt of the notice.
+
+ Termination of your rights under this section does not terminate
+ the licenses of parties who have received copies or rights from you
+ under this License. If your rights have been terminated and not
+ permanently reinstated, receipt of a copy of some or all of the
+ same material does not give you any rights to use it.
+
+10. FUTURE REVISIONS OF THIS LICENSE
+
+ The Free Software Foundation may publish new, revised versions of
+ the GNU Free Documentation License from time to time. Such new
+ versions will be similar in spirit to the present version, but may
+ differ in detail to address new problems or concerns. See
+ http://www.gnu.org/copyleft.
+
+ Each version of the License is given a distinguishing version
+ number. If the Document specifies that a particular numbered
+ version of this License "or any later version" applies to it, you
+ have the option of following the terms and conditions either of
+ that specified version or of any later version that has been
+ published (not as a draft) by the Free Software Foundation. If the
+ Document does not specify a version number of this License, you may
+ choose any version ever published (not as a draft) by the Free
+ Software Foundation. If the Document specifies that a proxy can
+ decide which future versions of this License can be used, that
+ proxy's public statement of acceptance of a version permanently
+ authorizes you to choose that version for the Document.
+
+11. RELICENSING
+
+ "Massive Multiauthor Collaboration Site" (or "MMC Site") means any
+ World Wide Web server that publishes copyrightable works and also
+ provides prominent facilities for anybody to edit those works. A
+ public wiki that anybody can edit is an example of such a server.
+ A "Massive Multiauthor Collaboration" (or "MMC") contained in the
+ site means any set of copyrightable works thus published on the MMC
+ site.
+
+ "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
+ license published by Creative Commons Corporation, a not-for-profit
+ corporation with a principal place of business in San Francisco,
+ California, as well as future copyleft versions of that license
+ published by that same organization.
+
+ "Incorporate" means to publish or republish a Document, in whole or
+ in part, as part of another Document.
+
+ An MMC is "eligible for relicensing" if it is licensed under this
+ License, and if all works that were first published under this
+ License somewhere other than this MMC, and subsequently
+ incorporated in whole or in part into the MMC, (1) had no cover
+ texts or invariant sections, and (2) were thus incorporated prior
+ to November 1, 2008.
+
+ The operator of an MMC Site may republish an MMC contained in the
+ site under CC-BY-SA on the same site at any time before August 1,
+ 2009, provided the MMC is eligible for relicensing.
diff --git a/.config/emacs/lisp/evil/doc/source/overview.rst b/.config/emacs/lisp/evil/doc/source/overview.rst
new file mode 100644
index 0000000..96af183
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/overview.rst
@@ -0,0 +1,117 @@
+Overview
+========
+
+Evil is an extensible vi layer for Emacs. It emulates the main
+features of Vim, [#vim]_ turning Emacs into a modal editor. Like Emacs in
+general, Evil is extensible in Emacs Lisp.
+
+
+Installation via package.el
+---------------------------
+
+Evil is available as a package from MELPA stable, MELPA unstable and
+NonGNU ELPA. This is the recommended way of installing Evil.
+
+To set up `package.el` to work with one of the MELPA repositories, you
+can follow the instructions on `melpa.org
+<https://melpa.org/#/getting-started>`_.
+
+Alternatively you can use NonGNU ELPA. It is part of the default
+package archives as of Emacs 28. For older Emacs versions you'll need
+to add it yourself:
+
+.. code-block:: elisp
+
+ (add-to-list 'package-archives
+ (cons "nongnu" (format "http%s://elpa.nongnu.org/nongnu/"
+ (if (gnutls-available-p) "s" ""))))
+
+Once that is done, you can execute the following commands::
+
+ M-x package-refresh-contents
+ M-x package-install RET evil RET
+
+Finally, add the following lines to your Emacs init file:
+
+.. code-block:: elisp
+
+ (require 'evil)
+ (evil-mode 1)
+
+
+Manual installation
+-------------------
+
+First, install `goto-chg` and `cl-lib`. If you have an Emacs version
+of 24.3 or newer, you should already have `cl-lib`.
+
+Evil lives in a git repository. To download Evil, do::
+
+ git clone --depth 1 https://github.com/emacs-evil/evil.git
+
+Then add the following lines to your Emacs init file:
+
+.. code-block:: elisp
+
+ (add-to-list 'load-path "path/to/evil")
+ (require 'evil)
+ (evil-mode 1)
+
+Ensure that your replace ``path/to/evil`` with the actual path to
+where you cloned Evil.
+
+
+Modes and states
+----------------
+
+The next time Emacs is started, it will come up in *normal state*,
+denoted by ``<N>`` in the mode line. This is where the main vi
+bindings are defined. Note that you can always disable normal state
+with :kbd:`C-z`, which switches to an "Emacs state" (denoted by
+``<E>``) in which vi keys are completely disabled. Press :kbd:`C-z`
+again to switch back to normal state.
+
+state
+ Evil uses the term *state* for what is called a "mode" in regular vi
+ usage, because *modes* are understood in Emacs terms to mean
+ something else.
+
+Evil defines a number of states by default:
+
+normal state (``<N>``)
+ This is the default "resting state" of Evil, in which the main body
+ of vi bindings are defined.
+
+insert state (``<I>``)
+ This is the state for insertion of text, where non-modified keys
+ will insert the corresponding character in the buffer.
+
+visual state (``<V>``)
+ A state for selecting text regions. Motions are available for
+ modifying the selected region, and operators are available for
+ acting on it.
+
+replace state (``<R>``)
+ A special state mostly similar to insert state, except it replaces
+ text instead of inserting.
+
+operator-pending state (``<O>``)
+ A special state entered after launching an operator, but before
+ specifying the corresponding motion or text object.
+
+motion state (``<M>``)
+ A special state useful for buffers that are read-only, where motions
+ are available but editing operations are not.
+
+Emacs state (``<E>``)
+ A state that as closely as possible mimics default Emacs behaviour,
+ by eliminating all vi bindings, except for :kbd:`C-z`, to re-enter
+ normal state.
+
+
+.. rubric:: Footnotes
+
+.. [#vim] Vim is the most popular version of *vi*, a modal text editor
+ with many implementations. Vim also adds some functions of its
+ own, like visual selection and text objects. For more information
+ see `the official Vim website <https://www.vim.org>`_.
diff --git a/.config/emacs/lisp/evil/doc/source/settings.rst b/.config/emacs/lisp/evil/doc/source/settings.rst
new file mode 100644
index 0000000..8ca78e6
--- /dev/null
+++ b/.config/emacs/lisp/evil/doc/source/settings.rst
@@ -0,0 +1,199 @@
+Settings
+========
+
+Evil's behaviour can be adjusted by setting some variables. The list
+of all available variables and their current values can be inspected
+by doing::
+
+ M-x customize-group RET evil RET
+
+To change the value of a variable, you can use this interface, or add
+a ``setq`` form to your Emacs init file, preferably before Evil is
+loaded. [#order]_
+
+.. code-block:: elisp
+
+ (setq evil-shift-width 0)
+ ;; Load Evil
+ (require 'evil)
+
+What follows is a non-exhaustive list of the most relevant
+customization options.
+
+
+The initial state
+-----------------
+
+The initial state of a buffer is determined by its major mode. Evil
+maintains an association between major modes and their corresponding
+states, which is most easily modified using the function
+:elisp:ref:`evil-set-initial-state`.
+
+.. elisp:autofunction:: evil-set-initial-state
+
+If no state can be found, Evil uses the default initial state.
+
+.. elisp:autovariable:: evil-default-state
+
+Alternatively, it is possible to select the initial state based on the
+buffer *name* rather than its major mode. This is checked first, so
+it takes precedence over the other methods for setting the state.
+
+.. elisp:autovariable:: evil-buffer-regexps
+
+
+Keybindings and other behaviour
+-------------------------------
+
+Evil comes with a rich system for modifying its key bindings
+:ref:`chapter-keymaps`. For the most common tweaks, the following
+variables are available.
+
+.. elisp:autovariable:: evil-toggle-key
+
+.. elisp:autovariable:: evil-want-C-i-jump
+
+.. elisp:autovariable:: evil-want-C-u-delete
+
+.. elisp:autovariable:: evil-want-C-u-scroll
+
+.. elisp:autovariable:: evil-want-C-d-scroll
+
+.. elisp:autovariable:: evil-want-C-w-delete
+
+.. elisp:autovariable:: evil-want-C-w-in-emacs-state
+
+.. elisp:autovariable:: evil-want-Y-yank-to-eol
+
+.. elisp:autovariable:: evil-disable-insert-state-bindings
+
+
+Search
+------
+
+.. elisp:autovariable:: evil-search-module
+
+.. elisp:autovariable:: evil-regexp-search
+
+.. elisp:autovariable:: evil-search-wrap
+
+.. elisp:autovariable:: evil-flash-delay
+
+.. elisp:autovariable:: evil-ex-hl-update-delay
+
+.. elisp:autovariable:: evil-ex-search-incremental
+
+
+Indentation
+-----------
+
+.. elisp:autovariable:: evil-auto-indent
+
+.. elisp:autovariable:: evil-shift-width
+
+.. elisp:autovariable:: evil-shift-round
+
+.. elisp:autovariable:: evil-indent-convert-tabs
+
+
+Cursor movement
+---------------
+
+In standard Emacs terms, the cursor is generally understood to be
+located between two characters. In Vim, and therefore also Evil, this
+is the case in insert state, but in other states the cursor is
+understood to be *on* a character, and that this character is not a
+newline.
+
+Forcing this behaviour in Emacs is the source of some potentially
+surprising results (especially for traditional Emacs users---users
+used to Vim may find the default behavior to their satisfaction). Many
+of them can be tweaked using the following variables.
+
+.. elisp:autovariable:: evil-repeat-move-cursor
+
+.. elisp:autovariable:: evil-move-cursor-back
+
+.. elisp:autovariable:: evil-move-beyond-eol
+
+.. elisp:autovariable:: evil-v$-excludes-newline
+
+.. elisp:autovariable:: evil-cross-lines
+
+.. elisp:autovariable:: evil-respect-visual-line-mode
+
+.. elisp:autovariable:: evil-track-eol
+
+.. elisp:autovariable:: evil-start-of-line
+
+
+Cursor display
+--------------
+
+A state may change the appearance of the cursor. Use the variable
+:elisp:ref:`evil-default-cursor` to set the default cursor, and the
+variables ``evil-normal-state-cursor``, ``evil-insert-state-cursor``
+etc. to set the cursors for specific states. The acceptable values
+for all of them are the same.
+
+.. elisp:autovariable:: evil-default-cursor
+
+
+Window management
+-----------------
+
+.. elisp:autovariable:: evil-auto-balance-windows
+
+.. elisp:autovariable:: evil-split-window-below
+
+.. elisp:autovariable:: evil-vsplit-window-right
+
+
+Parenthesis highlighting
+------------------------
+
+These settings concern the integration between Evil and
+``show-paren-mode``. They take no effect if this mode is not enabled.
+
+.. elisp:autovariable:: evil-show-paren-range
+
+.. elisp:autovariable:: evil-highlight-closing-paren-at-point-states
+
+
+Miscellaneous
+-------------
+
+.. elisp:autovariable:: evil-want-fine-undo
+
+.. elisp:autovariable:: evil-undo-system
+
+.. elisp:autovariable:: evil-backspace-join-lines
+
+.. elisp:autovariable:: evil-kbd-macro-suppress-motion-error
+
+.. elisp:autovariable:: evil-mode-line-format
+
+.. elisp:autovariable:: evil-mouse-word
+
+.. elisp:autovariable:: evil-transient-mouse-selection
+
+.. elisp:autovariable:: evil-bigword
+
+.. elisp:autovariable:: evil-esc-delay
+
+.. elisp:autovariable:: evil-intercept-esc
+
+.. elisp:autovariable:: evil-kill-on-visual-paste
+
+.. elisp:autovariable:: evil-echo-state
+
+.. elisp:autovariable:: evil-complete-all-buffers
+
+.. elisp:autovariable:: evil-want-empty-ex-last-command
+
+
+.. rubric:: Footnotes
+
+.. [#order] Strictly speaking, the order only matters if the variable
+ affects the way Evil is loaded. This is the case with some
+ variables.
diff --git a/.config/emacs/lisp/evil/evil-command-window.el b/.config/emacs/lisp/evil/evil-command-window.el
new file mode 100644
index 0000000..ef22be0
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-command-window.el
@@ -0,0 +1,191 @@
+;;; evil-command-window.el --- Evil command-line window -*- lexical-binding: t -*-
+;; Author: Emanuel Evans <emanuel.evans at gmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This provides an implementation of the Vim command-line window for
+;; editing and repeating past Ex commands and searches.
+
+;;; Code:
+
+(require 'evil-vars)
+(require 'evil-common)
+(require 'evil-ex)
+(require 'evil-search)
+
+(defvar evil-search-module)
+
+(defvar evil-command-window-current-buffer nil
+ "The buffer from which the command-line window was called.")
+
+(defvar evil-command-window-execute-fn nil
+ "The command to execute when exiting the command-line window.")
+
+(defvar evil--command-window-prompt nil
+ "The key for the command that opened the command-line window (:, /, or ?).")
+
+(define-derived-mode evil-command-window-mode fundamental-mode "Evil-cmd"
+ "Major mode for the Evil command-line window."
+ (add-hook 'after-change-functions #'evil--command-window-draw-prefix nil t)
+ (auto-fill-mode 0))
+
+(defun evil-command-window (history prompt execute-fn)
+ "Open a command-line window for HISTORY with PROMPT and EXECUTE-FN.
+HISTORY should be a list of commands. PROMPT should be the
+command-line prompt (one of \":\", \"/\" or \"?\"). EXECUTE-FN should
+be a unary function to execute on the result that the user selects.
+
+If called interactively, edit this minibuffer argument."
+ (interactive
+ (list (cons (minibuffer-contents) (minibuffer-history-value))
+ (or (minibuffer-prompt) (user-error "Minibuffer is inactive"))
+ #'evil--command-window-minibuffer-execute))
+ (when (derived-mode-p 'evil-command-window-mode)
+ (user-error "Command-line window is already open"))
+ (when (evil-ex-p) (evil-ex-teardown))
+ (let ((previous-buffer (current-buffer))
+ (buffer (get-buffer-create "*Command Line*")))
+ (with-current-buffer buffer
+ (erase-buffer)
+ (evil-command-window-mode)
+ (setq-local evil-command-window-current-buffer previous-buffer)
+ (setq-local evil-command-window-execute-fn execute-fn)
+ (setq-local evil--command-window-prompt prompt)
+ (evil--command-window-insert-commands history))
+
+ (let* ((action
+ `((display-buffer-reuse-window display-buffer-at-bottom)
+ ,@(unless (zerop evil-command-window-height)
+ `((window-height body-lines . ,evil-command-window-height)
+ (preserve-size nil . t)))
+ (dedicated . t)))
+ (window (display-buffer buffer action))
+ (delete-window-fun
+ (lambda (window)
+ (set-window-parameter window 'delete-window nil)
+ (delete-window window)
+ (switch-to-minibuffer))))
+ (when (minibufferp)
+ (set-window-parameter window 'delete-window delete-window-fun))
+ (select-window window)))
+ (goto-char (point-max))
+ (unless (bobp) (backward-char) (evil-adjust-cursor)))
+
+(defun evil--command-window-draw-prefix (beg end _old-len)
+ "Display `evil--command-window-prompt' as a prefix of the changed lines."
+ (let ((prefix (propertize evil--command-window-prompt
+ 'font-lock-face 'minibuffer-prompt)))
+ (put-text-property beg end 'line-prefix prefix)))
+
+(defun evil--command-window-insert-commands (history)
+ "Insert the commands in HISTORY."
+ (let ((inhibit-modification-hooks t))
+ (dolist (cmd (reverse history)) (insert cmd "\n"))
+ (evil--command-window-draw-prefix (point-min) (point-max) nil)))
+
+(defun evil-command-window-execute ()
+ "Execute the command on the current line in the appropriate buffer.
+The local variable `evil-command-window-execute-fn' determines which
+function to execute."
+ (interactive)
+ (let ((result (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position)))
+ (original-buffer evil-command-window-current-buffer)
+ (execute-fn evil-command-window-execute-fn))
+ (let ((ignore-window-parameters t))
+ (ignore-errors (kill-buffer-and-window)))
+ (unless (buffer-live-p original-buffer)
+ (user-error "Originating buffer is no longer active"))
+ (let ((window (get-buffer-window original-buffer)))
+ (when window (select-window window)))
+ (with-current-buffer original-buffer (funcall execute-fn result))))
+
+(defun evil--command-window-minibuffer-execute (result)
+ "Terminate this minibuffer argument with RESULT."
+ (delete-minibuffer-contents)
+ (insert result)
+ (exit-minibuffer))
+
+(defun evil-command-window-ex (&optional current-command)
+ "Open a command-line window for editing and executing Ex commands.
+If CURRENT-COMMAND is present, it will be inserted under the cursor as
+the current command to be edited."
+ (interactive)
+ (evil-command-window (cons (or current-command "") evil-ex-history)
+ ":"
+ #'evil-command-window-ex-execute))
+
+(define-obsolete-function-alias
+ 'evil-ex-command-window #'evil-command-window "1.15.0"
+ "Start command window with Ex history and current minibuffer content.")
+
+(define-obsolete-function-alias
+ 'evil-ex-search-command-window #'evil-command-window "1.15.0"
+ "Start command window with search history and current minibuffer content.")
+
+(defun evil-command-window-ex-execute (result)
+ "Execute RESULT as an Ex command."
+ (unless (string-match-p "\\`[ \t\n\r]*\\'" result)
+ (unless (equal result (car evil-ex-history))
+ (push result evil-ex-history))
+ (evil-ex-execute result)))
+
+(defun evil--command-window-search (forward)
+ "Open a command-line window for searches."
+ (evil-command-window
+ (cons "" (cond ((eq evil-search-module 'evil-search)
+ evil-ex-search-history)
+ (forward evil-search-forward-history)
+ (t evil-search-backward-history)))
+ (evil-search-prompt forward)
+ (lambda (result) (evil-command-window-search-execute result forward))))
+
+(defun evil-command-window-search-forward ()
+ "Open a command-line window for forward searches."
+ (interactive)
+ (evil--command-window-search t))
+
+(defun evil-command-window-search-backward ()
+ "Open a command-line window for backward searches."
+ (interactive)
+ (evil--command-window-search nil))
+
+(defun evil-command-window-search-execute (result forward)
+ "Search for RESULT using FORWARD to determine direction."
+ (unless (string= result "")
+ (if (eq evil-search-module 'evil-search)
+ (progn
+ (setq evil-ex-search-pattern (evil-ex-make-search-pattern result)
+ evil-ex-search-direction (if forward 'forward 'backward))
+ (unless (equal result (car evil-ex-search-history))
+ (push result evil-ex-search-history))
+ (evil-ex-search))
+ (evil-push-search-history result forward)
+ (evil-search result forward evil-regexp-search))))
+
+(provide 'evil-command-window)
+
+;;; evil-command-window.el ends here
diff --git a/.config/emacs/lisp/evil/evil-commands.el b/.config/emacs/lisp/evil/evil-commands.el
new file mode 100644
index 0000000..5dbda83
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-commands.el
@@ -0,0 +1,5288 @@
+;;; evil-commands.el --- Evil commands and operators -*- lexical-binding: t -*-
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'evil-common)
+(require 'evil-search)
+(require 'evil-states)
+(require 'evil-ex)
+(require 'evil-types)
+(require 'evil-command-window)
+(require 'evil-jumps)
+(require 'evil-vars)
+(require 'cl-lib)
+(require 'reveal)
+
+(declare-function imenu--in-alist "imenu")
+
+;;; Motions
+
+;; Movement commands, or motions, are defined with the macro
+;; `evil-define-motion'. A motion is a command with an optional
+;; argument COUNT (interactively accessed by the code "<c>").
+;; It may specify the :type command property (e.g., :type line),
+;; which determines how it is handled by an operator command.
+;; Furthermore, the command must have the command properties
+;; :keep-visual t and :repeat motion; these are automatically
+;; set by the `evil-define-motion' macro.
+
+(evil-define-motion evil-forward-char (count &optional crosslines noerror)
+ "Move cursor to the right by COUNT characters.
+Movement is restricted to the current line unless CROSSLINES is non-nil.
+If NOERROR is non-nil, don't signal an error upon reaching the end
+of the line or the buffer; just return nil."
+ :type exclusive
+ (interactive "<c>" (list evil-cross-lines
+ (evil-kbd-macro-suppress-motion-error)))
+ (cond
+ ((not crosslines)
+ ;; For efficiency, narrow the buffer to the projected
+ ;; movement before determining the current line
+ (evil-with-restriction nil (min (+ (point) (or count 1) 1) (point-max))
+ (condition-case err
+ (evil-narrow-to-line (forward-char count))
+ (error
+ ;; Restore the previous command (this one never happened).
+ ;; This preserves the current column if the previous command
+ ;; was `evil-next-line' or `evil-previous-line'.
+ (setq this-command last-command)
+ (unless noerror (signal (car err) (cdr err)))))))
+ (noerror (ignore-errors (evil-forward-char count crosslines)))
+ (t (evil-motion-loop (nil (or count 1))
+ (forward-char)
+ ;; don't put the cursor on a newline
+ (or evil-move-beyond-eol
+ (evil-visual-state-p) (evil-operator-state-p)
+ (not (eolp)) (bolp)
+ (forward-char))))))
+
+(evil-define-motion evil-backward-char (count &optional crosslines noerror)
+ "Move cursor to the left by COUNT characters.
+Movement is restricted to the current line unless CROSSLINES is non-nil.
+If NOERROR is non-nil, don't signal an error upon reaching the beginning
+of the line or the buffer; just return nil."
+ :type exclusive
+ (interactive "<c>" (list evil-cross-lines
+ (evil-kbd-macro-suppress-motion-error)))
+ (cond
+ ((not crosslines)
+ ;; Restrict movement to the current line
+ (evil-with-restriction
+ (max (- (point) (or count 1)) (point-min))
+ (min (1+ (point)) (point-max))
+ (condition-case err
+ (evil-narrow-to-line (backward-char count))
+ (error
+ ;; Restore the previous command (this one never happened).
+ ;; This preserves the current column if the previous command
+ ;; was `evil-next-line' or `evil-previous-line'.
+ (setq this-command last-command)
+ (unless noerror (signal (car err) (cdr err)))))))
+ (noerror (ignore-errors (evil-backward-char count crosslines)))
+ (t (evil-motion-loop (nil (or count 1))
+ (backward-char)
+ ;; don't put the cursor on a newline
+ (unless (or (evil-visual-state-p) (evil-operator-state-p))
+ (evil-adjust-cursor))))))
+
+(evil-define-motion evil-next-line (count)
+ "Move the cursor COUNT lines down."
+ :type line
+ (let (line-move-visual)
+ (evil-line-move (or count 1))))
+
+(evil-define-motion evil-previous-line (count)
+ "Move the cursor COUNT lines up."
+ :type line
+ (let (line-move-visual)
+ (evil-line-move (- (or count 1)))))
+
+(evil-define-motion evil-next-visual-line (count)
+ "Move the cursor COUNT screen lines down."
+ :type exclusive
+ (let ((line-move-visual t))
+ (evil-line-move (or count 1))))
+
+(evil-define-motion evil-previous-visual-line (count)
+ "Move the cursor COUNT screen lines up."
+ :type exclusive
+ (let ((line-move-visual t))
+ (evil-line-move (- (or count 1)))))
+
+;; Used for repeated commands like "dd"
+(evil-define-motion evil-line (count)
+ "Move COUNT - 1 lines down."
+ :type line
+ (let (line-move-visual)
+ (evil-line-move (1- (or count 1)) t)))
+
+(evil-define-motion evil-line-or-visual-line (count)
+ "Move COUNT - 1 lines down."
+ :type screen-line
+ (let ((line-move-visual (and evil-respect-visual-line-mode
+ visual-line-mode)))
+ (evil-line-move (1- (or count 1)) t)))
+
+(evil-define-motion evil-beginning-of-line ()
+ "Move the cursor to the beginning of the current line."
+ :type exclusive
+ (move-beginning-of-line nil))
+
+(evil-define-motion evil-end-of-line (count)
+ "Move the cursor to the end of the current line.
+If COUNT is given, move COUNT - 1 lines downward first."
+ :type inclusive
+ (move-end-of-line count)
+ (when evil-track-eol
+ (setq temporary-goal-column most-positive-fixnum
+ this-command 'next-line))
+ (let ((evil-move-beyond-eol
+ (if (evil-visual-state-p) (not evil-v$-excludes-newline)
+ evil-move-beyond-eol)))
+ (evil-adjust-cursor))
+ ;; Prevent "c$" and "d$" from deleting blank lines
+ (when (eolp) (setq evil-this-type 'exclusive)))
+
+(evil-define-motion evil-beginning-of-visual-line ()
+ "Move the cursor to the first character of the current screen line."
+ :type exclusive
+ (beginning-of-visual-line))
+
+(evil-define-motion evil-end-of-visual-line (count)
+ "Move the cursor to the last character of the current screen line.
+If COUNT is given, move COUNT - 1 screen lines downward first."
+ :type inclusive
+ (end-of-visual-line count)
+ (evil-move-cursor-back t))
+
+(evil-define-motion evil-end-of-line-or-visual-line (count)
+ "Move the cursor to the last character of the current screen
+line if `visual-line-mode' is active and
+`evil-respect-visual-line-mode' is non-nil. If COUNT is given,
+move COUNT - 1 screen lines downward first."
+ :type inclusive
+ (if (and evil-respect-visual-line-mode
+ visual-line-mode)
+ (evil-end-of-visual-line count)
+ (evil-end-of-line count)))
+
+(evil-define-motion evil-middle-of-visual-line ()
+ "Move the cursor to the middle of the current visual line."
+ :type exclusive
+ (beginning-of-visual-line)
+ (evil-with-restriction
+ nil
+ (save-excursion (end-of-visual-line) (point))
+ (move-to-column
+ (+ (current-column) -1 (/ (window-body-width) 2)))))
+
+(evil-define-motion evil-percentage-of-line (count)
+ "Move the cursor to COUNT % of the width of the current line.
+If no COUNT is given, default to 50%."
+ :type exclusive
+ (let ((line-length (- (line-end-position) (line-beginning-position)
+ (if evil-move-beyond-eol -1 0))))
+ (move-to-column (truncate (* line-length (or count 50)) 100))))
+
+(evil-define-motion evil-first-non-blank ()
+ "Move the cursor to the first non-blank character of the current line."
+ :type exclusive
+ (evil-narrow-to-line (back-to-indentation)))
+
+(evil-define-motion evil-last-non-blank (count)
+ "Move the cursor to the last non-blank character of the current line.
+If COUNT is given, move COUNT - 1 lines downward first."
+ :type inclusive
+ (evil-move-end-of-line count)
+ (skip-chars-backward " \t")
+ (unless (bolp) (backward-char)))
+
+(evil-define-motion evil-first-non-blank-of-visual-line ()
+ "Move the cursor to the first non blank character
+of the current screen line."
+ :type exclusive
+ (evil-beginning-of-visual-line)
+ (skip-chars-forward " \t\r"))
+
+(evil-define-motion evil-next-line-first-non-blank (count)
+ "Move the cursor COUNT lines down on the first non-blank character."
+ :type line
+ (let ((this-command this-command))
+ (evil-next-line (or count 1)))
+ (evil-first-non-blank))
+
+(evil-define-motion evil-next-line-1-first-non-blank (count)
+ "Move the cursor COUNT-1 lines down on the first non-blank character."
+ :type line
+ (let ((this-command this-command))
+ (evil-next-line (1- (or count 1))))
+ (evil-first-non-blank))
+
+(evil-define-motion evil-previous-line-first-non-blank (count)
+ "Move the cursor COUNT lines up on the first non-blank character."
+ :type line
+ (let ((this-command this-command))
+ (evil-previous-line (or count 1)))
+ (evil-first-non-blank))
+
+(evil-define-motion evil-goto-line (count)
+ "Go to line COUNT. By default the last line."
+ :jump t
+ :type line
+ (evil-ensure-column
+ (if (null count)
+ (progn
+ (goto-char (point-max))
+ (when (and (eq (current-buffer) (window-buffer))
+ (> (point) (window-end nil t)))
+ ;; If the end of the buffer is not already on the screen, scroll to
+ ;; position it near the bottom.
+ (overlay-recenter (point))
+ (recenter (and (< 100 scroll-conservatively) -1))))
+ (goto-char (point-min))
+ (forward-line (1- count)))))
+
+(evil-define-motion evil-goto-first-line (count)
+ "Go to line COUNT. By default the first line."
+ :jump t
+ :type line
+ (evil-goto-line (or count 1)))
+
+(evil-define-motion evil-forward-word-begin (count &optional bigword)
+ "Move the cursor to the beginning of the COUNT-th next word.
+If BIGWORD is non-nil, move by WORDS.
+
+If this command is called in operator-pending state it behaves
+differently. If point reaches the beginning of a word on a new
+line point is moved back to the end of the previous line.
+
+If called after a change operator, i.e. cw or cW,
+`evil-want-change-word-to-end' is non-nil and point is on a word,
+then both behave like ce or cE.
+
+If point is at the end of the buffer and cannot be moved then
+`end-of-buffer' is signaled."
+ :type exclusive
+ (let ((thing (if bigword 'evil-WORD 'evil-word))
+ (orig (point))
+ (count (or count 1)))
+ (evil-signal-at-bob-or-eob count)
+ (cond
+ ;; default motion, beginning of next word
+ ((not (evil-operator-state-p))
+ (evil-forward-beginning thing count))
+ ;; the evil-change operator, maybe behave like ce or cE
+ ((and evil-want-change-word-to-end
+ (memq evil-this-operator evil-change-commands)
+ (< orig (or (cdr-safe (bounds-of-thing-at-point thing)) orig)))
+ ;; forward-thing moves point to the correct position because
+ ;; this is an exclusive motion
+ (forward-thing thing count))
+ ;; operator state
+ (t
+ (prog1 (evil-forward-beginning thing count)
+ ;; if we reached the beginning of a word on a new line in
+ ;; Operator-Pending state, go back to the end of the previous
+ ;; line
+ (when (and (> (line-beginning-position) orig)
+ (looking-back "^[[:space:]]*" (line-beginning-position)))
+ ;; move cursor back as long as the line contains only
+ ;; whitespaces and is non-empty
+ (evil-move-end-of-line 0)
+ ;; skip non-empty lines containing only spaces
+ (while (and (looking-back "^[[:space:]]+$" (line-beginning-position))
+ (not (<= (line-beginning-position) orig)))
+ (evil-move-end-of-line 0))
+ ;; but if the previous line is empty, delete this line
+ (when (bolp) (forward-char))))))))
+
+(evil-define-motion evil-forward-word-end (count &optional bigword)
+ "Move the cursor to the end of the COUNT-th next word.
+If BIGWORD is non-nil, move by WORDS."
+ :type inclusive
+ (let ((thing (if bigword 'evil-WORD 'evil-word))
+ (count (or count 1)))
+ (evil-signal-at-bob-or-eob count)
+ ;; Evil special behaviour: e or E on a one-character word in
+ ;; operator state does not move point
+ (unless (and (evil-operator-state-p)
+ (= 1 count)
+ (let ((bnd (bounds-of-thing-at-point thing)))
+ (and bnd
+ (= (car bnd) (point))
+ (= (cdr bnd) (1+ (point)))))
+ (looking-at "[[:word:]]"))
+ (evil-forward-end thing count))))
+
+(evil-define-motion evil-backward-word-begin (count &optional bigword)
+ "Move the cursor to the beginning of the COUNT-th previous word.
+If BIGWORD is non-nil, move by WORDS."
+ :type exclusive
+ (let ((thing (if bigword 'evil-WORD 'evil-word)))
+ (evil-signal-at-bob-or-eob (- (or count 1)))
+ (evil-backward-beginning thing count)))
+
+(evil-define-motion evil-backward-word-end (count &optional bigword)
+ "Move the cursor to the end of the COUNT-th previous word.
+If BIGWORD is non-nil, move by WORDS."
+ :type inclusive
+ (let ((thing (if bigword 'evil-WORD 'evil-word)))
+ (evil-signal-at-bob-or-eob (- (or count 1)))
+ (evil-backward-end thing count)))
+
+(evil-define-motion evil-forward-WORD-begin (count)
+ "Move the cursor to the beginning of the COUNT-th next WORD."
+ :type exclusive
+ (evil-forward-word-begin count t))
+
+(evil-define-motion evil-forward-WORD-end (count)
+ "Move the cursor to the end of the COUNT-th next WORD."
+ :type inclusive
+ (evil-forward-word-end count t))
+
+(evil-define-motion evil-backward-WORD-begin (count)
+ "Move the cursor to the beginning of the COUNT-th previous WORD."
+ :type exclusive
+ (evil-backward-word-begin count t))
+
+(evil-define-motion evil-backward-WORD-end (count)
+ "Move the cursor to the end of the COUNT-th previous WORD."
+ :type inclusive
+ (evil-backward-word-end count t))
+
+;; section movement
+(evil-define-motion evil-forward-section-begin (count)
+ "Move the cursor to the beginning of the COUNT-th next section."
+ :jump t
+ :type exclusive
+ (evil-signal-at-bob-or-eob count)
+ (evil-forward-beginning 'evil-defun count))
+
+(evil-define-motion evil-forward-section-end (count)
+ "Move the cursor to the end of the COUNT-th next section."
+ :jump t
+ :type inclusive
+ (evil-signal-at-bob-or-eob count)
+ (evil-forward-end 'evil-defun count)
+ (unless (eobp) (forward-line)))
+
+(evil-define-motion evil-backward-section-begin (count)
+ "Move the cursor to the beginning of the COUNT-th previous section."
+ :jump t
+ :type exclusive
+ (evil-signal-at-bob-or-eob (- (or count 1)))
+ (evil-backward-beginning 'evil-defun count))
+
+(evil-define-motion evil-backward-section-end (count)
+ "Move the cursor to the end of the COUNT-th previous section."
+ :jump t
+ :type inclusive
+ (evil-signal-at-bob-or-eob (- (or count 1)))
+ (end-of-line -1)
+ (evil-backward-end 'evil-defun count)
+ (unless (eobp) (forward-line)))
+
+(evil-define-motion evil-forward-sentence-begin (count)
+ "Move to the next COUNT-th beginning of a sentence or end of a paragraph."
+ :jump t
+ :type exclusive
+ (evil-signal-at-bob-or-eob count)
+ (evil-forward-nearest count
+ #'(lambda (_cnt)
+ (evil-forward-beginning 'evil-sentence))
+ #'evil-forward-paragraph))
+
+(evil-define-motion evil-backward-sentence-begin (count)
+ "Move to the previous COUNT-th beginning of a sentence or paragraph."
+ :jump t
+ :type exclusive
+ (evil-signal-at-bob-or-eob (- (or count 1)))
+ (evil-forward-nearest (- (or count 1))
+ #'(lambda (_cnt)
+ (evil-backward-beginning 'evil-sentence))
+ #'(lambda (_cnt)
+ (evil-backward-paragraph))))
+
+(evil-define-motion evil-forward-paragraph (count)
+ "Move to the end of the COUNT-th next paragraph."
+ :jump t
+ :type exclusive
+ (evil-signal-at-bob-or-eob count)
+ (evil-forward-end 'evil-paragraph count)
+ (unless (eobp) (forward-line)))
+
+(evil-define-motion evil-backward-paragraph (count)
+ "Move to the beginning of the COUNT-th previous paragraph."
+ :jump t
+ :type exclusive
+ (evil-signal-at-bob-or-eob (- (or count 1)))
+ (unless (eobp) (forward-line))
+ (evil-backward-beginning 'evil-paragraph count)
+ (unless (bobp) (forward-line -1)))
+
+(defvar hif-ifx-else-endif-regexp)
+(evil-define-motion evil-jump-item (count)
+ "Find the next item in this line after or under the cursor
+and jump to the corresponding one."
+ :jump t
+ :type inclusive
+ (cond
+ ;; COUNT% jumps to a line COUNT percentage down the file
+ (count
+ (evil-ensure-column
+ (goto-char
+ (let ((size (- (point-max) (point-min))))
+ (+ (point-min)
+ (if (> size 80000)
+ (* count (/ size 100))
+ (/ (* count size) 100))))))
+ (setq evil-this-type 'line))
+ ((and (evil-looking-at-start-comment t)
+ (let ((pnt (point)))
+ (forward-comment 1)
+ (or (not (bolp))
+ (prog1 nil (goto-char pnt)))))
+ (backward-char))
+ ((and (not (eolp)) (evil-looking-at-end-comment t))
+ (forward-comment -1))
+ ((and
+ (memq major-mode '(c-mode c++-mode c-ts-mode c++-ts-mode))
+ (require 'hideif nil t)
+ (with-no-warnings
+ (let* ((hif-else-regexp (concat hif-cpp-prefix "\\(?:else\\|elif[ \t]+\\)"))
+ (hif-ifx-else-endif-regexp
+ (concat hif-ifx-regexp "\\|" hif-else-regexp "\\|" hif-endif-regexp)))
+ (cond
+ ((save-excursion (beginning-of-line) (or (hif-looking-at-ifX) (hif-looking-at-else)))
+ (hif-find-next-relevant)
+ (while (hif-looking-at-ifX)
+ (hif-ifdef-to-endif)
+ (hif-find-next-relevant))
+ t)
+ ((save-excursion (beginning-of-line) (hif-looking-at-endif))
+ (hif-endif-to-ifdef)
+ t))))))
+ (t
+ (let* ((open (point-max))
+ (close (point-max))
+ (open-pair (ignore-errors
+ (save-excursion
+ ;; consider the character right before eol given that
+ ;; point may be placed there, e.g. in visual state
+ (when (and (eolp) (not (bolp)))
+ (backward-char))
+ (setq open (1- (scan-lists (point) 1 -1)))
+ (when (< open (line-end-position))
+ (goto-char open)
+ (forward-list)
+ (1- (point))))))
+ (close-pair (ignore-errors
+ (save-excursion
+ ;; consider the character right before eol given that
+ ;; point may be placed there, e.g. in visual state
+ (when (and (eolp) (not (bolp)))
+ (backward-char))
+ (setq close (1- (scan-lists (point) 1 1)))
+ (when (< close (line-end-position))
+ (goto-char (1+ close))
+ (backward-list)
+ (point))))))
+ (cond
+ ((not (or open-pair close-pair))
+ ;; nothing found, check if we are inside a string
+ (let ((pnt (point))
+ (bnd (bounds-of-thing-at-point 'evil-string)))
+ (if (not (and bnd (< (point) (cdr bnd))))
+ ;; no, then we really failed
+ (user-error "No matching item found on the current line")
+ ;; yes, go to the end of the string and try again
+ (let ((endstr (cdr bnd)))
+ (when (or (save-excursion
+ (goto-char endstr)
+ (let ((b (bounds-of-thing-at-point 'evil-string)))
+ (and b (< (point) (cdr b))))) ; not at end of string
+ (condition-case nil
+ (progn
+ (goto-char endstr)
+ (evil-jump-item)
+ nil)
+ (error t)))
+ ;; failed again, go back to original point
+ (goto-char pnt)
+ (user-error "No matching item found on the current line"))))))
+ ((< open close) (goto-char open-pair))
+ (t (goto-char close-pair)))))))
+
+(declare-function flyspell-overlay-p "flyspell")
+(evil-define-motion evil-next-flyspell-error (count)
+ "Go to the COUNT'th spelling mistake after point."
+ :jump t
+ (unless (bound-and-true-p flyspell-mode) (signal 'search-failed nil))
+ (let ((fwd (> (or count 1) 0)) (start (point)) (pos (point)) ov)
+ (dotimes (_ (abs (or count 1)))
+ (let ((limit (if fwd (point-max) (point-min))) wrappedp)
+ (when fwd (setq pos (save-excursion (goto-char pos)
+ (skip-syntax-forward "w") (point))))
+ (while (progn (if (if fwd (>= pos limit) (<= pos limit))
+ (if (or wrappedp (not evil-search-wrap))
+ (signal 'search-failed nil)
+ (setq wrappedp t
+ limit start
+ pos (if fwd (point-min)
+ (previous-overlay-change (point-max)))))
+ (setq pos (if fwd (next-overlay-change pos)
+ (previous-overlay-change pos))))
+ (not (setq ov (seq-find #'flyspell-overlay-p
+ (overlays-at pos))))))
+ (when wrappedp (let (message-log-max) (message "Search wrapped")))))
+ (goto-char (overlay-start ov))))
+
+(evil-define-motion evil-prev-flyspell-error (count)
+ "Go to the COUNT'th spelling mistake preceding point."
+ :jump t
+ (evil-next-flyspell-error (- (or count 1))))
+
+(evil-define-motion evil-previous-open-paren (count)
+ "Go to COUNT previous unmatched \"(\"."
+ :jump t
+ :type exclusive
+ (evil-up-paren ?\( ?\) (- (or count 1))))
+
+(evil-define-motion evil-next-close-paren (count)
+ "Go to COUNT next unmatched \")\"."
+ :jump t
+ :type exclusive
+ (forward-char)
+ (evil-up-paren ?\( ?\) (or count 1))
+ (backward-char))
+
+(evil-define-motion evil-previous-open-brace (count)
+ "Go to COUNT previous unmatched \"{\"."
+ :jump t
+ :type exclusive
+ (evil-up-paren ?{ ?} (- (or count 1))))
+
+(evil-define-motion evil-next-close-brace (count)
+ "Go to COUNT next unmatched \"}\"."
+ :jump t
+ :type exclusive
+ (forward-char)
+ (evil-up-paren ?{ ?} (or count 1))
+ (backward-char))
+
+(defun evil--lowercase-markers ()
+ "Get all lowercase markers."
+ (cl-remove-if-not (lambda (x) (and (markerp (cdr x))
+ (<= ?a (car x) ?z)))
+ evil-markers-alist))
+
+(defun evil--next-mark (forwardp)
+ "Move to next lowercase mark.
+Move forward if FORWARDP is non-nil, and backward otherwise. Loop back
+to the beginning of buffer if the end is reached."
+ (let* ((pos (if forwardp (1+ (point)) (point)))
+ (centered-markers
+ (cl-sort
+ (or (evil--lowercase-markers) (user-error "No marks in this buffer"))
+ (if forwardp #'< #'>)
+ :key (lambda (x) (+ (if (< (cdr x) pos) 0 most-negative-fixnum)
+ (cdr x))))))
+ (goto-char (cdar centered-markers))))
+
+(evil-define-motion evil-next-mark (count)
+ "Go to COUNT next lowercase mark."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (dotimes (_ (or count 1))
+ (evil--next-mark t)))
+
+(evil-define-motion evil-next-mark-line (count)
+ "Go to COUNT line of next lowercase mark after current line."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (unless (evil--lowercase-markers) (user-error "No marks in this buffer"))
+ (dotimes (_ (or count 1))
+ (move-end-of-line nil)
+ (evil--next-mark t))
+ (evil-first-non-blank))
+
+(evil-define-motion evil-previous-mark (count)
+ "Go to COUNT previous lowercase mark."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (dotimes (_ (or count 1))
+ (evil--next-mark nil)))
+
+(evil-define-motion evil-previous-mark-line (count)
+ "Go to COUNT line of previous lowercase mark before current line."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (unless (evil--lowercase-markers) (user-error "No marks in this buffer"))
+ (dotimes (_ (or count 1))
+ (move-beginning-of-line nil)
+ (evil--next-mark nil))
+ (evil-first-non-blank))
+
+(evil-define-command evil-set-col-0-mark (_beg end mark)
+ "Set MARK at column 0 of line of END.
+Default is cursor line."
+ (interactive "<r><a>")
+ (if (< 1 (length mark))
+ (user-error "Trailing characters")
+ (save-excursion
+ (goto-char (if (eobp) end (1- end)))
+ (evil-beginning-of-line)
+ (evil-set-marker (string-to-char mark)))))
+
+(evil-define-motion evil-find-char (count char)
+ "Move to the next COUNT'th occurrence of CHAR.
+Movement is restricted to the current line unless `evil-cross-lines'
+is non-nil."
+ :type inclusive
+ (interactive "<c><C>")
+ (setq count (or count 1))
+ (let ((fwd (> count 0))
+ (visual (and evil-respect-visual-line-mode
+ visual-line-mode))
+ case-fold-search)
+ (setq evil-last-find (list #'evil-find-char char fwd))
+ (when fwd (evil-forward-char 1 evil-cross-lines))
+ (unless (prog1
+ (search-forward
+ (char-to-string char)
+ (cond (evil-cross-lines nil)
+ ((and fwd visual)
+ (save-excursion
+ (end-of-visual-line)
+ (point)))
+ (fwd (line-end-position))
+ (visual
+ (save-excursion
+ (beginning-of-visual-line)
+ (point)))
+ (t (line-beginning-position)))
+ t count)
+ (when fwd (backward-char)))
+ (user-error "Can't find `%c'" char))))
+
+(evil-define-motion evil-find-char-backward (count char)
+ "Move to the previous COUNT'th occurrence of CHAR."
+ :type exclusive
+ (interactive "<c><C>")
+ (evil-find-char (- (or count 1)) char))
+
+(evil-define-motion evil-find-char-to (count char)
+ "Move before the next COUNT'th occurrence of CHAR."
+ :type inclusive
+ (interactive "<c><C>")
+ (unwind-protect
+ (evil-find-char count char)
+ (setcar evil-last-find #'evil-find-char-to))
+ (if (> (or count 1) 0)
+ (backward-char)
+ (forward-char)))
+
+(evil-define-motion evil-find-char-to-backward (count char)
+ "Move before the previous COUNT'th occurrence of CHAR."
+ :type exclusive
+ (interactive "<c><C>")
+ (evil-find-char-to (- (or count 1)) char))
+
+(evil-define-motion evil-repeat-find-char (count)
+ "Repeat the last find COUNT times."
+ :type inclusive
+ (setq count (or count 1))
+ (cl-destructuring-bind (cmd char fwd)
+ (or evil-last-find (user-error "No previous search"))
+ ;; ensure count is non-negative
+ (when (< count 0)
+ (setq count (- count)
+ fwd (not fwd)))
+ ;; skip next character when repeating t or T
+ (and (eq cmd #'evil-find-char-to)
+ evil-repeat-find-to-skip-next
+ (= count 1)
+ (eql (if fwd (char-after (1+ (point))) (char-before)) char)
+ (setq count (1+ count)))
+ (let (evil-last-find)
+ (funcall cmd (if fwd count (- count)) char)
+ (unless (nth 2 evil-last-find)
+ (setq evil-this-type 'exclusive)))))
+
+(evil-define-motion evil-repeat-find-char-reverse (count)
+ "Repeat the last find COUNT times in the opposite direction."
+ :type inclusive
+ (evil-repeat-find-char (- (or count 1))))
+
+;; ceci n'est pas une pipe
+(evil-define-motion evil-goto-column (count)
+ "Go to column COUNT on the current line.
+Columns are counted from zero."
+ :type exclusive
+ (move-to-column (or count 0)))
+
+(evil-define-command evil-goto-mark (char &optional noerror)
+ "Go to the marker specified by CHAR."
+ :keep-visual t
+ :repeat nil
+ :type exclusive
+ :jump t
+ (interactive (list (read-char)))
+ (let ((marker (evil-get-marker char)))
+ (cond
+ ((markerp marker)
+ (switch-to-buffer (marker-buffer marker))
+ (goto-char marker))
+ ((numberp marker) (goto-char marker))
+ ((consp marker)
+ (when (or (find-buffer-visiting (car marker))
+ (and (y-or-n-p (format "Visit file %s again? "
+ (car marker)))
+ (find-file (car marker))))
+ (goto-char (cdr marker))))
+ ((not noerror)
+ (user-error "Marker `%c' is not set%s" char
+ (if (evil-global-marker-p char) ""
+ " in this buffer"))))))
+
+(evil-define-command evil-goto-mark-line (char &optional noerror)
+ "Go to the line of the marker specified by CHAR."
+ :keep-visual t
+ :repeat nil
+ :type line
+ :jump t
+ (interactive (list (read-char)))
+ (evil-goto-mark char noerror)
+ (evil-first-non-blank))
+
+(declare-function goto-last-change "ext:goto-chg")
+(declare-function goto-last-change-reverse "ext:goto-chg")
+
+(evil-define-motion evil-goto-last-change (count)
+ "Like `goto-last-change' but takes a COUNT rather than a span."
+ (setq this-command 'goto-last-change)
+ (dotimes (_ (or count 1))
+ (goto-last-change nil)))
+
+(evil-define-motion evil-goto-last-change-reverse (count)
+ "Like `goto-last-change-reverse' but takes a COUNT rather than a span."
+ (setq this-command 'goto-last-change-reverse)
+ (dotimes (_ (or count 1))
+ (goto-last-change-reverse nil)))
+
+(evil-define-motion evil-jump-backward (count)
+ "Go to older position in jump list.
+To go the other way, press \
+\\<evil-motion-state-map>\\[evil-jump-forward]."
+ (evil--jump-backward count))
+
+(evil-define-motion evil-jump-forward (count)
+ "Go to newer position in jump list.
+To go the other way, press \
+\\<evil-motion-state-map>\\[evil-jump-backward]."
+ (evil--jump-forward count))
+
+(evil-define-motion evil-jump-backward-swap (_count)
+ "Go to the previous position in jump list.
+The current position is placed in the jump list."
+ (let ((pnt (point)))
+ (evil--jump-backward 1)
+ (evil-set-jump pnt)))
+
+(defvar xref-prompt-for-identifier)
+(evil-define-motion evil-jump-to-tag (arg)
+ "Jump to tag under point.
+If called with a prefix argument, provide a prompt
+for specifying the tag."
+ :jump t
+ (interactive "P")
+ (cond
+ ((fboundp 'xref-find-definitions)
+ (let ((xref-prompt-for-identifier arg))
+ (call-interactively #'xref-find-definitions)))
+ ((fboundp 'find-tag)
+ (if arg (call-interactively #'find-tag)
+ (let ((tag (funcall (or find-tag-default-function
+ (get major-mode 'find-tag-default-function)
+ #'find-tag-default))))
+ (find-tag (or tag (user-error "No tag found around point"))))))))
+
+(evil-define-motion evil-lookup ()
+ "Look up the keyword at point.
+Calls `evil-lookup-func'."
+ (funcall evil-lookup-func))
+
+(defun evil-ret-gen (count indent?)
+ (let ((widget (or (get-char-property (point) 'field)
+ (get-char-property (point) 'button)
+ (get-char-property (point) 'widget-doc))))
+ (cond
+ ((and widget
+ (fboundp 'widget-type)
+ (fboundp 'widget-button-press)
+ (or (and (symbolp widget)
+ (get widget 'widget-type))
+ (and (consp widget)
+ (get (widget-type widget) 'widget-type))))
+ (when (evil-operator-state-p)
+ (setq evil-inhibit-operator t))
+ (when (fboundp 'widget-button-press)
+ (widget-button-press (point))))
+ ((and (fboundp 'button-at)
+ (fboundp 'push-button)
+ (button-at (point)))
+ (when (evil-operator-state-p)
+ (setq evil-inhibit-operator t))
+ (push-button))
+ ((or (evil-emacs-state-p)
+ (and (evil-insert-state-p)
+ (not buffer-read-only)))
+ (if (not indent?)
+ (newline count)
+ (delete-horizontal-space t)
+ (newline count)
+ (indent-according-to-mode)))
+ (t (evil-next-line-first-non-blank count)))))
+
+(evil-define-motion evil-ret (count)
+ "Move the cursor COUNT lines down.
+If point is on a widget or a button, click on it.
+In Insert state, insert a newline."
+ :type line
+ (evil-ret-gen count nil))
+
+(evil-define-motion evil-ret-and-indent (count)
+ "Move the cursor COUNT lines down.
+If point is on a widget or a button, click on it.
+In Insert state, insert a newline and indent."
+ :type line
+ (evil-ret-gen count t))
+
+(evil-define-motion evil-window-top (count)
+ "Move the cursor to line COUNT from the top of the window."
+ :jump t
+ :type line
+ (evil-ensure-column
+ (move-to-window-line
+ (max (or count 0)
+ (if (or (zerop scroll-margin)
+ (= (point-min) (window-start))
+ (< (count-screen-lines (window-start) (point))
+ scroll-margin))
+ 0
+ scroll-margin)))))
+
+(evil-define-motion evil-window-middle ()
+ "Move the cursor to the middle line in the window."
+ :jump t
+ :type line
+ (evil-ensure-column (move-to-window-line nil)))
+
+(evil-define-motion evil-window-bottom (count)
+ "Move the cursor to line COUNT from the bottom of the window."
+ :jump t
+ :type line
+ (evil-ensure-column
+ (move-to-window-line
+ (- (max (or count 1)
+ (if (or (zerop scroll-margin)
+ (< (count-screen-lines (point) (window-end))
+ scroll-margin))
+ 1
+ (1+ scroll-margin)))))))
+
+;; scrolling
+(evil-define-command evil-scroll-line-up (count)
+ "Scroll the window COUNT lines upwards."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (let (scroll-preserve-screen-position) (scroll-down count)))
+
+(evil-define-command evil-scroll-line-down (count)
+ "Scroll the window COUNT lines downwards."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (let (scroll-preserve-screen-position) (scroll-up count)))
+
+(evil-define-command evil-scroll-count-reset ()
+ "Set `evil-scroll-count' to 0.
+`evil-scroll-up' and `evil-scroll-down' will then scroll by half of
+the screen (the default)."
+ :repeat nil
+ :keep-visual t
+ (interactive)
+ (setq evil-scroll-count 0))
+
+(defun evil--get-scroll-count (count)
+ "Given a user-supplied COUNT, return scroll count."
+ (cl-flet ((posint (x) (and (natnump x) (< 0 x) x)))
+ (or (posint count)
+ (posint evil-scroll-count)
+ (/ (window-body-height) 2))))
+
+;; With `scroll-preserve-screen-position' `scroll-up'/`scroll-down'
+;; target the same cursor pixel Y-coordinate while `last-command' has
+;; the `scroll-command' property. However the target needs updating
+;; when e.g. scrolling maximally to the first or last line and then
+;; switching scroll direction. Do this by resetting `last-command'
+;; when `real-this-command' (`evil-ensure-column' modifies
+;; `this-command') changed from last value:
+
+(evil-define-command evil-scroll-up (count)
+ "Scroll the window and the cursor COUNT lines upwards.
+If COUNT is not specified the function scrolls up `evil-scroll-count'
+lines, which is the last used count.
+If the scroll count is zero the command scrolls half the screen."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (when (= (line-beginning-position) (point-min))
+ (signal 'beginning-of-buffer nil))
+ (setq count (evil--get-scroll-count count))
+ (evil-ensure-column
+ (let ((opoint (point)))
+ (condition-case nil
+ (let ((scroll-preserve-screen-position 'always)
+ (last-command (when (eq real-last-command real-this-command)
+ real-last-command)))
+ (scroll-down count))
+ (:success
+ ;; Redo if `scroll-down' only did partial scroll up to BOB
+ (when (<= (window-start) (point-min))
+ (goto-char opoint)
+ (vertical-motion (- count))))
+ (beginning-of-buffer (vertical-motion (- count)))))))
+(put 'evil-scroll-up 'scroll-command t)
+
+(evil-define-command evil-scroll-down (count)
+ "Scroll the window and the cursor COUNT lines downwards.
+If COUNT is not specified the function scrolls down
+`evil-scroll-count' lines, which is the last used count.
+If the scroll count is zero the command scrolls half the screen."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (when (= (line-end-position) (point-max))
+ (signal 'end-of-buffer nil))
+ (setq count (evil--get-scroll-count count))
+ (evil-ensure-column
+ ;; BUG #660: First check whether the eob is visible.
+ ;; In that case we do not scroll but merely move point.
+ (if (<= (point-max) (window-end))
+ (vertical-motion count)
+ (condition-case nil
+ (let ((scroll-preserve-screen-position 'always)
+ (last-command (when (eq real-last-command real-this-command)
+ real-last-command)))
+ (scroll-up count))
+ (:success
+ ;; If EOB became visible: Scroll it to the bottom
+ (save-excursion
+ (goto-char (window-start))
+ (vertical-motion (max 0 (- (window-height) 1 scroll-margin)))
+ (when (<= (point-max) (point)) (recenter -1))))
+ (end-of-buffer (goto-char (point-max)) (recenter -1))))))
+(put 'evil-scroll-down 'scroll-command t)
+
+(evil-define-command evil-scroll-page-up (count)
+ "Scroll the window COUNT pages upwards."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (evil-ensure-column
+ (dotimes (i count)
+ (condition-case err
+ (scroll-down nil)
+ (beginning-of-buffer
+ (if (and (bobp) (zerop i))
+ (signal (car err) (cdr err))
+ (goto-char (point-min))))))))
+
+(evil-define-command evil-scroll-page-down (count)
+ "Scroll the window COUNT pages downwards."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (evil-ensure-column
+ (dotimes (i count)
+ (condition-case err
+ (scroll-up nil)
+ (end-of-buffer
+ (if (and (eobp) (zerop i))
+ (signal (car err) (cdr err))
+ (goto-char (point-max))))))))
+
+(evil-define-command evil-scroll-line-to-top (count)
+ "Scroll line number COUNT (or the cursor line) to the top of the window."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (when count
+ (evil-save-column
+ (goto-char (point-min))
+ (forward-line (1- count))))
+ (recenter 0))
+
+(evil-define-command evil-scroll-line-to-top-first-non-blank (count)
+ "Scroll line number COUNT (or the cursor line) to the top of the window.
+Then move the cursor to the first non-blank character of that line."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (evil-scroll-line-to-top count)
+ (evil-first-non-blank))
+
+(evil-define-command evil-scroll-line-to-center (count)
+ "Scroll line number COUNT (or the cursor line) to the center of the window."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (when count
+ (evil-save-column
+ (goto-char (point-min))
+ (forward-line (1- count))))
+ (recenter))
+
+(evil-define-command evil-scroll-line-to-center-first-non-blank (count)
+ "Scroll line number COUNT (or the cursor line) to the center of the window.
+Then move the cursor to the first non-blank character of that line."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (evil-scroll-line-to-center count)
+ (evil-first-non-blank))
+
+(evil-define-command evil-scroll-line-to-bottom (count)
+ "Scroll line number COUNT (or the cursor line) to the bottom of the window."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (when count
+ (evil-save-column
+ (goto-char (point-min))
+ (forward-line (1- count))))
+ (recenter -1))
+
+(evil-define-command evil-scroll-line-to-bottom-first-non-blank (count)
+ "Scroll line number COUNT (or the cursor line) to the bottom of the window.
+Then move the cursor to the first non-blank character of that line."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (evil-scroll-line-to-bottom count)
+ (evil-first-non-blank))
+
+(evil-define-command evil-scroll-bottom-line-to-top (count)
+ "Scroll the line right below the window,
+or line COUNT to the top of the window."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (unless count
+ (goto-char (window-end))
+ (evil-first-non-blank))
+ (evil-scroll-line-to-top count))
+
+(evil-define-command evil-scroll-top-line-to-bottom (count)
+ "Scroll the line right above the window,
+or line COUNT to the bottom of the window."
+ :repeat nil
+ :keep-visual t
+ (interactive "<c>")
+ (unless count
+ (goto-char (window-start))
+ (evil-first-non-blank))
+ (evil-scroll-line-to-bottom count))
+
+(evil-define-command evil-scroll-left (count)
+ "Scroll the window COUNT half-screenwidths to the left."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (evil-with-hproject-point-on-window
+ (scroll-right (* count (/ (window-width) 2)))))
+
+(evil-define-command evil-scroll-right (count)
+ "Scroll the window COUNT half-screenwidths to the right."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (evil-with-hproject-point-on-window
+ (scroll-left (* count (/ (window-width) 2)))))
+
+(evil-define-command evil-scroll-column-left (count)
+ "Scroll the window COUNT columns to the left."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (evil-with-hproject-point-on-window
+ (scroll-right count)))
+
+(evil-define-command evil-scroll-column-right (count)
+ "Scroll the window COUNT columns to the right."
+ :repeat nil
+ :keep-visual t
+ (interactive "p")
+ (evil-with-hproject-point-on-window
+ (scroll-left count)))
+
+(evil-define-command evil-scroll-end-column ()
+ "Scroll the window to position the cursor at the end (right side) of the screen.
+Warn if `hscroll-margin' > 0, as cursor will be `hscroll-margin' chars from
+the right edge."
+ :repeat nil
+ :keep-visual t
+ (interactive)
+ (let* ((window-hpos (- (current-column) (window-hscroll)))
+ (dist-from-right-edge (- (window-width) window-hpos)))
+ (when (< 0 hscroll-margin)
+ (evil-echo "%s: hscroll-margin = %d" this-command hscroll-margin))
+ (evil-scroll-column-left (- dist-from-right-edge (abs (* 2 hscroll-margin))))))
+
+(evil-define-command evil-scroll-start-column ()
+ "Scroll the window to position the cursor at the start (left side) of the screen.
+Warn if `hscroll-margin' > 0, as cursor will be `hscroll-margin' chars from
+the left edge."
+ :repeat nil
+ :keep-visual t
+ (interactive)
+ (let ((initial-column (current-column))
+ (initial-hscroll (window-hscroll)))
+ (when (< 0 hscroll-margin)
+ (evil-echo "%s: hscroll-margin = %d" this-command hscroll-margin))
+ (evil-scroll-column-right (- initial-column initial-hscroll hscroll-margin 1))))
+
+;;; Text objects
+
+;; Text objects are defined with `evil-define-text-object'. In Visual
+;; state, they modify the current selection; in Operator-Pending
+;; state, they return a pair of buffer positions. Outer text objects
+;; are bound in the keymap `evil-outer-text-objects-map', and inner
+;; text objects are bound in `evil-inner-text-objects-map'.
+;;
+;; Common text objects like words, WORDS, paragraphs and sentences are
+;; defined via a corresponding move-function. This function must have
+;; the following properties:
+;;
+;; 1. Take exactly one argument, the count.
+;; 2. When the count is positive, move point forward to the first
+;; character after the end of the next count-th object.
+;; 3. When the count is negative, move point backward to the first
+;; character of the count-th previous object.
+;; 4. If point is placed on the first character of an object, the
+;; backward motion does NOT count that object.
+;; 5. If point is placed on the last character of an object, the
+;; forward motion DOES count that object.
+;; 6. The return value is "count left", i.e., in forward direction
+;; count is decreased by one for each successful move and in
+;; backward direction count is increased by one for each
+;; successful move, returning the final value of count.
+;; Therefore, if the complete move is successful, the return
+;; value is 0.
+;;
+;; A useful macro in this regard is `evil-motion-loop', which quits
+;; when point does not move further and returns the count difference.
+;; It also provides a "unit value" of 1 or -1 for use in each
+;; iteration. For example, a hypothetical "foo-bar" move could be
+;; written as such:
+;;
+;; (defun foo-bar (count)
+;; (evil-motion-loop (var count)
+;; (forward-foo var) ; `var' is 1 or -1 depending on COUNT
+;; (forward-bar var)))
+;;
+;; If "forward-foo" and "-bar" didn't accept negative arguments,
+;; we could choose their backward equivalents by inspecting `var':
+;;
+;; (defun foo-bar (count)
+;; (evil-motion-loop (var count)
+;; (cond
+;; ((< var 0)
+;; (backward-foo 1)
+;; (backward-bar 1))
+;; (t
+;; (forward-foo 1)
+;; (forward-bar 1)))))
+;;
+;; After a forward motion, point has to be placed on the first
+;; character after some object, unless no motion was possible at all.
+;; Similarly, after a backward motion, point has to be placed on the
+;; first character of some object. This implies that point should
+;; NEVER be moved to eob or bob, unless an object ends or begins at
+;; eob or bob. (Usually, Emacs motions always move as far as possible.
+;; But we want to use the motion-function to identify certain objects
+;; in the buffer, and thus exact movement to object boundaries is
+;; required.)
+
+(evil-define-text-object evil-a-word (count &optional beg end _type)
+ "Select a word."
+ (evil-select-a-restricted-object 'evil-word beg end type count))
+
+(evil-define-text-object evil-inner-word (count &optional beg end _type)
+ "Select inner word."
+ (evil-select-inner-restricted-object 'evil-word beg end type count))
+
+(evil-define-text-object evil-a-WORD (count &optional beg end _type)
+ "Select a WORD."
+ (evil-select-a-restricted-object 'evil-WORD beg end type count))
+
+(evil-define-text-object evil-inner-WORD (count &optional beg end _type)
+ "Select inner WORD."
+ (evil-select-inner-restricted-object 'evil-WORD beg end type count))
+
+(evil-define-text-object evil-a-symbol (count &optional beg end _type)
+ "Select a symbol."
+ (evil-select-an-object 'evil-symbol beg end type count))
+
+(evil-define-text-object evil-inner-symbol (count &optional beg end _type)
+ "Select inner symbol."
+ (evil-select-inner-object 'evil-symbol beg end type count))
+
+(evil-define-text-object evil-a-sentence (count &optional beg end _type)
+ "Select a sentence."
+ (evil-select-an-object 'evil-sentence beg end type count))
+
+(evil-define-text-object evil-inner-sentence (count &optional beg end _type)
+ "Select inner sentence."
+ (evil-select-inner-object 'evil-sentence beg end type count))
+
+(evil-define-text-object evil-a-paragraph (count &optional beg end _type)
+ "Select a paragraph."
+ :type line
+ (evil-select-an-object 'evil-paragraph beg end type count t))
+
+(evil-define-text-object evil-inner-paragraph (count &optional beg end _type)
+ "Select inner paragraph."
+ :type line
+ (evil-select-inner-object 'evil-paragraph beg end type count t))
+
+(evil-define-text-object evil-a-paren (count &optional beg end _type)
+ "Select a parenthesis."
+ :extend-selection nil
+ (evil-select-paren ?\( ?\) beg end type count t))
+
+(evil-define-text-object evil-inner-paren (count &optional beg end _type)
+ "Select inner parenthesis."
+ :extend-selection nil
+ (evil-select-paren ?\( ?\) beg end type count))
+
+(evil-define-text-object evil-a-bracket (count &optional beg end _type)
+ "Select a square bracket."
+ :extend-selection nil
+ (evil-select-paren ?\[ ?\] beg end type count t))
+
+(evil-define-text-object evil-inner-bracket (count &optional beg end _type)
+ "Select inner square bracket."
+ :extend-selection nil
+ (evil-select-paren ?\[ ?\] beg end type count))
+
+(evil-define-text-object evil-a-curly (count &optional beg end _type)
+ "Select a curly bracket (\"brace\")."
+ :extend-selection nil
+ (evil-select-paren ?{ ?} beg end type count t))
+
+(evil-define-text-object evil-inner-curly (count &optional beg end _type)
+ "Select inner curly bracket (\"brace\")."
+ :extend-selection nil
+ (evil-select-paren ?{ ?} beg end type count))
+
+(evil-define-text-object evil-an-angle (count &optional beg end _type)
+ "Select an angle bracket."
+ :extend-selection nil
+ (evil-select-paren ?< ?> beg end type count t))
+
+(evil-define-text-object evil-inner-angle (count &optional beg end _type)
+ "Select inner angle bracket."
+ :extend-selection nil
+ (evil-select-paren ?< ?> beg end type count))
+
+(evil-define-text-object evil-a-single-quote (count &optional beg end _type)
+ "Select a single-quoted expression."
+ :extend-selection t
+ (evil-select-quote ?' beg end type count t))
+
+(evil-define-text-object evil-inner-single-quote (count &optional beg end _type)
+ "Select inner single-quoted expression."
+ :extend-selection nil
+ (evil-select-quote ?' beg end type count))
+
+(evil-define-text-object evil-a-double-quote (count &optional beg end _type)
+ "Select a double-quoted expression."
+ :extend-selection t
+ (evil-select-quote ?\" beg end type count t))
+
+(evil-define-text-object evil-inner-double-quote (count &optional beg end _type)
+ "Select inner double-quoted expression."
+ :extend-selection nil
+ (evil-select-quote ?\" beg end type count))
+
+(evil-define-text-object evil-a-back-quote (count &optional beg end _type)
+ "Select a back-quoted expression."
+ :extend-selection t
+ (evil-select-quote ?\` beg end type count t))
+
+(evil-define-text-object evil-inner-back-quote (count &optional beg end _type)
+ "Select inner back-quoted expression."
+ :extend-selection nil
+ (evil-select-quote ?\` beg end type count))
+
+(evil-define-text-object evil-a-tag (count &optional beg end _type)
+ "Select a tag block."
+ :extend-selection nil
+ (evil-select-xml-tag beg end type count t))
+
+(evil-define-text-object evil-inner-tag (count &optional beg end _type)
+ "Select inner tag block."
+ :extend-selection nil
+ (evil-select-xml-tag beg end type count))
+
+(defun evil-match (direction count)
+ "Find COUNTth next match in DIRECTION."
+ (defvar evil-search-module)
+ (unless (eq evil-search-module 'evil-search)
+ (user-error "Match text objects only work with Evil search module"))
+ (let ((pnt (point))
+ (count (abs count)) ; Undo effect of evil-visual-direction
+ (evil-ex-search-direction 'backward)
+ (visual-state (evil-visual-state-p))
+ on-start-match in-match on-end-match)
+ (save-excursion
+ (unless (eobp) (forward-char)) ; If on start of a match, stay there
+ (evil-ex-search 1)
+ (setq on-start-match (= evil-ex-search-match-beg pnt)
+ in-match (<= evil-ex-search-match-beg pnt (1- evil-ex-search-match-end))
+ on-end-match (= (1- evil-ex-search-match-end) pnt)
+ evil-ex-search-direction direction)
+ (cond
+ ((and visual-state on-start-match (eq 'backward direction))
+ (evil-ex-search count))
+ ((and visual-state on-end-match (eq 'forward direction))
+ (evil-ex-search count))
+ ((or in-match (eq 'backward direction))
+ (evil-ex-search (1- count)))
+ (t (evil-ex-search count)))
+ (setq pnt (point)))
+ (goto-char pnt)
+ (cond
+ ((evil-normal-state-p)
+ (evil-visual-select evil-ex-search-match-beg
+ evil-ex-search-match-end
+ 'inclusive
+ (pcase direction ('forward +1) ('backward -1))
+ t)
+ (list evil-ex-search-match-beg evil-ex-search-match-end))
+ ((and visual-state (eq 'forward direction))
+ (goto-char (1- evil-ex-search-match-end)))
+ ((and visual-state (eq 'backward direction))
+ (goto-char evil-ex-search-match-beg))
+ ;; e.g. operator pending...
+ (t (list evil-ex-search-match-beg evil-ex-search-match-end)))))
+
+(evil-define-text-object evil-next-match (count &optional _beg _end _type)
+ "Select next match."
+ :extend-selection t
+ (evil-match 'forward count))
+
+(evil-define-text-object evil-previous-match (count &optional _beg _end _type)
+ "Select previous match."
+ :extend-selection t
+ (evil-match 'backward count))
+
+;;; Operator commands
+
+(evil-define-operator evil-yank (beg end type register yank-handler)
+ "Save the characters in motion into the kill-ring."
+ :move-point nil
+ :repeat nil
+ (interactive "<R><x><y>")
+ (let ((evil-was-yanked-without-register
+ (and evil-was-yanked-without-register (not register))))
+ (cond
+ ((and (fboundp 'cua--global-mark-active)
+ (fboundp 'cua-copy-region-to-global-mark)
+ (cua--global-mark-active))
+ (cua-copy-region-to-global-mark beg end))
+ ((eq type 'block)
+ (evil-yank-rectangle beg end register yank-handler))
+ ((memq type '(line screen-line))
+ (evil-yank-lines beg end register yank-handler))
+ (t
+ (evil-yank-characters beg end register yank-handler)
+ (goto-char beg)))))
+
+(defun evil-expand-line-for-line-based-operators (beg end type)
+ "Expand to line when in visual mode possibly changing BEG, END and TYPE.
+Avoids double expansion for line-based commands like \"V\" or \"D\"."
+ (when (evil-visual-state-p)
+ (unless (memq type '(line block screen-line))
+ ;; Subtract 1 from end to avoid expanding to the next line
+ ;; when \n is part of the visually selected region.
+ ;; If removed (evil-expand beg end 'line)
+ ;; will expand to the end of the next line instead of the current
+ ;; line which will cause line expanding commands like 'Y' to
+ ;; misbehave when used in visual state.
+ (when (eq ?\n (char-before end))
+ (cl-decf end))
+ (let ((range (evil-expand beg end (if (and evil-respect-visual-line-mode
+ visual-line-mode)
+ 'screen-line
+ 'line))))
+ (setq beg (evil-range-beginning range)
+ end (evil-range-end range)
+ type (evil-type range))))
+ (evil-exit-visual-state))
+ (list beg end type))
+
+(evil-define-operator evil-yank-line (beg end type register)
+ "Save whole lines into the kill-ring."
+ :motion evil-line-or-visual-line
+ :move-point nil
+ (interactive "<R><x>")
+ (cl-destructuring-bind
+ (beg end type) (evil-expand-line-for-line-based-operators beg end type)
+ (evil-yank beg end type register)))
+
+(evil-define-operator evil-delete (beg end type register yank-handler)
+ "Delete text from BEG to END with TYPE.
+Save in REGISTER or in the kill-ring with YANK-HANDLER."
+ (interactive "<R><x><y>")
+ (when (and (memq type '(inclusive exclusive))
+ (not (evil-visual-state-p))
+ (eq 'evil-delete evil-this-operator)
+ (save-excursion (goto-char beg) (bolp))
+ (save-excursion (goto-char end) (eolp))
+ (<= 1 (evil-count-lines beg end)))
+ ;; Imitate Vi strangeness: if motion meets above criteria,
+ ;; delete linewise. Not for change operator or visual state.
+ (let ((new-range (evil-line-expand beg end)))
+ (setq beg (car new-range)
+ end (cadr new-range)
+ type 'line)))
+ (unless register
+ (let ((text (filter-buffer-substring beg end)))
+ (unless (string-match-p "\n" text)
+ ;; set the small delete register
+ (evil-set-register ?- text))))
+ (let ((evil-was-yanked-without-register nil))
+ (evil-yank beg end type register yank-handler))
+ (cond
+ ((eq type 'block)
+ (evil-apply-on-block #'delete-region beg end nil))
+ ((and (eq type 'line)
+ (= end (point-max))
+ (or (= beg end)
+ (/= (char-before end) ?\n))
+ (/= beg (point-min))
+ (= (char-before beg) ?\n))
+ (delete-region (1- beg) end))
+ (t (delete-region beg end)))
+ (when (and (eq type 'line)
+ (called-interactively-p 'any))
+ (evil-first-non-blank)
+ (when (and (not evil-start-of-line)
+ evil-operator-start-col
+ ;; Special exceptions to ever saving column:
+ (not (memq evil-this-motion '(evil-forward-word-begin
+ evil-forward-WORD-begin))))
+ (move-to-column (if (and (eq most-positive-fixnum temporary-goal-column)
+ (memq last-command '(next-line previous-line)))
+ temporary-goal-column
+ evil-operator-start-col)))))
+
+(evil-define-operator evil-delete-line (beg end type register yank-handler)
+ "Delete to end of line."
+ :motion evil-end-of-line-or-visual-line
+ (interactive "<R><x>")
+ (cl-destructuring-bind
+ (beg end type) (evil-expand-line-for-line-based-operators beg end type)
+ (if (eq type 'block)
+ ;; Equivalent to $d, i.e., we use the block-to-eol selection and
+ ;; call `evil-delete'. In this case we fake the call to
+ ;; `evil-end-of-line' by setting `temporary-goal-column' and
+ ;; `last-command' appropriately as `evil-end-of-line' would do.
+ (let ((temporary-goal-column most-positive-fixnum)
+ (last-command 'next-line))
+ (evil-delete beg end 'block register yank-handler))
+ (evil-delete beg end type register yank-handler)
+ (when (eq 'line type)
+ (evil-first-non-blank)
+ (when (and (not evil-start-of-line) evil-operator-start-col)
+ (move-to-column (if (and (eq most-positive-fixnum temporary-goal-column)
+ (memq last-command '(next-line previous-line)))
+ temporary-goal-column
+ evil-operator-start-col)))))))
+
+(evil-define-operator evil-delete-whole-line
+ (beg end type register yank-handler)
+ "Delete whole line."
+ :motion evil-line-or-visual-line
+ (interactive "<R><x>")
+ (evil-delete beg end type register yank-handler))
+
+(evil-define-operator evil-delete-char (beg end type register)
+ "Delete next character."
+ :motion evil-forward-char
+ (interactive "<R><x>")
+ (evil-delete beg end type register))
+
+(evil-define-operator evil-delete-backward-char (beg end type register)
+ "Delete previous character."
+ :motion evil-backward-char
+ (interactive "<R><x>")
+ (evil-delete beg end type register))
+
+(evil-define-command evil-delete-backward-char-and-join (_count)
+ "Delete previous character and join lines.
+If point is at the beginning of a line then the current line will
+be joined with the previous line if and only if
+`evil-backspace-join-lines'."
+ (interactive "p")
+ (if (or evil-backspace-join-lines (not (bolp)))
+ (call-interactively #'delete-backward-char)
+ (signal 'beginning-of-line nil)))
+
+(evil-define-command evil-delete-backward-word ()
+ "Delete previous word."
+ (let ((beg (save-excursion (evil-backward-word-begin) (point)))
+ (end (point)))
+ (cond
+ ((evil-replace-state-p) (while (< beg (point))
+ (evil-replace-backspace)))
+ ((or (not (bolp)) (bobp)) (delete-region (max beg (line-beginning-position))
+ end))
+ (evil-backspace-join-lines (delete-char -1))
+ (t (signal 'beginning-of-line nil)))))
+
+(evil-define-command evil-delete-back-to-indentation ()
+ "Delete back to the first non-whitespace character.
+If point is before the first non-whitespace character of a
+current line then delete from the point to the beginning of the
+current line. If point is on the beginning of the line, behave
+according to `evil-backspace-join-lines'."
+ (let ((beg (if (<= (current-column) (current-indentation))
+ (line-beginning-position)
+ (save-excursion (evil-first-non-blank) (point)))))
+ (cond
+ ((and (bolp) (evil-replace-state-p)) (evil-replace-backspace))
+ ((bolp) (evil-delete-backward-char-and-join 1))
+ ((evil-replace-state-p)
+ (while (< beg (point)) (evil-replace-backspace)))
+ (t (delete-region beg (point))))))
+
+(defun evil-ex-delete-or-yank (should-delete beg end type register count yank-handler)
+ "Execute evil-delete or evil-yank on the given region.
+If SHOULD-DELETE is t, evil-delete will be executed, otherwise
+evil-yank.
+The region specified by BEG and END will be adjusted if COUNT is
+given."
+ (when count
+ ;; with COUNT, the command should go the end of the region and delete/yank
+ ;; COUNT lines from there
+ (setq beg (save-excursion (goto-char end)
+ (line-beginning-position 0))
+ end (save-excursion (goto-char end)
+ (line-beginning-position count))
+ type 'line))
+ (funcall (if should-delete #'evil-delete #'evil-yank)
+ beg end type register yank-handler))
+
+(evil-define-operator evil-ex-delete (beg end type register count yank-handler)
+ "The Ex delete command.
+\[BEG,END]delete [REGISTER] [COUNT]"
+ (interactive "<R><xc/><y>")
+ (evil-ex-delete-or-yank t beg end type register count yank-handler))
+
+(evil-define-operator evil-ex-yank (beg end type register count yank-handler)
+ "The Ex yank command.
+\[BEG,END]yank [REGISTER] [COUNT]"
+ :restore-point t
+ (interactive "<R><xc/><y>")
+ (evil-ex-delete-or-yank nil beg end type register count yank-handler))
+
+(evil-define-command evil-ex-put (_beg end ex-arg &optional force)
+ (interactive "<r><a><!>")
+ (let* ((arg-chars (remove ?\s (string-to-list ex-arg)))
+ (reg (or (car arg-chars) ?\"))
+ (text (cond
+ ((and (< 1 (length arg-chars))
+ (/= ?= reg))
+ (user-error "Trailing characters"))
+ ((eq ?= reg)
+ (evil--eval-expr (if (= 1 (length arg-chars))
+ evil-last-=-register-input
+ (setq evil-last-=-register-input (substring ex-arg 1)))))
+ (t (evil-get-register reg)))))
+ (unless text (user-error "Nothing in register %c" reg))
+ (evil-remove-yank-excluded-properties text)
+ (goto-char (if (= (point-max) end) end (1- end)))
+ (if force (evil-insert-newline-above) (evil-insert-newline-below))
+ (evil-set-marker ?\[ (point))
+ ;; `insert' rather than `insert-for-yank' as we want to ignore yank-handlers...
+ (insert (if (and (< 0 (length text))
+ (eq ?\n (aref text (1- (length text)))))
+ (substring text 0 (1- (length text)))
+ text))
+ (evil-set-marker ?\] (1- (point)))
+ (back-to-indentation)
+ (evil-normal-state)))
+
+(evil-define-operator evil-change
+ (beg end type register yank-handler delete-func)
+ "Change text from BEG to END with TYPE.
+Save in REGISTER or the kill-ring with YANK-HANDLER.
+DELETE-FUNC is a function for deleting text, default `evil-delete'.
+If TYPE is `line', insertion starts on an empty line.
+If TYPE is `block', the inserted text in inserted at each line
+of the block."
+ (interactive "<R><x><y>")
+ (let ((delete-func (or delete-func #'evil-delete))
+ (nlines (1+ (evil-count-lines beg end)))
+ opoint leftmost-point)
+ (save-excursion
+ (goto-char beg)
+ (setq opoint (line-beginning-position))
+ (setq leftmost-point
+ (let ((inhibit-field-text-motion t)) (line-beginning-position))))
+ (unless (eq evil-want-fine-undo t)
+ (evil-start-undo-step))
+ (funcall delete-func beg end type register yank-handler)
+ (cond
+ ((eq type 'line)
+ (setq this-command 'evil-change-whole-line) ; for evil-maybe-remove-spaces
+ (cond
+ ((/= opoint leftmost-point) (evil-insert 1)) ; deletion didn't delete line
+ ((= opoint (point)) (evil-open-above 1))
+ (t (evil-open-below 1))))
+ ((eq type 'block)
+ (evil-insert 1 nlines))
+ (t (evil-insert 1)))
+ (setq evil-this-register nil)))
+
+(evil-define-operator evil-change-line (beg end type register yank-handler)
+ "Change to end of line, or change whole line if characterwise visual mode."
+ :motion evil-end-of-line-or-visual-line
+ (interactive "<R><x><y>")
+ (if (and (evil-visual-state-p) (eq type 'inclusive))
+ (cl-destructuring-bind
+ (beg end _type) (evil-expand-line-for-line-based-operators beg end type)
+ (evil-change-whole-line beg end register yank-handler))
+ (evil-change beg end type register yank-handler #'evil-delete-line)))
+
+(evil-define-operator evil-change-whole-line
+ (beg end register yank-handler)
+ "Change whole line."
+ :motion evil-line-or-visual-line
+ :type line
+ (interactive "<r><x>")
+ (evil-change beg end 'line register yank-handler))
+
+(evil-define-command evil-copy (beg end address)
+ "Copy lines in BEG END below line given by ADDRESS."
+ :motion evil-line-or-visual-line
+ (interactive "<r><addr>")
+ (goto-char (point-min))
+ (forward-line address)
+ (let* ((txt (buffer-substring-no-properties beg end))
+ (len (length txt)))
+ ;; ensure text consists of complete lines
+ (when (or (zerop len) (/= (aref txt (1- len)) ?\n))
+ (setq txt (concat txt "\n")))
+ (when (and (eobp) (not (bolp))) (newline)) ; incomplete last line
+ (insert txt)
+ (forward-line -1)))
+
+(evil-define-command evil-move (beg end address)
+ "Move lines in BEG .. END below the line given by ADDRESS."
+ :motion evil-line-or-visual-line
+ (interactive "<r><addr>")
+ (unless (= (1+ address) (line-number-at-pos beg))
+ (goto-char (point-min))
+ (forward-line address)
+ (let* ((m (set-marker (make-marker) (point)))
+ (txt (buffer-substring-no-properties beg end))
+ (len (length txt))
+ (last-line-blank (progn (goto-char (point-max)) (bolp))))
+ (delete-region beg end)
+ (unless last-line-blank ; as vim, preserve lack of blank last line
+ (progn (goto-char (point-max)) (when (bolp) (delete-char -1))))
+ (goto-char m)
+ (set-marker m nil)
+ ;; ensure text consists of complete lines
+ (when (or (zerop len) (/= (aref txt (1- len)) ?\n))
+ (setq txt (concat txt "\n")))
+ (when (and (eobp) (not (bolp))) (newline)) ; incomplete last line
+ (when (evil-visual-state-p)
+ (move-marker evil-visual-mark (point)))
+ (insert txt)
+ (forward-line -1)
+ (when (evil-visual-state-p)
+ (move-marker evil-visual-point (point))))))
+
+(defun evil--check-undo-system ()
+ (when (and (eq evil-undo-system 'undo-tree)
+ (not (bound-and-true-p undo-tree-mode)))
+ (user-error "Enable `global-undo-tree-mode' to use undo-tree commands.
+Add (add-hook 'evil-local-mode-hook 'turn-on-undo-tree-mode) to your init file for undo in non-file buffers.")))
+
+(evil-define-command evil-undo (count)
+ "Undo COUNT changes in buffer using `evil-undo-function'."
+ :repeat abort
+ :jump t
+ (interactive "*p")
+ (evil--check-undo-system)
+ (let ((state-before evil-state))
+ (unless (memq state-before '(normal visual)) (evil-normal-state))
+ (funcall evil-undo-function count)
+ (unless (memq state-before '(normal visual)) (evil-change-state state-before))))
+
+(evil-define-command evil-redo (count)
+ "Undo COUNT changes in buffer using `evil-redo-function'."
+ :repeat abort
+ (interactive "*p")
+ (evil--check-undo-system)
+ (funcall evil-redo-function count))
+
+(evil-define-operator evil-substitute (beg end type register)
+ "Change a character."
+ :motion evil-forward-char
+ (interactive "<R><x>")
+ (evil-change beg end type register))
+
+(evil-define-operator evil-upcase (beg end type)
+ "Convert text to upper case."
+ (if (eq type 'block)
+ (evil-apply-on-block #'evil-upcase beg end nil)
+ (upcase-region beg end)))
+
+(evil-define-operator evil-downcase (beg end type)
+ "Convert text to lower case."
+ (if (eq type 'block)
+ (evil-apply-on-block #'evil-downcase beg end nil)
+ (downcase-region beg end)))
+
+(evil-define-operator evil-invert-case (beg end type)
+ "Invert case of text."
+ (if (eq type 'block)
+ (evil-apply-on-block #'evil-invert-case beg end nil)
+ (save-excursion
+ (goto-char beg)
+ (while (< beg end)
+ (let ((char (following-char)))
+ (delete-char 1)
+ (insert-char
+ (if (eq (upcase char) char) (downcase char) (upcase char))))
+ (setq beg (1+ beg))))))
+
+(evil-define-operator evil-invert-char (beg end type)
+ "Invert case of character."
+ :motion evil-forward-char
+ (if (eq type 'block)
+ (evil-apply-on-block #'evil-invert-case beg end nil)
+ (evil-invert-case beg end)
+ (when evil-this-motion
+ (goto-char end)
+ (when (and evil-cross-lines
+ (not evil-move-beyond-eol)
+ (not (evil-visual-state-p))
+ (not (evil-operator-state-p))
+ (eolp) (not (eobp)) (not (bolp)))
+ (forward-char)))))
+
+(evil-define-operator evil-rot13 (beg end type)
+ "ROT13 encrypt text."
+ (if (eq type 'block)
+ (evil-apply-on-block #'rot13-region beg end nil)
+ (rot13-region beg end)))
+
+(evil-define-operator evil-join (beg end)
+ "Join the selected lines."
+ :motion evil-line
+ (let ((count (count-lines beg end))
+ last-line-blank)
+ (when (> count 1)
+ (setq count (1- count)))
+ (goto-char beg)
+ (dotimes (i count)
+ (when (= (1+ i) count) ; i.e. we're just before the last join
+ (evil-move-beginning-of-line)
+ (setq last-line-blank (looking-at "[ \t]*$")))
+ (join-line 1))
+ (and last-line-blank (indent-according-to-mode))))
+
+(evil-define-operator evil-join-whitespace (beg end)
+ "Join the selected lines without changing whitespace.
+\\<evil-normal-state-map>Like \\[evil-join], \
+but doesn't insert or remove any spaces."
+ :motion evil-line
+ (let ((count (count-lines beg end)))
+ (when (> count 1)
+ (setq count (1- count)))
+ (goto-char beg)
+ (dotimes (_ count)
+ (evil-move-end-of-line 1)
+ (unless (eobp)
+ (delete-char 1)))))
+
+(evil-define-operator evil-ex-join (beg end &optional count bang)
+ "Join the selected lines with optional COUNT and BANG."
+ (interactive "<r><a><!>")
+ (let ((join-fn (if bang 'evil-join-whitespace 'evil-join)))
+ (if (not count)
+ ;; without count - just join the given region
+ (funcall join-fn beg end)
+ (unless (string-match-p "^[1-9][0-9]*$" count)
+ (user-error "Invalid count"))
+ ;; emulate Vim's :join when count is given - start from the
+ ;; end of the region and join COUNT lines from there
+ (save-excursion
+ (goto-char end)
+ (let ((beg-adjusted (line-beginning-position 0))
+ (end-adjusted (line-beginning-position (string-to-number count))))
+ (funcall join-fn beg-adjusted end-adjusted))))))
+
+(defun evil--ex-string-for-print (beg end linump borderline)
+ "Return a string to be printed by :print etc.
+Starts at line of BEG and end at line of END.
+Include line number at the start of each line if LINUMP is non-nil.
+Surround line denoted by BORDERLINE with dashes if non-nil."
+ (let ((result-string "")
+ (continue t)
+ (line-move-visual nil))
+ (save-excursion
+ (goto-char beg)
+ (while continue
+ (let* ((line-num (line-number-at-pos))
+ (border (and (natnump borderline) (= borderline line-num)))
+ (raw-line (thing-at-point 'line))
+ (line (if (string= "\n" (substring raw-line -1))
+ raw-line (concat raw-line "\n")))
+ (border-length (1- (min (length line) (frame-width)))))
+ (when border
+ (setq result-string
+ (concat result-string (make-string border-length ?-) "\n")))
+ (when linump
+ (setq result-string
+ (concat result-string
+ (propertize (number-to-string (line-number-at-pos))
+ 'face 'line-number-current-line)
+ " ")))
+ (unless (eobp)
+ (setq result-string (concat result-string line)))
+ (when border
+ (setq result-string
+ (concat result-string (make-string border-length ?-) "\n")))
+ (when (or (= (point) (progn (evil-line-move 1 t) (point)))
+ (> (line-end-position) end))
+ (setq continue nil)))))
+ (string-trim-right result-string "\n")))
+
+(defun evil--ex-print-to-minibuffer (string)
+ "Print STRING to the minibuffer for better persistence."
+ (let ((keymap (make-keymap))
+ minibuffer-local-map)
+ (set-char-table-range (nth 1 keymap) t 'abort-recursive-edit)
+ (setq minibuffer-local-map keymap)
+ (read-from-minibuffer "" (propertize string 'read-only t))))
+
+(defun evil--ex-print (beg end count &optional linump borderline)
+ "Print lines in range to the minibuffer.
+Starting at BEG and ending at END + COUNT lines.
+Include line number at the start of each line if LINUMP is non-nil.
+Surround line denoted by BORDERLINE with dashes if non-nil."
+ (let* ((count (cond ((stringp count) (string-to-number count))
+ ((natnump count) count)
+ (t 1)))
+ (end (save-excursion (goto-char (if (= (point-max) end) end (1- end)))
+ (line-end-position count)))
+ (substring (evil--ex-string-for-print beg end linump borderline)))
+ (cond ((> 1 count) (user-error "Positive count required"))
+ (evil--ex-global-active-p
+ (setq evil--ex-print-accumulator
+ (if (string= "" evil--ex-print-accumulator)
+ (concat evil--ex-print-accumulator substring)
+ (concat evil--ex-print-accumulator "\n" substring))))
+ (t (evil--ex-print-to-minibuffer substring)
+ (when (string-match-p "\n" substring)
+ (goto-char end)
+ (evil-beginning-of-line))))))
+
+(defun evil--global-print+clear ()
+ "Print accumulated print output from :global print, and clear."
+ (let ((s evil--ex-print-accumulator))
+ (unless (string= s "")
+ (setq evil--ex-print-accumulator "")
+ (evil--ex-print-to-minibuffer s))))
+(add-hook 'evil-after-global-hook #'evil--global-print+clear)
+
+(evil-define-command evil-ex-print (beg end &optional count)
+ (interactive "<r><a>")
+ (evil--ex-print beg end count))
+
+(evil-define-command evil-ex-numbered-print (beg end &optional count)
+ (interactive "<r><a>")
+ (evil--ex-print beg end count t))
+
+(evil-define-command evil-ex-z (_beg end &optional zmarks _bang)
+ "Display several lines of text surrounding the line specified by range.
+BEG and END represent the range, ZMARKS represents the args in string form.
+With a count supplied in the args, display that number of lines. Without a
+count, display `evil-scroll-count' number of lines, or half the window height.
+This table explains what each mark argument does.
+
+mark | first line | last line | new cursor line
+-----+-------------------------+----------------------------+----------------
++ | current line | 1 scr (or 1 count) forward | last line
+- | 1 scr (or 1 count) back | current line | last line
+^ | 2 scr (or 2 count) back | 1 scr (or 1 count) back | last line
+. | ½ scr (or ½ count) back | ½ scr (or ½ count) forward | last line
+= | ½ scr (or ½ count) back | ½ scr (or ½ count) forward | current line
+
+Specifying no mark at all is the same as `+'.
+If the mark is `=' a line of dashes is printed around the current line.
+If a `#' is included before the mark args, the lines are numbered."
+ ;; TODO implement bang argument.
+ (interactive "<r><a><!>")
+ (goto-char (setq end (1- end)))
+ (save-match-data
+ (string-match "\\(#?\\)\\([^0-9]*\\)\\([0-9]*\\)" (or zmarks ""))
+ (cl-destructuring-bind (_ _ hs he ms me cs ce) (match-data)
+ (let* ((linump (/= hs he))
+ (mark-string (if (= ms me) "+" (substring zmarks ms me)))
+ (count-string (if (= cs ce) "" (substring zmarks cs ce)))
+ (count (evil--get-scroll-count (string-to-number count-string)))
+ (max-mini-window-height 0.5))
+ (cond
+ ((< 1 (- me ms))
+ (evil-beginning-of-line)
+ (user-error "Too many mark args (got %d, expected 1)" (- me ms)))
+ ((string= "+" mark-string)
+ (ignore-errors (beginning-of-line count))
+ (evil--ex-print end end count linump))
+ ((string= "-" mark-string)
+ (evil-beginning-of-line)
+ (evil--ex-print (line-beginning-position (- 2 count)) end 1 linump))
+ ((string= "^" mark-string)
+ (let ((end* (progn (move-end-of-line (- 1 count)) (point)))
+ (beg* (line-beginning-position (- 2 count))))
+ (evil-beginning-of-line)
+ (evil--ex-print beg* end* 1 linump)))
+ ((string= "." mark-string)
+ (let ((beg* (line-beginning-position (- 1 (floor count 2))))
+ (end* (progn (move-end-of-line (ceiling count 2)) (point))))
+ (evil-beginning-of-line)
+ (evil--ex-print beg* end* 1 linump)))
+ ((string= "=" mark-string)
+ (let ((beg* (line-beginning-position (- 1 (floor count 2))))
+ (end* (line-end-position (ceiling count 2))))
+ (evil-beginning-of-line)
+ (evil--ex-print beg* end* 1 linump (line-number-at-pos end))))
+ (t (evil-beginning-of-line)
+ (user-error "Invalid mark arg: %s" mark-string)))))))
+
+(evil-define-operator evil-fill (beg end)
+ "Fill text."
+ :move-point nil
+ :type line
+ (save-excursion
+ (ignore-errors (fill-region beg end))))
+
+(evil-define-operator evil-fill-and-move (beg end)
+ "Fill text and move point to the end of the filled region."
+ :move-point nil
+ :type line
+ (let ((marker (make-marker)))
+ (move-marker marker (1- end))
+ (ignore-errors
+ (fill-region beg end)
+ (goto-char marker)
+ (evil-first-non-blank))))
+
+(evil-define-operator evil-indent (beg end)
+ "Indent text."
+ :move-point nil
+ :type line
+ (evil-ensure-column
+ (setq this-command real-this-command) ; Reset change made by evil-ensure-column
+ (save-restriction
+ (narrow-to-region beg end)
+ (if (save-excursion (goto-char beg) (= end (line-beginning-position 2)))
+ ;; since some Emacs modes can only indent one line at a time,
+ ;; implement "==" as a call to `indent-according-to-mode'
+ (indent-according-to-mode)
+ (goto-char beg)
+ (indent-region beg end))
+ ;; Tabify or untabify leading whitespace characters
+ (when evil-indent-convert-tabs
+ ;; Whether tab or space should be used is determined by indent-tabs-mode
+ (let ((convert-fun (if indent-tabs-mode #'tabify #'untabify)))
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eolp))
+ (funcall convert-fun (point) (progn (skip-chars-forward " \t") (point)))
+ (forward-line))))))))
+
+(evil-define-operator evil-indent-line (beg end)
+ "Indent the line."
+ :motion evil-line
+ (evil-indent beg end))
+
+(evil-define-operator evil-shift-left (beg end &optional count preserve-empty)
+ "Shift text from BEG to END to the left.
+The text is shifted to the nearest multiple of `evil-shift-width'
+\(the rounding can be disabled by setting `evil-shift-round').
+If PRESERVE-EMPTY is non-nil, lines that contain only spaces are
+indented, too, otherwise they are ignored. Location of point
+is preserved relative to text when called from insert state.
+Otherwise, it is determined by `evil-start-of-line' and/or `evil-track-eol'.
+See also `evil-shift-right'."
+ :type line
+ (interactive "<r><vc>")
+ (evil-shift-right beg end (- (or count 1)) preserve-empty))
+
+(evil-define-operator evil-shift-right (beg end &optional count preserve-empty)
+ "Shift text from BEG to END to the right.
+The text is shifted to the nearest multiple of `evil-shift-width'
+\(the rounding can be disabled by setting `evil-shift-round').
+If PRESERVE-EMPTY is non-nil, lines that contain only spaces are
+indented, too, otherwise they are ignored. Location of point
+is preserved relative to text when called from insert or replace states.
+Otherwise, it is determined by `evil-start-of-line' and/or `evil-track-eol'.
+See also `evil-shift-left'."
+ :type line
+ :move-point nil ; point is moved according to `evil-start-of-line' and state
+ (interactive "<r><vc>")
+ (setq count (or count 1))
+ (let ((beg (set-marker (make-marker) beg))
+ (end (set-marker (make-marker) end))
+ (col-for-insert (current-column))
+ first-shift) ; shift of first line
+ (save-excursion
+ (goto-char beg)
+ (while (< (point) end)
+ (let* ((indent (current-indentation))
+ (new-indent
+ (max 0
+ (if (not evil-shift-round)
+ (+ indent (* count evil-shift-width))
+ (* (+ (/ indent evil-shift-width)
+ count
+ (cond
+ ((> count 0) 0)
+ ((zerop (mod indent evil-shift-width)) 0)
+ (t 1)))
+ evil-shift-width)))))
+ (unless first-shift
+ (setq first-shift (- new-indent indent)))
+ (when (or preserve-empty
+ (save-excursion
+ (skip-chars-forward " \t")
+ (not (eolp))))
+ (indent-to new-indent 0))
+ (delete-region (point) (progn (skip-chars-forward " \t") (point)))
+ (forward-line 1))))
+ ;; in case we're in an empty buffer first-shift is still unchanged
+ (unless first-shift
+ (if (< count 0)
+ (setq first-shift 0)
+ (setq first-shift (* count evil-shift-width))
+ (indent-to first-shift)))
+ ;; When called from insert state (C-t or C-d) the cursor should shift with the line,
+ ;; otherwise (normal state) its position is determined by `evil-start-of-line'.
+ (cond
+ ((or (evil-insert-state-p) (evil-replace-state-p))
+ (move-to-column (max 0 (+ col-for-insert first-shift))))
+ (evil-start-of-line (evil-first-non-blank))
+ ((evil--stick-to-eol-p) (move-end-of-line 1))
+ (t (move-to-column (or goal-column evil-operator-start-col col-for-insert))))))
+
+(defun evil-delete-indentation ()
+ "Delete all indentation on current line."
+ (interactive)
+ (save-excursion
+ (move-beginning-of-line nil)
+ (delete-region (point) (progn (skip-chars-forward " \t") (point)))))
+
+(evil-define-command evil-shift-right-line (count)
+ "Shift the current line COUNT times to the right.
+The text is shifted to the nearest multiple of
+`evil-shift-width'. Like `evil-shift-right' but always works on
+the current line."
+ (interactive "<c>")
+ (evil-shift-right (line-beginning-position) (line-beginning-position 2) count t))
+
+(evil-define-command evil-shift-left-line (count)
+ "Shift the current line COUNT times to the left.
+The text is shifted to the nearest multiple of
+`evil-shift-width'. Like `evil-shift-left' but always works on
+the current line."
+ (interactive "<c>")
+ (if (and (eq 'self-insert-command last-command)
+ (eq ?0 (char-before)))
+ (progn (delete-char -1)
+ (evil-delete-indentation))
+ (evil-shift-left (line-beginning-position) (line-beginning-position 2) count t)))
+
+(evil-define-operator evil-align-left (beg end _type &optional width)
+ "Left-align lines in the region at WIDTH columns.
+The default for width is the value of `fill-column'."
+ :motion evil-line
+ :type line
+ (interactive "<R><a>")
+ (evil-justify-lines beg end 'left (if width
+ (string-to-number width)
+ 0)))
+
+(evil-define-operator evil-align-right (beg end _type &optional width)
+ "Right-align lines in the region at WIDTH columns.
+The default for width is the value of `fill-column'."
+ :motion evil-line
+ :type line
+ (interactive "<R><a>")
+ (evil-justify-lines beg end 'right (if width
+ (string-to-number width)
+ fill-column)))
+
+(evil-define-operator evil-align-center (beg end _type &optional width)
+ "Center lines in the region between WIDTH columns.
+The default for width is the value of `fill-column'."
+ :motion evil-line
+ :type line
+ (interactive "<R><a>")
+ (evil-justify-lines beg end 'center (if width
+ (string-to-number width)
+ fill-column)))
+
+(evil-define-operator evil-replace (beg end type char)
+ "Replace text from BEG to END with CHAR."
+ :motion evil-forward-char
+ (interactive "<R>"
+ (unwind-protect
+ (let ((evil-force-cursor 'replace))
+ (evil-refresh-cursor)
+ (list (evil-read-key)))
+ (evil-refresh-cursor)))
+ (when char
+ (if (eq type 'block)
+ (save-excursion
+ (evil-apply-on-rectangle
+ #'(lambda (begcol endcol char)
+ (let ((maxcol (evil-column (line-end-position))))
+ (when (< begcol maxcol)
+ (setq endcol (min endcol maxcol))
+ (let ((beg (evil-move-to-column begcol nil t))
+ (end (evil-move-to-column endcol nil t)))
+ (delete-region beg end)
+ (insert (make-string (- endcol begcol) char))))))
+ beg end char))
+ (goto-char beg)
+ (cond
+ ((eq char ?\n)
+ (delete-region beg end)
+ (newline)
+ (when evil-auto-indent
+ (indent-according-to-mode)))
+ (t
+ (while (< (point) end)
+ (if (eq (char-after) ?\n)
+ (forward-char)
+ (delete-char 1)
+ (insert-char char 1)))
+ (goto-char (max beg (1- end))))))))
+
+(evil-define-command evil-paste-before
+ (count &optional register yank-handler)
+ "Paste the latest yanked text before the cursor position.
+The return value is the yanked text."
+ :suppress-operator t
+ (interactive "*P<x>")
+ (setq count (prefix-numeric-value count))
+ (if (evil-visual-state-p)
+ ;; This is the only difference with evil-paste-after in visual-state
+ (let ((evil-kill-on-visual-paste (not evil-kill-on-visual-paste)))
+ (evil-visual-paste count register))
+ (evil-with-undo
+ (let* ((text (copy-sequence
+ (if register
+ (evil-get-register register)
+ (current-kill 0))))
+ (yank-handler (or yank-handler
+ (when (stringp text)
+ (car-safe (get-text-property
+ 0 'yank-handler text)))))
+ (opoint (point)))
+ (when evil-paste-clear-minibuffer-first
+ (delete-minibuffer-contents)
+ (setq evil-paste-clear-minibuffer-first nil))
+ (when text
+ (if (functionp yank-handler)
+ (let ((evil-paste-count count)
+ ;; for non-interactive use
+ (this-command #'evil-paste-before))
+ (push-mark opoint t)
+ (insert-for-yank text))
+ ;; no yank-handler, default
+ (when (vectorp text)
+ (setq text (evil-vector-to-string text)))
+ (set-text-properties 0 (length text) nil text)
+ (push-mark opoint t)
+ (dotimes (_ (or count 1))
+ (insert-for-yank text))
+ (setq evil-last-paste
+ (list #'evil-paste-before
+ count
+ opoint
+ opoint ; beg
+ (point))) ; end
+ (evil-set-marker ?\[ opoint)
+ (evil-set-marker ?\] (1- (point)))
+ (when (and evil-move-cursor-back
+ (> (length text) 0))
+ (backward-char))))
+ (when evil--cursor-after
+ (if (eq 'evil-yank-line-handler yank-handler)
+ (ignore-errors (evil-next-line-first-non-blank))
+ (evil-forward-char 1 nil t))
+ (setq evil--cursor-after nil))
+ ;; no paste-pop after pasting from a register
+ (when register
+ (setq evil-last-paste nil))
+ (and (> (length text) 0) text)))))
+
+(evil-define-command evil-paste-after
+ (count &optional register yank-handler)
+ "Paste the latest yanked text behind point.
+The return value is the yanked text."
+ :suppress-operator t
+ (interactive "*P<x>")
+ (setq count (prefix-numeric-value count))
+ (if (evil-visual-state-p)
+ (evil-visual-paste count register)
+ (evil-with-undo
+ (let* ((text (copy-sequence
+ (if register
+ (evil-get-register register)
+ (current-kill 0))))
+ (yank-handler (or yank-handler
+ (when (stringp text)
+ (car-safe (get-text-property
+ 0 'yank-handler text)))))
+ (opoint (point)))
+ (when text
+ (if (functionp yank-handler)
+ (let ((evil-paste-count count)
+ ;; for non-interactive use
+ (this-command #'evil-paste-after))
+ (insert-for-yank text))
+ ;; no yank-handler, default
+ (when (vectorp text)
+ (setq text (evil-vector-to-string text)))
+ (set-text-properties 0 (length text) nil text)
+ (unless (eolp) (forward-char))
+ (push-mark (point) t)
+ ;; TODO: Perhaps it is better to collect a list of all
+ ;; (point . mark) pairs to undo the yanking for COUNT > 1.
+ ;; The reason is that this yanking could very well use
+ ;; `yank-handler'.
+ (let ((beg (point)))
+ (dotimes (_ (or count 1))
+ (insert-for-yank text))
+ (setq evil-last-paste
+ (list #'evil-paste-after
+ count
+ opoint
+ beg ; beg
+ (point))) ; end
+ (evil-set-marker ?\[ beg)
+ (evil-set-marker ?\] (1- (point)))
+ (when (evil-normal-state-p)
+ (evil-move-cursor-back)))))
+ (when evil--cursor-after
+ (if (eq 'evil-yank-line-handler yank-handler)
+ (ignore-errors (evil-next-line-first-non-blank 1))
+ (evil-forward-char 1 nil t))
+ (setq evil--cursor-after nil))
+ (when register
+ (setq evil-last-paste nil))
+ (and (> (length text) 0) text)))))
+
+(evil-define-command evil-paste-before-cursor-after
+ (count &optional register yank-handler)
+ "The same as `evil-paste-before' but
+leave the cursor just after the new text."
+ :suppress-operator t
+ (interactive "*P<x>")
+ (setq count (prefix-numeric-value count)
+ evil--cursor-after t)
+ (evil-paste-before count register yank-handler))
+
+(evil-define-command evil-paste-after-cursor-after
+ (count &optional register yank-handler)
+ "The same as `evil-paste-after' but
+leave the cursor just after the new text."
+ :suppress-operator t
+ (interactive "*P<x>")
+ (setq count (prefix-numeric-value count)
+ evil--cursor-after t)
+ (evil-paste-after count register yank-handler))
+
+(defun evil-insert-for-yank-at-col (startcol _endcol string count)
+ "Insert STRING at STARTCOL."
+ (move-to-column startcol)
+ (dotimes (_ (or count 1))
+ (insert-for-yank string))
+ (evil-set-marker ?\] (1- (point))))
+
+(evil-define-command evil-visual-paste (count &optional register)
+ "Paste over Visual selection."
+ :suppress-operator t
+ (interactive "*P<x>")
+ (setq count (prefix-numeric-value count))
+ ;; evil-visual-paste is typically called from evil-paste-before or
+ ;; evil-paste-after, but we have to mark that the paste was from
+ ;; visual state
+ (setq this-command 'evil-visual-paste)
+ (let* ((text (if register
+ (evil-get-register register)
+ (current-kill 0)))
+ (yank-handler (car-safe (get-text-property
+ 0 'yank-handler text)))
+ (dir (evil-visual-direction))
+ beg end type)
+ (evil-with-undo
+ (let ((kill-ring-yank-pointer (when kill-ring (list (current-kill 0)))))
+ (when (evil-visual-state-p)
+ (setq beg evil-visual-beginning
+ end evil-visual-end
+ type (evil-visual-type))
+ ;; When pasting charwise text into linewise selection, keep trailing NL
+ (when (and text end
+ (eq 'line type)
+ (not (eq ?\n (aref text (1- (length text))))))
+ (cl-decf end))
+ (evil-visual-rotate 'upper-left)
+ (evil-delete beg end type (unless evil-kill-on-visual-paste ?_))
+ (when (and (eq yank-handler #'evil-yank-line-handler)
+ (not (memq type '(line block)))
+ (/= end (point-max)))
+ (insert "\n"))
+ (evil-normal-state)
+ (when kill-ring (current-kill 1)))
+ ;; Effectively memoize `evil-get-register' because it can be
+ ;; side-effecting (e.g. for the "=" register)...
+ (cl-letf (((symbol-function #'evil-get-register)
+ (lambda (&rest _) text)))
+ (cond
+ ;; When replacing the last buffer line and it does not end
+ ;; in a newline, use `evil-paste-after' because
+ ;; `evil-delete' will have moved point to the line above.
+ ((cond ((eq type 'line) (= end (point-max)))
+ ((eq type 'block) (eq yank-handler #'evil-yank-line-handler)))
+ (goto-char end)
+ (evil-paste-after count register))
+ ((and (eq type 'block)
+ (not (eq yank-handler #'evil-yank-block-handler))
+ (not (string-match-p "\n" text)))
+ (evil-apply-on-block #'evil-insert-for-yank-at-col beg end t text count))
+ (t (evil-paste-before count register)))))
+ (when evil-kill-on-visual-paste
+ (current-kill -1))
+ ;; Ensure that gv can restore visually pasted area...
+ (set-marker evil-visual-point (evil-get-marker (if (< dir 0) ?\[ ?\]) t))
+ (set-marker evil-visual-mark (evil-get-marker (if (< dir 0) ?\] ?\[) t))
+ ;; mark the last paste as visual-paste
+ (setq evil-last-paste
+ (list (nth 0 evil-last-paste)
+ (nth 1 evil-last-paste)
+ (nth 2 evil-last-paste)
+ (nth 3 evil-last-paste)
+ (nth 4 evil-last-paste)
+ t)))))
+
+(defun evil-paste-from-register (register)
+ "Paste from REGISTER."
+ (interactive
+ (let ((ov (make-overlay (point) (+ (point) (if (evil-replace-state-p) 1 0)))))
+ (unwind-protect
+ (progn
+ (overlay-put ov 'invisible t)
+ (overlay-put ov 'after-string
+ #("\"" 0 1 (face minibuffer-prompt cursor 1)))
+ (list (or evil-this-register (read-char))))
+ (delete-overlay ov))))
+ (let ((opoint (point))
+ evil-move-cursor-back)
+ (evil-paste-before nil register t)
+ (when (evil-replace-state-p)
+ (let* ((reg-length (- (point) opoint))
+ (chars-to-delete (min (- (line-end-position) (point)) reg-length)))
+ ;; TODO: handle multi-line paste backspacing
+ (evil-update-replace-alist (point) reg-length chars-to-delete chars-to-delete)
+ (delete-char chars-to-delete)))))
+
+(defun evil-paste-last-insertion ()
+ "Paste last insertion."
+ (interactive)
+ (evil-paste-from-register ?.))
+
+(defun evil-paste-last-insertion-and-stop-insert ()
+ "Paste last insertion and change to normal state."
+ (interactive)
+ (evil-paste-last-insertion)
+ (evil-normal-state))
+
+(evil-define-command evil-use-register (register)
+ "Use REGISTER for the next command."
+ :keep-visual t
+ :repeat ignore
+ :suppress-operator t
+ (interactive "<C>")
+ (setq evil-this-register register))
+
+(defvar evil-macro-buffer nil
+ "The buffer that has been active on macro recording.")
+
+(defvar evil-execute-normal-keys nil
+ "The keys used to invoke the current `evil-execute-in-normal-state'.
+Can be used to detect if we are currently in that quasi-state.
+With current bindings, it will be \\<evil-insert-state-map>\\[evil-execute-in-normal-state]")
+
+(defun evil-end-and-return-macro ()
+ "Like `kmacro-end-macro' but also return the macro.
+Remove \\<evil-insert-state-map>\\[evil-execute-in-normal-state] from the end."
+ ;; `end-kbd-macro' rather than `kmacro-end-macro' to allow clearing registers
+ (end-kbd-macro nil #'kmacro-loop-setup-function)
+ (let ((end-keys-seq (append evil-execute-normal-keys nil))
+ (last-kbd-macro-seq (append last-kbd-macro nil)))
+ (unless last-kbd-macro-seq
+ (setq last-kbd-macro nil))
+ (if (and end-keys-seq last-kbd-macro-seq)
+ (apply #'vector (butlast last-kbd-macro-seq (length end-keys-seq)))
+ last-kbd-macro)))
+
+(evil-define-command evil-record-macro (register)
+ "Record a keyboard macro into REGISTER.
+If REGISTER is :, /, or ?, the corresponding command line window
+will be opened instead."
+ :keep-visual t
+ :suppress-operator t
+ (interactive
+ (list (unless (and evil-this-macro defining-kbd-macro)
+ (or evil-this-register (evil-read-key)))))
+ (let (last-macro)
+ (cond
+ ((eq register ?\C-g)
+ (keyboard-quit))
+ ((and evil-this-macro defining-kbd-macro)
+ (setq evil-macro-buffer nil
+ last-macro (ignore-errors (evil-end-and-return-macro)))
+ (when last-macro
+ (evil-set-register evil-this-macro last-macro))
+ (setq evil-this-macro nil))
+ ((eq register ?:)
+ (evil-command-window-ex))
+ ((eq register ?/)
+ (evil-command-window-search-forward))
+ ((eq register ??)
+ (evil-command-window-search-backward))
+ ((or (<= ?0 register ?9)
+ (<= ?a register ?z)
+ (<= ?A register ?Z))
+ (when defining-kbd-macro (end-kbd-macro))
+ (setq evil-this-macro register
+ evil-last-recorded-register register)
+ (evil-set-register evil-this-macro nil)
+ (kmacro-start-macro nil)
+ (setq evil-macro-buffer (current-buffer)))
+ (t (error "Invalid register `%s'" register)))))
+
+(defun evil-repeat-execute-macro (flag)
+ "Called to record a macro execution.
+FLAG is either `pre' or `post' if the function is called before resp.
+after executing the command."
+ (pcase flag
+ ('pre (evil-repeat-record (this-command-keys)))
+ ('post (evil-repeat-record (string evil-last-register)))))
+
+(evil-define-command evil-execute-macro (count macro)
+ "Execute keyboard macro MACRO, COUNT times.
+When called with a non-numerical prefix \
+\(such as \\[universal-argument]),
+COUNT is infinite. MACRO is read from a register
+when called interactively."
+ :keep-visual t
+ :suppress-operator t
+ :repeat evil-repeat-execute-macro
+ (interactive
+ (let (count macro register)
+ (setq count (cond ((null current-prefix-arg) 1)
+ ((numberp current-prefix-arg) current-prefix-arg)
+ (t 0))
+ register (or evil-this-register (read-char)))
+ (cond
+ ((or (eq register ?:)
+ (and (eq register ?@) (eq evil-last-register ?:)))
+ (setq macro #'evil-ex-repeat
+ evil-last-register ?:))
+ ((eq register ?@)
+ (unless evil-last-register
+ (user-error "No previously executed keyboard macro."))
+ (setq macro (evil-get-register evil-last-register t)))
+ (t
+ (setq macro (evil-get-register register t)
+ evil-last-register register)))
+ (list count macro)))
+ (cond
+ ((functionp macro)
+ (evil-repeat-abort)
+ (if (zerop count)
+ (while t (funcall macro))
+ (dotimes (_ (or count 1)) (funcall macro))))
+ ((or (and (not (stringp macro))
+ (not (vectorp macro)))
+ (member macro '("" [])))
+ ;; allow references to currently empty registers
+ ;; when defining macro
+ (unless evil-this-macro (user-error "No previous macro")))
+ (t
+ (condition-case err
+ (evil-with-single-undo
+ (let (pre-command-hook post-command-hook) ; For performance
+ (combine-after-change-calls
+ (execute-kbd-macro macro count)
+ (setq this-command 'evil-execute-macro)))) ; For repeatability
+ ;; enter Normal state if the macro fails
+ (error
+ (evil-normal-state)
+ (signal (car err) (cdr err)))))))
+
+(evil-define-command evil-execute-last-recorded-macro (count)
+ "Execute last recorded keyboard macro COUNT times.
+When called with a non-numerical prefix \
+\(such as \\[universal-argument]),
+COUNT is infinite."
+ :keep-visual t
+ :suppress-operator t
+ (interactive
+ (list (cond
+ ((and current-prefix-arg (numberp current-prefix-arg)) current-prefix-arg)
+ (current-prefix-arg 0)
+ (t 1))))
+ (if evil-last-recorded-register
+ (evil-execute-macro count (evil-get-register evil-last-recorded-register t))
+ (user-error "No previous macro"))
+ (setq evil-last-register evil-last-recorded-register))
+
+;;; Visual commands
+
+(evil-define-motion evil-visual-restore ()
+ "Restore previous selection."
+ (cond
+ ;; Called from visual state
+ ((and (evil-visual-state-p)
+ evil-prev-visual-mark evil-prev-visual-point evil-prev-visual-selection)
+ (let ((tmp-visual-mark (marker-position evil-visual-mark))
+ (tmp-visual-point (marker-position evil-visual-point))
+ (tmp-visual-selection evil-visual-selection))
+ (evil-visual-make-selection evil-prev-visual-mark
+ evil-prev-visual-point
+ evil-prev-visual-selection
+ t)
+ (move-marker evil-prev-visual-mark tmp-visual-mark)
+ (move-marker evil-prev-visual-point tmp-visual-point)
+ (setq evil-prev-visual-selection tmp-visual-selection)))
+ ;; Called from other state
+ ((and evil-visual-selection evil-visual-mark evil-visual-point)
+ (evil-visual-make-selection evil-visual-mark
+ evil-visual-point
+ (evil-visual-type)
+ t))))
+
+(evil-define-motion evil-visual-exchange-corners ()
+ "Rearrange corners in Visual Block mode.
+
+ M---+ +---M
+ | | <=> | |
+ +---P P---+
+
+For example, if mark is in the upper left corner and point
+in the lower right, this function puts mark in the upper right
+corner and point in the lower left."
+ (cond
+ ((eq evil-visual-selection 'block)
+ (let* ((point (point))
+ (mark (or (mark t) point))
+ (point-col (evil-column point))
+ (mark-col (evil-column mark))
+ (mark (save-excursion
+ (goto-char mark)
+ (evil-move-to-column point-col)
+ (point)))
+ (point (save-excursion
+ (goto-char point)
+ (evil-move-to-column mark-col)
+ (point))))
+ (evil-visual-refresh mark point)))
+ (t
+ (evil-exchange-point-and-mark)
+ (evil-visual-refresh))))
+
+(evil-define-command evil-visual-rotate (corner &optional beg end type)
+ "Move point to CORNER of the Visual selection.
+Corner may be one of `upper-left', `upper-right', `lower-left' and
+`lower-right':
+
+ upper-left +---+ upper-right
+ | |
+ lower-left +---+ lower-right
+
+When called interactively, the selection is rotated clockwise."
+ :keep-visual t
+ (interactive
+ (let ((corners '(#1=upper-left upper-right lower-right lower-left #1#)))
+ (list (cadr (memq (evil-visual-block-corner) corners)))))
+ (let* ((beg (or beg (point)))
+ (end (or end (mark t) beg))
+ (type (or type evil-this-type))
+ range)
+ (cond
+ ((memq type '(rectangle block))
+ (setq range (evil-block-rotate beg end :corner corner)
+ beg (pop range)
+ end (pop range))
+ (unless (eq corner (evil-visual-block-corner corner beg end))
+ (evil-swap beg end))
+ (goto-char beg)
+ (when (evil-visual-state-p)
+ (evil-move-mark end)
+ (evil-visual-refresh nil nil nil :corner corner)))
+ ((memq corner '(upper-right lower-right))
+ (goto-char (max beg end))
+ (when (evil-visual-state-p)
+ (evil-move-mark (min beg end))))
+ (t
+ (goto-char (min beg end))
+ (when (evil-visual-state-p)
+ (evil-move-mark (max beg end)))))))
+
+;;; Insertion commands
+
+(defun evil-insert (count &optional vcount skip-empty-lines)
+ "Switch to Insert state just before point.
+The insertion will be repeated COUNT times on the next VCOUNT lines,
+starting at the same column.
+If SKIP-EMPTY-LINES is non-nil, the insertion will not be performed
+on lines on which the insertion point would be after the end of the
+lines. This is the default behaviour for Visual-state insertion."
+ (interactive
+ (if (not (evil-visual-state-p))
+ (list (prefix-numeric-value current-prefix-arg))
+ (evil-visual-rotate 'upper-left)
+ (list (prefix-numeric-value current-prefix-arg)
+ (when (memq (evil-visual-type) '(line block))
+ (1+ (evil-count-lines evil-visual-point evil-visual-mark)))
+ t)))
+ (and evil-want-fine-undo vcount (evil-start-undo-step))
+ (if (and (evil-visual-state-p) (eq (evil-visual-type) 'line))
+ (evil-insert-line count vcount)
+ (setq evil-insert-count count
+ evil-insert-lines nil
+ evil-insert-vcount (and vcount
+ (> vcount 1)
+ (list (line-number-at-pos)
+ (current-column)
+ vcount))
+ evil-insert-skip-empty-lines skip-empty-lines)
+ (evil-insert-state 1)))
+
+(defun evil-append (count &optional vcount skip-empty-lines)
+ "Switch to Insert state just after point.
+The insertion will be repeated COUNT times and repeated once for
+the next VCOUNT - 1 lines starting at the same column. If
+SKIP-EMPTY-LINES is non-nil, the insertion will not be performed
+on lines on which the insertion point would be after the end of
+the lines."
+ (interactive
+ (list (prefix-numeric-value current-prefix-arg)
+ (and (evil-visual-state-p)
+ (memq (evil-visual-type) '(line block))
+ (1+ (evil-count-lines evil-visual-point evil-visual-mark)))))
+ (if (and (called-interactively-p 'any)
+ (evil-visual-state-p))
+ (cond
+ ((or (eq (evil-visual-type) 'line)
+ (and (eq (evil-visual-type) 'block)
+ (memq last-command '(next-line previous-line))
+ (eq temporary-goal-column most-positive-fixnum)))
+ (evil-visual-rotate 'upper-left)
+ (evil-append-line count vcount))
+ ((eq (evil-visual-type) 'block)
+ (let ((column (max (evil-column evil-visual-beginning)
+ (evil-column evil-visual-end))))
+ (evil-visual-rotate 'upper-left)
+ (move-to-column column t)
+ (evil-insert count vcount skip-empty-lines)))
+ (t
+ (evil-visual-rotate 'lower-right)
+ (backward-char)
+ (evil-append count)))
+ (unless (eolp) (forward-char))
+ (evil-insert count vcount skip-empty-lines)
+ (add-hook 'post-command-hook #'evil-maybe-remove-spaces)))
+
+(evil-define-command evil-insert-resume (count)
+ "Switch to Insert state at previous insertion point.
+The insertion will be repeated COUNT times. If called from visual
+state, only place point at the previous insertion position but do not
+switch to insert state."
+ :keep-visual t
+ :type exclusive
+ :jump t
+ (interactive "p")
+ (evil-goto-mark ?^ t)
+ (unless (evil-visual-state-p)
+ (evil-insert count)))
+
+(defun evil-quoted-insert (count)
+ "Like `quoted-insert' but delete COUNT chars forward in replace state.
+Adds a \"^\" overlay as an input prompt."
+ (interactive "p")
+ (let* ((opoint (point))
+ chars-to-delete
+ (ov (if (not (evil-replace-state-p))
+ (make-overlay opoint opoint)
+ (setq chars-to-delete (min (- (line-end-position) opoint) count))
+ (evil-update-replace-alist opoint count chars-to-delete)
+ (make-overlay opoint (+ chars-to-delete opoint)))))
+ (unwind-protect
+ (progn
+ (overlay-put ov 'invisible t)
+ (overlay-put ov 'after-string #("^" 0 1 (face escape-glyph cursor 1)))
+ (let (overwrite-mode) ; Force `read-quoted-char'
+ (quoted-insert count))
+ (when chars-to-delete (delete-char chars-to-delete)))
+ (delete-overlay ov))))
+
+(evil-define-command evil-open-above (count)
+ "Insert a new line above point and switch to Insert state.
+The insertion will be repeated COUNT times."
+ :suppress-operator t
+ (interactive "p")
+ (unless (eq evil-want-fine-undo t)
+ (evil-start-undo-step))
+ (evil-insert-newline-above)
+ (setq evil-insert-count count
+ evil-insert-lines t
+ evil-insert-vcount nil)
+ (unwind-protect
+ (when evil-auto-indent
+ (indent-according-to-mode))
+ (evil-insert-state 1)))
+
+(evil-define-command evil-open-below (count)
+ "Insert a new line below point and switch to Insert state.
+The insertion will be repeated COUNT times."
+ :suppress-operator t
+ (interactive "p")
+ (unless (eq evil-want-fine-undo t)
+ (evil-start-undo-step))
+ (push (point) buffer-undo-list)
+ (evil-insert-newline-below)
+ (setq evil-insert-count count
+ evil-insert-lines t
+ evil-insert-vcount nil)
+ (unwind-protect
+ (when evil-auto-indent
+ (indent-according-to-mode))
+ (evil-insert-state 1)))
+
+(defun evil--insert-line (count vcount non-blank-p)
+ "Switch to insert state at the beginning of the current line.
+If NON-BLANK-P is non-nil, point is placed at the first non-blank character
+on the current line. If NON-BLANK-P is nil, point is placed at column 0,
+or the beginning of visual line. The insertion will be repeated COUNT times.
+If VCOUNT is non nil it should be number > 0. The insertion will be repeated
+in the next VCOUNT - 1 lines below the current one."
+ (push (point) buffer-undo-list)
+ (let ((move-fn (if non-blank-p #'evil-first-non-blank #'evil-beginning-of-line)))
+ (if (and visual-line-mode
+ evil-respect-visual-line-mode)
+ (goto-char
+ (max (save-excursion
+ (funcall move-fn)
+ (point))
+ (save-excursion
+ (beginning-of-visual-line)
+ (point))))
+ (funcall move-fn))
+ (setq evil-insert-count count
+ evil-insert-lines nil
+ evil-insert-vcount
+ (and vcount
+ (> vcount 1)
+ (list (line-number-at-pos)
+ move-fn
+ vcount))))
+ (evil-insert-state 1))
+
+(defun evil-insert-line (count &optional vcount)
+ "Switch to insert state at beginning of current line.
+Point is placed at the first non-blank character on the current
+line. The insertion will be repeated COUNT times. If VCOUNT is
+non nil it should be number > 0. The insertion will be repeated
+in the next VCOUNT - 1 lines below the current one."
+ (interactive "p")
+ (evil--insert-line count vcount t))
+
+(evil-define-command evil-insert-0-line (count &optional vcount)
+ "Switch to insert state at beginning of current line.
+Point is placed at column 0, or the beginning of the visual line.
+The insertion will be repeated COUNT times. If VCOUNT is
+non nil it should be number > 0. The insertion will be repeated
+in the next VCOUNT - 1 lines below the current one."
+ :keep-visual t
+ :type exclusive
+ (interactive "p")
+ (if (evil-visual-state-p)
+ (evil-beginning-of-line)
+ (evil--insert-line count vcount nil)))
+
+(defun evil-append-line (count &optional vcount)
+ "Switch to Insert state at the end of the current line.
+The insertion will be repeated COUNT times. If VCOUNT is non nil
+it should be number > 0. The insertion will be repeated in the
+next VCOUNT - 1 lines below the current one."
+ (interactive "p")
+ (if (and visual-line-mode
+ evil-respect-visual-line-mode)
+ (end-of-visual-line)
+ (evil-move-end-of-line))
+ (setq evil-insert-count count
+ evil-insert-lines nil
+ evil-insert-vcount
+ (and vcount
+ (> vcount 1)
+ (list (line-number-at-pos)
+ #'end-of-line
+ vcount)))
+ (evil-insert-state 1))
+
+(evil-define-command evil-insert-digraph (count)
+ "Insert COUNT digraphs."
+ :repeat change
+ (interactive "p")
+ (let ((opoint (point))
+ chars-to-delete insert-prompt)
+ (if (evil-replace-state-p)
+ (progn
+ (setq chars-to-delete (min (- (line-end-position) opoint) count)
+ insert-prompt (make-overlay opoint (+ chars-to-delete opoint)))
+ (evil-update-replace-alist opoint count chars-to-delete))
+ (setq insert-prompt (make-overlay opoint opoint)))
+ (insert-char (evil-read-digraph-char-with-overlay insert-prompt) count)
+ (when chars-to-delete (delete-char chars-to-delete))))
+
+(evil-define-command evil-ex-show-digraphs ()
+ "Show a list of all available digraphs."
+ :repeat nil
+ (eval-and-compile (require 'evil-digraphs))
+ (let ((columns 3))
+ (evil-with-view-list
+ :name "evil-digraphs"
+ :mode-name "Evil Digraphs"
+ :format
+ (cl-loop repeat columns vconcat [("Digraph" 8 nil) ("Sequence" 16 nil)])
+ :entries
+ (cl-loop
+ with xs = (append evil-digraphs-table-user evil-digraphs-table)
+ while xs collect
+ (cl-loop
+ repeat columns vconcat
+ (cl-destructuring-bind (chars . digraph) (or (pop xs) '(() . ?\ ))
+ (list (char-to-string digraph) (concat chars)))
+ into row finally return (list nil row))))))
+
+(defun evil--self-insert-string (string)
+ "Insert STRING as if typed interactively."
+ (let ((chars (append string nil)))
+ (dolist (char chars)
+ (let ((last-command-event char))
+ (self-insert-command 1)))))
+
+(defun evil-copy-from-above (arg)
+ "Copy characters from preceding non-blank line.
+The copied text is inserted before point.
+ARG is the number of lines to move backward.
+See also \\<evil-insert-state-map>\\[evil-copy-from-below]."
+ (interactive
+ (cond
+ ;; if a prefix argument was given, repeat it for subsequent calls
+ ((and (null current-prefix-arg)
+ (eq last-command #'evil-copy-from-above))
+ (setq current-prefix-arg last-prefix-arg)
+ (list (prefix-numeric-value current-prefix-arg)))
+ (t
+ (list (prefix-numeric-value current-prefix-arg)))))
+ (evil--self-insert-string (evil-copy-chars-from-line arg -1)))
+
+(defun evil-copy-from-below (arg)
+ "Copy characters from following non-blank line.
+The copied text is inserted before point.
+ARG is the number of lines to move forward.
+See also \\<evil-insert-state-map>\\[evil-copy-from-above]."
+ (interactive
+ (cond
+ ((and (null current-prefix-arg)
+ (eq last-command #'evil-copy-from-below))
+ (setq current-prefix-arg last-prefix-arg)
+ (list (prefix-numeric-value current-prefix-arg)))
+ (t
+ (list (prefix-numeric-value current-prefix-arg)))))
+ (evil--self-insert-string (evil-copy-chars-from-line arg 1)))
+
+;; adapted from `copy-from-above-command' in misc.el
+(defun evil-copy-chars-from-line (n num &optional col)
+ "Return N characters from line NUM, starting at column COL.
+NUM is relative to the current line and can be negative.
+COL defaults to the current column."
+ (interactive "p")
+ (let ((col (or col (current-column))) prefix)
+ (save-excursion
+ (forward-line num)
+ (when (looking-at "[[:space:]]*$")
+ (if (< num 0)
+ (skip-chars-backward " \t\n")
+ (skip-chars-forward " \t\n")))
+ (evil-move-beginning-of-line)
+ (move-to-column col)
+ ;; if the column winds up in middle of a tab,
+ ;; return the appropriate number of spaces
+ (when (< col (current-column))
+ (if (eq (preceding-char) ?\t)
+ (let ((len (min n (- (current-column) col))))
+ (setq prefix (make-string len ?\s)
+ n (- n len)))
+ ;; if in middle of a control char, return the whole char
+ (backward-char 1)))
+ (concat prefix
+ (buffer-substring (point)
+ (min (line-end-position)
+ (+ n (point))))))))
+
+(defun evil-enter-replace-state (count)
+ "Switch to Replace state at point.
+The insertion will be repeated COUNT times."
+ (interactive "p")
+ (setq evil-insert-count count)
+ (setq evil-insert-count count
+ evil-insert-lines nil
+ evil-insert-vcount nil)
+ (evil-replace-state 1))
+
+;; completion
+(evil-define-command evil-complete-next (&optional arg)
+ "Complete to the nearest following word.
+Search backward if a match isn't found.
+Calls `evil-complete-next-func'."
+ :repeat change
+ (interactive "P")
+ (if (minibufferp)
+ (funcall evil-complete-next-minibuffer-func)
+ (funcall evil-complete-next-func arg)))
+
+(evil-define-command evil-complete-previous (&optional arg)
+ "Complete to the nearest preceding word.
+Search forward if a match isn't found.
+Calls `evil-complete-previous-func'."
+ :repeat change
+ (interactive "P")
+ (if (minibufferp)
+ (funcall evil-complete-previous-minibuffer-func)
+ (funcall evil-complete-previous-func arg)))
+
+(evil-define-command evil-complete-next-line (&optional arg)
+ "Complete a whole line.
+Calls `evil-complete-next-line-func'."
+ :repeat change
+ (interactive "P")
+ (if (minibufferp)
+ (funcall evil-complete-next-minibuffer-func)
+ (funcall evil-complete-next-line-func arg)))
+
+(evil-define-command evil-complete-previous-line (&optional arg)
+ "Complete a whole line.
+Calls `evil-complete-previous-line-func'."
+ :repeat change
+ (interactive "P")
+ (if (minibufferp)
+ (funcall evil-complete-previous-minibuffer-func)
+ (funcall evil-complete-previous-line-func arg)))
+
+;;; Search
+
+(defun evil-repeat-search (flag)
+ "Called to record a search command.
+FLAG is either `pre' or `post' if the function is called before resp.
+after executing the command."
+ (cond
+ ((and (evil-operator-state-p) (eq flag 'pre))
+ (evil-repeat-record (this-command-keys))
+ (evil-clear-command-keys))
+ ((and (evil-operator-state-p) (eq flag 'post))
+ ;; The value of (this-command-keys) at this point should be the
+ ;; key-sequence that called the last command that finished the
+ ;; search, usually RET. Therefore this key-sequence will be
+ ;; recorded in the post-command of the operator. Alternatively we
+ ;; could do it here.
+ (evil-repeat-record (if evil-regexp-search
+ (car-safe regexp-search-ring)
+ (car-safe search-ring))))
+ (t (evil-repeat-motion flag))))
+
+(evil-define-motion evil-search-forward ()
+ (format "Search forward for user-entered text.
+Searches for regular expression if `evil-regexp-search' is t.%s"
+ (if (and (fboundp 'isearch-forward)
+ (documentation 'isearch-forward))
+ (format "\n\nBelow is the documentation string \
+for `isearch-forward',\nwhich lists available keys:\n\n%s"
+ (documentation 'isearch-forward)) ""))
+ :jump t
+ :type exclusive
+ :repeat evil-repeat-search
+ (evil-search-incrementally t evil-regexp-search))
+
+(evil-define-motion evil-search-backward ()
+ (format "Search backward for user-entered text.
+Searches for regular expression if `evil-regexp-search' is t.%s"
+ (if (and (fboundp 'isearch-forward)
+ (documentation 'isearch-forward))
+ (format "\n\nBelow is the documentation string \
+for `isearch-forward',\nwhich lists available keys:\n\n%s"
+ (documentation 'isearch-forward)) ""))
+ :jump t
+ :type exclusive
+ :repeat evil-repeat-search
+ (evil-search-incrementally nil evil-regexp-search))
+
+(evil-define-motion evil-search-next (count)
+ "Repeat the last search."
+ :jump t
+ :type exclusive
+ (let ((orig (point))
+ (search-string (if evil-regexp-search
+ (car-safe regexp-search-ring)
+ (car-safe search-ring))))
+ (goto-char
+ ;; Wrap in `save-excursion' so that multiple searches have no visual effect.
+ (save-excursion
+ (evil-search search-string isearch-forward evil-regexp-search)
+ (when (and (> (point) orig)
+ (save-excursion
+ (evil-adjust-cursor)
+ (= (point) orig)))
+ ;; Point won't move after first attempt and `evil-adjust-cursor' takes
+ ;; effect, so start again.
+ (evil-search search-string isearch-forward evil-regexp-search))
+ (point)))
+ (when (and count (> count 1))
+ (dotimes (_ (1- count))
+ (evil-search search-string isearch-forward evil-regexp-search)))))
+
+(evil-define-motion evil-search-previous (count)
+ "Repeat the last search in the opposite direction."
+ :jump t
+ :type exclusive
+ (dotimes (_ (or count 1))
+ (evil-search (if evil-regexp-search
+ (car-safe regexp-search-ring)
+ (car-safe search-ring))
+ (not isearch-forward) evil-regexp-search)))
+
+(evil-define-motion evil-search-word-backward (count &optional symbol)
+ "Search backward for symbol under point."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (dotimes (_ (or count 1))
+ (evil-search-word nil nil symbol)))
+
+(evil-define-motion evil-search-word-forward (count &optional symbol)
+ "Search forward for symbol under point."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (dotimes (_ (or count 1))
+ (evil-search-word t nil symbol)))
+
+(evil-define-motion evil-search-unbounded-word-backward (count &optional symbol)
+ "Search backward for symbol under point.
+The search is unbounded, i.e., the pattern is not wrapped in
+\\<...\\>."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (dotimes (_ (or count 1))
+ (evil-search-word nil t symbol)))
+
+(evil-define-motion evil-search-unbounded-word-forward (count &optional symbol)
+ "Search forward for symbol under point.
+The search is unbounded, i.e., the pattern is not wrapped in
+\\<...\\>."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (dotimes (_ (or count 1))
+ (evil-search-word t t symbol)))
+
+(defun evil-goto-definition-imenu (string _position)
+ "Find definition for STRING with imenu."
+ (require 'imenu nil t)
+ (let (ientry ipos)
+ (when (fboundp 'imenu--make-index-alist)
+ (ignore-errors (setq ientry (imenu--make-index-alist)))
+ (setq ientry (imenu--in-alist string ientry))
+ (setq ipos (cdr ientry))
+ (when (and (markerp ipos)
+ (eq (marker-buffer ipos) (current-buffer)))
+ (setq ipos (marker-position ipos))
+ (when (numberp ipos)
+ (evil-search (format "\\_<%s\\_>" (regexp-quote string)) t t ipos)
+ t)))))
+
+(defun evil-goto-definition-semantic (_string position)
+ "Find definition for POSITION with semantic."
+ (and (fboundp 'semantic-ia-fast-jump)
+ (ignore-errors (semantic-ia-fast-jump position))))
+
+(declare-function xref-backend-identifier-at-point "xref")
+
+(defun evil-goto-definition-xref (_string position)
+ "Find definition at POSITION with xref."
+ (when (fboundp 'xref-find-definitions)
+ (let ((identifier (save-excursion
+ (goto-char position)
+ (xref-backend-identifier-at-point (xref-find-backend)))))
+ (condition-case nil
+ (progn (xref-find-definitions identifier)
+ t)
+ (user-error nil)))))
+
+(defun evil-goto-definition-search (string _position)
+ "Find definition for STRING with evil-search."
+ (evil-search (format "\\_<%s\\_>" (regexp-quote string)) t t (point-min))
+ t)
+
+(evil-define-motion evil-goto-definition ()
+ "Go to definition or first occurrence of symbol under point.
+See also `evil-goto-definition-functions'."
+ :jump t
+ :type exclusive
+ (let* ((match (evil--find-thing t 'symbol))
+ (string (car match))
+ (position (cdr match)))
+ (if (null string)
+ (user-error "No symbol under cursor")
+ (setq isearch-forward t)
+ (run-hook-with-args-until-success 'evil-goto-definition-functions
+ string position))))
+
+;;; Folding
+(defun evil-fold-action (list action)
+ "Perform fold ACTION for each matching major or minor mode in LIST.
+
+ACTION will be performed for the first matching handler in LIST. For more
+information on its features and format, see the documentation for
+`evil-fold-list'.
+
+If no matching ACTION is found in LIST, an error will signaled.
+
+Handler errors will be demoted, so a problem in one handler will (hopefully)
+not interfere with another."
+ (if (null list)
+ (user-error
+ "Enable one of the following modes for folding to work: %s"
+ (mapconcat #'symbol-name (mapcar #'caar evil-fold-list) ", "))
+ (let* ((modes (caar list)))
+ (if (evil--mode-p modes)
+ (let* ((actions (cdar list))
+ (fn (plist-get actions action)))
+ (when fn
+ (with-demoted-errors "Error: %S" (funcall fn))))
+ (evil-fold-action (cdr list) action)))))
+
+(defun evil--mode-p (modes)
+ "Determine whether any symbol in MODES represents the current
+buffer's major mode or any of its minors."
+ (unless (eq modes '())
+ (let ((mode (car modes)))
+ (or (eq major-mode mode)
+ (and (boundp mode) (symbol-value mode))
+ (evil--mode-p (cdr modes))))))
+
+(evil-define-command evil-toggle-fold ()
+ "Open or close a fold under point.
+See also `evil-open-fold' and `evil-close-fold'."
+ (evil-fold-action evil-fold-list :toggle))
+
+(evil-define-command evil-open-folds ()
+ "Open all folds.
+See also `evil-close-folds'."
+ (evil-fold-action evil-fold-list :open-all))
+
+(evil-define-command evil-close-folds ()
+ "Close all folds.
+See also `evil-open-folds'."
+ (evil-fold-action evil-fold-list :close-all))
+
+(evil-define-command evil-open-fold ()
+ "Open fold at point.
+See also `evil-close-fold'."
+ (evil-fold-action evil-fold-list :open))
+
+(evil-define-command evil-open-fold-rec ()
+ "Open fold at point recursively.
+See also `evil-open-fold' and `evil-close-fold'."
+ (evil-fold-action evil-fold-list :open-rec))
+
+(evil-define-command evil-close-fold ()
+ "Close fold at point.
+See also `evil-open-fold'."
+ (evil-fold-action evil-fold-list :close))
+
+;;; Ex
+
+(evil-define-operator evil-write (beg end _type file-or-append &optional bang)
+ "Save the current buffer, from BEG to END, to FILE-OR-APPEND.
+If FILE-OR-APPEND is of the form \">> FILE\", append to FILE
+instead of overwriting. The current buffer's filename is not
+changed unless it has no associated file and no region is
+specified. If the file already exists and the BANG argument is
+non-nil, it is overwritten without confirmation."
+ :motion nil
+ :move-point nil
+ :type line
+ :repeat nil
+ (interactive "<R><fsh><!>")
+ (let* ((append-and-filename (evil-extract-append file-or-append))
+ (append (car append-and-filename))
+ (filename (cdr append-and-filename))
+ (bufname (buffer-file-name (buffer-base-buffer))))
+ (when (zerop (length filename))
+ (setq filename bufname))
+ (cond
+ ((zerop (length filename))
+ (user-error "Please specify a file name for the buffer"))
+ ;; execute command on region
+ ((eq (aref filename 0) ?!)
+ (shell-command-on-region beg end (substring filename 1)))
+ ;; with region or append, always save to file without resetting
+ ;; modified flag
+ ((or append (and beg end))
+ (write-region beg end filename append nil nil (not (or append bang))))
+ ;; no current file
+ ((null bufname)
+ (write-file filename (not bang)))
+ ;; save current buffer to its file
+ ((string= filename bufname)
+ (if (not bang) (save-buffer) (write-file filename)))
+ ;; save to another file
+ (t
+ (write-region nil nil filename
+ nil (not bufname) nil
+ (not bang))))))
+
+(evil-define-command evil-write-all (bang)
+ "Save all buffers visiting a file.
+If BANG is non nil then read-only buffers are saved, too,
+otherwise they are skipped. "
+ :repeat nil
+ :move-point nil
+ (interactive "<!>")
+ (if bang
+ (save-some-buffers t)
+ ;; save only buffer that are not read-only and
+ ;; that are visiting a file
+ (save-some-buffers t
+ #'(lambda ()
+ (and (not buffer-read-only)
+ (buffer-file-name))))))
+
+(evil-define-command evil-update ()
+ "Same as `evil-write', but only write when the buffer has been modified."
+ :motion nil
+ :move-point nil
+ :type line
+ :repeat nil
+ (when (buffer-modified-p)
+ (call-interactively #'evil-write)))
+
+(evil-define-command evil-save (filename &optional bang)
+ "Save the current buffer to FILENAME.
+Changes the file name of the current buffer to FILENAME. If no
+FILENAME is given, the current file name is used."
+ :repeat nil
+ :move-point nil
+ (interactive "<f><!>")
+ (when (zerop (length filename))
+ (setq filename (buffer-file-name (buffer-base-buffer))))
+ (write-file filename (not bang)))
+
+(evil-define-command evil-edit (file &optional bang)
+ "Open FILE.
+If no FILE is specified, reload the current buffer from disk."
+ :repeat nil
+ (interactive "<f><!>")
+ (if file
+ (find-file file)
+ (revert-buffer bang (or bang (not (buffer-modified-p))) t)
+ (read-only-mode -1)))
+
+(evil-define-command evil-view (file &optional bang)
+ "Open FILE but don't allow changes.
+If no FILE is specified, reload the current buffer from disk as read-only."
+ :repeat nil
+ (interactive "<f><!>")
+ (if file
+ (find-file-read-only file)
+ (revert-buffer bang (or bang (not (buffer-modified-p))) t)
+ (read-only-mode +1)))
+
+(evil-define-command evil-buffer-add (file)
+ "Add FILE to the buffer list, but don't visit it. "
+ :repeat nil
+ (interactive "<f>")
+ (if (or (not file) (string= "" file))
+ (user-error "No file specified")
+ (find-file-noselect file)))
+
+(evil-define-command evil-read (count file)
+ "Insert the contents of FILE below the current line or line COUNT."
+ :repeat nil
+ :move-point nil
+ (interactive "P<fsh>")
+ (when (and file (not (zerop (length file))))
+ (when count (goto-char (point-min)))
+ (when (or (not (zerop (forward-line (or count 1))))
+ (not (bolp)))
+ (insert "\n"))
+ (cond
+ ((/= (aref file 0) ?!)
+ (when (member file '("#" "%"))
+ (setq file (evil-ex-replace-special-filenames file)))
+ (let ((result (insert-file-contents file)))
+ (save-excursion
+ (forward-char (cadr result))
+ (unless (bolp) (insert "\n")))))
+ (t
+ (shell-command (evil-ex-replace-special-filenames (substring file 1)) t)
+ (goto-char (mark))
+ (unless (bolp) (insert "\n"))
+ (forward-line -1)))))
+
+(evil-define-command evil-show-files ()
+ "Show the file-list.
+The same as `buffer-menu', but shows only buffers visiting
+files."
+ :repeat nil
+ (buffer-menu 1))
+
+(evil-define-command evil-goto-error (count)
+ "Go to error number COUNT.
+If no COUNT is supplied, move to the current error.
+
+Acts like `first-error' other than when given no counts, goes
+to the current error instead of the first, like in Vim's :cc
+command."
+ :repeat nil
+ (interactive "<c>")
+ (if count
+ (first-error (if (eql 0 count) 1 count))
+ (next-error 0)))
+
+(evil-define-command evil-buffer (buffer)
+ "Switch to another buffer."
+ :repeat nil
+ (interactive "<b>")
+ (cond
+ ;; no buffer given, switch to "other" buffer
+ ((null buffer) (switch-to-buffer (other-buffer)))
+ ;; we are given the name of an existing buffer
+ ((get-buffer buffer) (switch-to-buffer buffer))
+ ;; try to complete the buffer
+ ((let ((all-buffers (internal-complete-buffer buffer nil t)))
+ (when (= (length all-buffers) 1)
+ (switch-to-buffer (car all-buffers)))))
+ (t
+ (when (y-or-n-p
+ (format "No buffer with name \"%s\" exists. Create new buffer? "
+ buffer))
+ (switch-to-buffer buffer)))))
+
+(evil-define-command evil-next-buffer (&optional count)
+ "Go to the COUNTth next buffer in the buffer list."
+ :repeat nil
+ (interactive "p")
+ (next-buffer count))
+
+(evil-define-command evil-prev-buffer (&optional count)
+ "Go to the COUNTth prev buffer in the buffer list."
+ :repeat nil
+ (interactive "p")
+ (previous-buffer count))
+
+(evil-define-command evil-delete-buffer (buffer &optional bang)
+ "Delete a buffer.
+All windows currently showing this buffer will be closed except
+for the last window in each frame."
+ (interactive "<b><!>")
+ (with-current-buffer (or buffer (current-buffer))
+ (when bang
+ (set-buffer-modified-p nil)
+ (dolist (process (process-list))
+ (when (eq (process-buffer process) (current-buffer))
+ (set-process-query-on-exit-flag process nil))))
+ ;; get all windows that show this buffer
+ (let ((wins (get-buffer-window-list (current-buffer) nil t)))
+ ;; if the buffer which was initiated by emacsclient,
+ ;; call `server-edit' from server.el to avoid
+ ;; "Buffer still has clients" message
+ (if (and (bound-and-true-p server-buffer-clients)
+ (fboundp 'server-edit))
+ (server-edit)
+ (kill-buffer nil))
+ ;; close all windows that showed this buffer
+ (dolist (w wins) (ignore-errors (delete-window w))))))
+
+(evil-define-command evil-quit (&optional force)
+ "Close the current window, current frame, current tab, Emacs.
+If the current frame belongs to some client the client connection
+is closed."
+ :repeat nil
+ (interactive "<!>")
+ (condition-case nil
+ (evil-window-delete)
+ (error
+ (if (and (bound-and-true-p server-buffer-clients)
+ (fboundp 'server-edit)
+ (fboundp 'server-buffer-done))
+ (if force
+ (server-buffer-done (current-buffer))
+ (server-edit))
+ (condition-case nil
+ (delete-frame)
+ (error
+ (condition-case nil
+ (tab-bar-close-tab)
+ (error
+ (if force
+ (kill-emacs)
+ (save-buffers-kill-emacs))))))))))
+
+(evil-define-command evil-quit-all (&optional bang)
+ "Exit Emacs, asking for saving."
+ :repeat nil
+ (interactive "<!>")
+ (if (null bang)
+ (save-buffers-kill-terminal)
+ (let ((proc (frame-parameter (selected-frame) 'client)))
+ (if proc
+ (with-no-warnings
+ (server-delete-client proc))
+ (dolist (process (process-list))
+ (set-process-query-on-exit-flag process nil))
+ (kill-emacs)))))
+
+(evil-define-command evil-quit-all-with-error-code (&optional err-code _force)
+ "Exit Emacs without saving, returning an non-zero error code.
+The FORCE argument is only there for compatibility and is ignored.
+This function fails with an error if Emacs is run in server mode."
+ :repeat nil
+ (interactive "<N><!>")
+ (if (bound-and-true-p server-buffer-clients)
+ (user-error "Cannot exit client process with error code")
+ (kill-emacs (or err-code 1))))
+
+(evil-define-command evil-save-and-quit ()
+ "Save all buffers and exit Emacs."
+ (save-buffers-kill-terminal t))
+
+(evil-define-command evil-save-and-close (file &optional bang)
+ "Save the current buffer and close the window."
+ :repeat nil
+ (interactive "<f><!>")
+ (evil-write nil nil nil file bang)
+ (evil-quit))
+
+(evil-define-command evil-save-modified-and-close (file &optional bang)
+ "Save the current buffer and close the window."
+ :repeat nil
+ (interactive "<f><!>")
+ (when (buffer-modified-p)
+ (evil-write nil nil nil file bang))
+ (evil-quit))
+
+(evil-define-operator evil-shell-command
+ (beg end _type command &optional previous)
+ "Execute a shell command.
+If BEG, END and TYPE is specified, COMMAND is executed on the region,
+which is replaced with the command's output. Otherwise, the
+output is displayed in its own buffer. If PREVIOUS is non-nil,
+the previous shell command is executed instead."
+ (interactive "<R><sh><!>")
+ (if (not evil-called-from-ex-p)
+ (let ((current-prefix-arg
+ (if (or current-prefix-arg (evil-visual-state-p))
+ current-prefix-arg
+ (goto-char (min beg end))
+ (count-lines beg end)))
+ (evil-ex-initial-input "!"))
+ (call-interactively #'evil-ex))
+ (if (zerop (length command))
+ (when previous (setq command evil-previous-shell-command))
+ (setq command (evil-ex-replace-special-filenames command)
+ evil-previous-shell-command command))
+ (cond
+ ((zerop (length command))
+ (user-error "No%s shell command" (if previous " previous" "")))
+ (evil-ex-range
+ (if (not evil-display-shell-error-in-message)
+ (shell-command-on-region beg end command nil t)
+ (let ((output-buffer (generate-new-buffer " *temp*"))
+ (error-buffer (generate-new-buffer " *temp*")))
+ (unwind-protect
+ (if (zerop (shell-command-on-region
+ beg end command
+ output-buffer nil error-buffer))
+ (progn
+ (delete-region beg end)
+ (insert-buffer-substring output-buffer)
+ (goto-char beg)
+ (evil-first-non-blank))
+ (display-message-or-buffer error-buffer))
+ (kill-buffer output-buffer)
+ (kill-buffer error-buffer)))))
+ (t (shell-command command)))))
+
+(evil-define-command evil-make (arg)
+ "Call a build command in the current directory.
+If ARG is nil this function calls `recompile', otherwise it calls
+`compile' passing ARG as build command."
+ (interactive "<sh>")
+ (if (and (fboundp 'recompile)
+ (not arg))
+ (recompile)
+ (compile arg)))
+
+;; TODO: escape special characters (currently only \n) ... perhaps
+;; there is some Emacs function doing this?
+(evil-define-command evil-show-registers (registers)
+ "Show the contents of REGISTERS, or all registers, if none supplied."
+ :repeat nil
+ (interactive "<a>")
+ (let* ((all-registers (evil-register-list))
+ (reg-chars (string-to-list registers))
+ (display-regs (if reg-chars
+ (cl-remove-if-not (lambda (r) (memq (car r) reg-chars))
+ all-registers)
+ all-registers)))
+ (evil-with-view-list
+ :name "evil-registers"
+ :mode-name "Evil Registers"
+ :format
+ [("Register" 10 nil)
+ ("Value" 1000 nil)]
+ :entries
+ (cl-loop for (key . val) in display-regs
+ collect `(nil [,(char-to-string key)
+ ,(cond ((stringp val)
+ (replace-regexp-in-string "\n" "^J" val))
+ ((vectorp val)
+ (key-description val))
+ (t ""))])))))
+
+(evil-define-command evil-show-marks (mrks)
+ "Show all marks.
+If MRKS is non-nil it should be a string and only registers
+corresponding to the characters of this string are shown."
+ :repeat nil
+ (interactive "<a>")
+ ;; To get markers and positions, we can't rely on 'global-mark-ring'
+ ;; provided by Emacs (although it will be much simpler and faster),
+ ;; because 'global-mark-ring' does not store mark characters, but
+ ;; only buffer name and position. Instead, 'evil-markers-alist' is
+ ;; used; this is list maintained by Evil for each buffer.
+ (let ((all-markers
+ ;; get global and local marks
+ (append (cl-remove-if (lambda (m)
+ (or (evil-global-marker-p (car m))
+ (not (markerp (cdr m)))))
+ evil-markers-alist)
+ (cl-remove-if (lambda (m)
+ (or (not (evil-global-marker-p (car m)))
+ (not (markerp (cdr m)))))
+ (default-value 'evil-markers-alist)))))
+ (when mrks
+ (setq mrks (string-to-list mrks))
+ (setq all-markers (cl-delete-if (lambda (m)
+ (not (member (car m) mrks)))
+ all-markers)))
+ ;; map marks to list of 4-tuples (char row col file)
+ (setq all-markers
+ (mapcar (lambda (m)
+ (with-current-buffer (marker-buffer (cdr m))
+ (save-excursion
+ (goto-char (cdr m))
+ (list (car m)
+ (line-number-at-pos (point))
+ (current-column)
+ (buffer-name)))))
+ all-markers))
+ (evil-with-view-list
+ :name "evil-marks"
+ :mode-name "Evil Marks"
+ :format [("Mark" 8 nil)
+ ("Line" 8 nil)
+ ("Column" 8 nil)
+ ("Buffer" 1000 nil)]
+ :entries (cl-loop for m in (sort all-markers (lambda (a b) (< (car a) (car b))))
+ collect `(nil [,(char-to-string (nth 0 m))
+ ,(number-to-string (nth 1 m))
+ ,(number-to-string (nth 2 m))
+ (,(nth 3 m))]))
+ :select-action #'evil--show-marks-select-action)))
+
+(defun evil--show-marks-select-action (entry)
+ (kill-buffer)
+ (switch-to-buffer (car (elt entry 3)))
+ (evil-goto-mark (string-to-char (elt entry 0))))
+
+(defun evil--parse-delmarks (to-be-parsed &optional parsed)
+ "Where TO-BE-PARSED can contain ranges in the form `x-y'.
+PARSED is a list of characters whose marks should be deleted.
+Like vim, on invalid input, preceeding valid input is still parsed."
+ (cl-destructuring-bind (&optional a b c &rest) to-be-parsed
+ (cond
+ ((null to-be-parsed) parsed)
+ ;; single mark...
+ ((and (not (eq ?- b)) (or (<= ?a a ?z) (<= ?A a ?Z) (<= ?0 a ?9)
+ (memq a '(?\" ?^ ?. ?\[ ?\] ?< ?>))))
+ (evil--parse-delmarks (cdr to-be-parsed) (cons a parsed)))
+ ;; range of marks...
+ ((and (eq ?- b) c (or (<= ?a a c ?z) (<= ?A a c ?Z) (<= ?0 a c ?9)))
+ (evil--parse-delmarks (nthcdr 3 to-be-parsed)
+ (append parsed (number-sequence a c))))
+ (t (progn (evil-echo "Invalid input: %s" (apply #'string (remove nil to-be-parsed)))
+ parsed)))))
+
+(evil-define-command evil-delete-marks (marks &optional force)
+ "MARKS is a string denoting all marks to be deleted. Mark names are
+either single characters or a range of characters in the form `x-y'.
+If FORCE is non-nil and MARKS is blank, all local marks except 0-9 are removed."
+ (interactive "<a><!>")
+ (let ((mark-chars (remove ?\s (append marks nil))))
+ (cond
+ ((and force mark-chars) (evil-echo "Invalid input"))
+ (mark-chars
+ (let* ((delmarks (evil--parse-delmarks mark-chars))
+ (delmarkp (lambda (m) (member (car m) delmarks))))
+ ;; delete all parsed marks...
+ (setq evil-markers-alist
+ (cl-remove-if delmarkp evil-markers-alist))
+ ;; ensure all parsed marks are deleted globally...
+ (set-default 'evil-markers-alist
+ (cl-remove-if delmarkp (default-value 'evil-markers-alist)))))
+ ;; delete local marks except 0-9...
+ (force (setq evil-markers-alist
+ (cl-remove-if-not (lambda (m) (<= ?0 (car m) ?9))
+ evil-markers-alist))))))
+
+(declare-function ffap-file-at-point "ffap")
+(defvar ffap-string-at-point-region)
+(evil-define-command evil-find-file-at-point-with-line ()
+ "Open the file at point and go to position if present.
+Supports positions in the following formats: \"path:line path(line)\",
+\"path:line:col\" and \"path(line,col)\"."
+ (require 'ffap)
+ (let ((fname (ffap-file-at-point)))
+ (unless fname
+ (user-error "File does not exist."))
+ (let* ((line-number-pattern ":\\([0-9]+\\)\\=" ) ; path:line format
+ (line-number-pattern-alt "\\=(\\([0-9]+\\))") ; path(line) format
+ (line-and-column-numbers-pattern ":\\([0-9]+\\):\\([0-9]+\\)\\=") ; path:line:col format
+ (line-and-column-numbers-pattern-alt "\\=(\\([0-9]+\\),\\([0-9]+\\))") ; file(line,col) format
+ (get-number (lambda (pattern match-number backward)
+ (save-excursion
+ (goto-char (cadr ffap-string-at-point-region))
+ (and (if backward
+ (re-search-backward pattern (line-beginning-position) t)
+ (re-search-forward pattern (line-end-position) t))
+ (string-to-number (match-string match-number))))))
+ (line-number (or (funcall get-number line-and-column-numbers-pattern 1 t)
+ (funcall get-number line-and-column-numbers-pattern-alt 1 nil)
+ (funcall get-number line-number-pattern 1 t)
+ (funcall get-number line-number-pattern-alt 1 nil)))
+ (column-number (or (funcall get-number line-and-column-numbers-pattern 2 t)
+ (funcall get-number line-and-column-numbers-pattern-alt 2 nil))))
+ (evil-echo "%s, %s"
+ (if line-number (format "line: %s" line-number) "no line")
+ (if column-number (format "column: %s" column-number) "no column"))
+ (find-file-at-point fname)
+ (when line-number
+ (goto-char (point-min))
+ (forward-line (1- line-number))
+ (when column-number
+ (move-to-column (1- column-number)))))))
+
+(evil-define-command evil-find-file-at-point-visual ()
+ "Find the filename selected by the visual region.
+Signal an error if the file does not exist."
+ (let ((region (buffer-substring (region-beginning) (region-end))))
+ (if (file-exists-p region)
+ (find-file-at-point region)
+ (user-error "Can't find file \"%s\" in path" region))))
+
+(evil-ex-define-argument-type state
+ "Define an argument type which can take state names."
+ :collection
+ (lambda (arg predicate flag)
+ (let ((completions (cons '(nil) evil-state-properties)))
+ (when arg
+ (cond
+ ((null flag)
+ (try-completion arg completions predicate))
+ ((eq flag t)
+ (all-completions arg completions predicate))
+ ((eq flag 'lambda)
+ (test-completion arg completions predicate))
+ ((eq (car-safe flag) 'boundaries)
+ (cons 'boundaries
+ (completion-boundaries arg
+ completions
+ predicate
+ (cdr flag)))))))))
+
+(evil-define-interactive-code "<state>"
+ "A valid evil state."
+ :ex-arg state
+ (list (and evil-called-from-ex-p evil-ex-argument
+ (intern-soft evil-ex-argument))))
+
+;; TODO: should we merge this command with `evil-set-initial-state'?
+(evil-define-command evil-ex-set-initial-state (state)
+ "Set the initial state for the current major mode to STATE.
+This is the state the buffer comes up in. See `evil-set-initial-state'."
+ :repeat nil
+ (interactive "<state>")
+ (if (not (or (assq state evil-state-properties)
+ (null state)))
+ (user-error "State %s cannot be set as initial Evil state" state)
+ (let ((current-initial-state (evil-initial-state major-mode)))
+ (unless (eq current-initial-state state)
+ ;; only if we selected a new mode
+ (when (y-or-n-p (format "Major-mode `%s' has initial mode `%s'. \
+Change to `%s'? "
+ major-mode
+ (or current-initial-state "DEFAULT")
+ (or state "DEFAULT")))
+ (evil-set-initial-state major-mode state)
+ (when (y-or-n-p "Save setting in customization file? ")
+ (dolist (s (list current-initial-state state))
+ (when s
+ (let ((var (intern (format "evil-%s-state-modes" s))))
+ (customize-save-variable var (symbol-value var)))))))))))
+
+(evil-define-command evil-force-normal-state ()
+ "Switch to normal state without recording current command."
+ :repeat abort
+ :suppress-operator t
+ (evil-normal-state))
+
+(evil-define-motion evil-ex-search-next (count)
+ "Go to the next occurrence."
+ :jump t
+ :type exclusive
+ (evil-ex-search count))
+
+(evil-define-motion evil-ex-search-previous (count)
+ "Go the the previous occurrence."
+ :jump t
+ :type exclusive
+ (let ((evil-ex-search-direction
+ (if (eq evil-ex-search-direction 'backward) 'forward 'backward)))
+ (evil-ex-search count)))
+
+(defun evil-repeat-ex-search (flag)
+ "Called to record a search command.
+FLAG is either `pre' or `post' if the function is called before resp.
+after executing the command."
+ (cond
+ ((and (evil-operator-state-p) (eq flag 'pre))
+ (evil-repeat-record (this-command-keys))
+ (evil-clear-command-keys))
+ ((and (evil-operator-state-p) (eq flag 'post))
+ (let ((search-separator (car (last evil-repeat-info))))
+ (evil-repeat-record (evil-ex-pattern-regex evil-ex-search-pattern))
+ (when evil-ex-search-offset
+ (evil-repeat-record (concat search-separator evil-ex-search-offset))))
+ ;; If it weren't for the fact that `exit-minibuffer' throws an `exit'
+ ;; tag, which bypasses the source of `this-command-keys', we'd be able
+ ;; to capture the key(s) in the post-command of the operator as usual.
+ ;; Fortunately however, `last-input-event' can see the key (by default, `return')
+ (when (zerop (length (this-command-keys)))
+ (evil-repeat-record (vector last-input-event))))
+ (t (evil-repeat-motion flag))))
+
+(evil-define-motion evil-ex-search-forward (count)
+ "Start a forward search."
+ :jump t
+ :type exclusive
+ :repeat evil-repeat-ex-search
+ (evil-ex-start-search 'forward count))
+
+(evil-define-motion evil-ex-search-backward (count)
+ "Start a backward search."
+ :jump t
+ :repeat evil-repeat-ex-search
+ (evil-ex-start-search 'backward count))
+
+(evil-define-motion evil-ex-search-word-forward (count &optional symbol)
+ "Search for the next occurrence of word under the cursor."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (evil-ex-start-word-search nil 'forward count symbol))
+
+(evil-define-motion evil-ex-search-word-backward (count &optional symbol)
+ "Search for the next occurrence of word under the cursor."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (evil-ex-start-word-search nil 'backward count symbol))
+
+(evil-define-motion evil-ex-search-unbounded-word-forward (count &optional symbol)
+ "Search for the next occurrence of word under the cursor."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (evil-ex-start-word-search t 'forward count symbol))
+
+(evil-define-motion evil-ex-search-unbounded-word-backward (count &optional symbol)
+ "Search for the next occurrence of word under the cursor."
+ :jump t
+ :type exclusive
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ evil-symbol-word-search))
+ (evil-ex-start-word-search t 'backward count symbol))
+
+(defun evil-revert-reveal (open-spots)
+ "Unconditionally close overlays in OPEN-SPOTS in current window.
+Modified version of `reveal-close-old-overlays' from
+reveal.el. OPEN-SPOTS is a local version of `reveal-open-spots'."
+ (dolist (spot open-spots)
+ (let ((window (car spot))
+ (ol (cdr spot)))
+ (unless (eq window (selected-window))
+ (error "evil-revert-reveal: slot with wrong window"))
+ (let* ((inv (overlay-get ol 'reveal-invisible))
+ (open (or (overlay-get ol 'reveal-toggle-invisible)
+ (get inv 'reveal-toggle-invisible)
+ (overlay-get ol 'isearch-open-invisible-temporary))))
+ (if (and (overlay-start ol) ; Check if still live
+ open)
+ (condition-case err
+ (funcall open ol t)
+ (error (message "!!Reveal-hide (funcall %s %s t): %s !!"
+ open ol err)))
+ (overlay-put ol 'invisible inv))
+ ;; Remove the overlay from the list of open spots.
+ (overlay-put ol 'reveal-invisible nil)))))
+
+(defun evil--ex-substitute-final-message (nreplaced flags)
+ "Display message according to replacements and flags.
+If FLAGS contains \"p\" or \"#\" and NREPLACED is more than 0, print
+the last line to the echo area. Otherwise, print the number of
+replacements made or found."
+ (let ((replaced-any (< 0 nreplaced)))
+ (cond
+ ((and replaced-any (memq ?p flags))
+ (evil-echo "%s" (buffer-substring (line-beginning-position)
+ (line-end-position))))
+ ((and replaced-any (memq ?# flags))
+ (evil-echo "%s %s" (propertize (number-to-string (line-number-at-pos))
+ 'face 'line-number-current-line)
+ (buffer-substring (line-beginning-position)
+ (line-end-position))))
+ (t (evil-echo "%s %d occurrence%s"
+ (if (memq ?n flags) "Found" "Replaced")
+ nreplaced
+ (if (/= nreplaced 1) "s" ""))))))
+
+(evil-define-operator evil-ex-substitute
+ (beg end pattern replacement flags)
+ "The Ex substitute command.
+\[BEG,END]substitute/PATTERN/REPLACEMENT/FLAGS"
+ :repeat nil
+ :jump t
+ :move-point nil
+ :motion evil-line
+ (interactive "<r><s/>")
+ (evil-ex-nohighlight)
+ (unless pattern (user-error "No pattern given"))
+ (setq replacement (or replacement "")
+ flags (append flags)
+ evil-ex-last-was-search nil
+ evil-ex-substitute-pattern pattern
+ evil-ex-substitute-replacement replacement
+ evil-ex-substitute-flags flags)
+ (let* ((inhibit-field-text-motion t)
+ (count-only (memq ?n flags))
+ (confirm (and (memq ?c flags) (not count-only)))
+ (case-fold-search (evil-ex-pattern-ignore-case pattern))
+ (case-replace case-fold-search)
+ (regex (evil-ex-pattern-regex pattern))
+ (nreplaced 0)
+ (orig-point (point-marker))
+ (last-point (point))
+ (whole-line (evil-ex-pattern-whole-line pattern))
+ (evil-ex-substitute-overlay (make-overlay (point) (point)))
+ (end-marker (move-marker (make-marker) end))
+ (use-reveal confirm)
+ match-data
+ reveal-open-spots
+ transient-mark-mode)
+ (unwind-protect
+ (catch 'exit-search
+ (isearch-update-ring (setq isearch-string regex) t)
+ (evil-ex-hl-change 'evil-ex-substitute pattern)
+ (overlay-put evil-ex-substitute-overlay 'face 'isearch)
+ (overlay-put evil-ex-substitute-overlay 'priority 1001)
+ (goto-char beg)
+ (while (re-search-forward regex end-marker t)
+ (unless (and query-replace-skip-read-only
+ (text-property-any (match-beginning 0) (match-end 0) 'read-only t))
+ (let* ((match-beg (match-beginning 0))
+ (match-end (match-end 0))
+ (zero-length-match (= match-beg match-end))
+ match-contains-newline)
+ (goto-char match-beg)
+ (when (and (= match-beg end-marker) (> end-marker beg) (bolp))
+ ;; This line is not included due to range being exclusive
+ (throw 'exit-search nil))
+ (setq match-data (match-data t match-data)
+ match-contains-newline (search-forward "\n" match-end t))
+ (goto-char match-end)
+ (if confirm
+ (let* ((next-replacement
+ (if (stringp replacement) replacement
+ (funcall (car replacement) (cdr replacement) nreplaced)))
+ (prompt
+ (format "Replace %s with %s (y/n/a/q/l/^E/^Y)? "
+ (match-string 0)
+ (match-substitute-replacement
+ next-replacement (not case-replace))))
+ (search-invisible t)
+ response)
+ (move-overlay evil-ex-substitute-overlay match-beg match-end)
+ ;; Simulate `reveal-mode'. `reveal-mode' uses
+ ;; `post-command-hook' but that won't work here.
+ (when use-reveal
+ (reveal-post-command))
+ (catch 'exit-read-char
+ (while (setq response (read-char prompt))
+ (when (member response '(?y ?a ?l))
+ (unless count-only
+ (set-match-data match-data)
+ (replace-match next-replacement (not case-replace)))
+ (cl-incf nreplaced)
+ (evil-ex-hl-set-region
+ 'evil-ex-substitute
+ (line-beginning-position 2)
+ (evil-ex-hl-get-max 'evil-ex-substitute)))
+ (cl-case response
+ ((?y ?n) (throw 'exit-read-char nil))
+ (?a (setq confirm nil)
+ (throw 'exit-read-char nil))
+ ((?q ?l ?\C-\[) (throw 'exit-search nil))
+ (?\C-e (evil-scroll-line-down 1))
+ (?\C-y (evil-scroll-line-up 1))))))
+ (unless count-only
+ (let ((next-replacement
+ (if (stringp replacement) replacement
+ (funcall (car replacement) (cdr replacement) nreplaced))))
+ (set-match-data match-data)
+ (replace-match next-replacement (not case-replace))))
+ (cl-incf nreplaced))
+ (setq last-point (point))
+ (cond ((>= (point) end-marker)
+ ;; Don't want to perform multiple replacements at the end
+ ;; of the search region.
+ (throw 'exit-search nil))
+ ((and (not whole-line)
+ (not match-contains-newline))
+ (forward-line)
+ ;; forward-line just moves to the end of the line on the
+ ;; last line of the buffer.
+ (when (>= (point) end-marker) (throw 'exit-search nil)))
+ ;; For zero-length matches check to see if point won't
+ ;; move next time. This is a problem when matching the
+ ;; regexp "$" because we can enter an infinite loop,
+ ;; repeatedly matching the same character
+ ((and zero-length-match
+ (let ((pnt (point)))
+ (save-excursion
+ (and (re-search-forward regex end-marker t)
+ (= pnt (point))))))
+ (when (eobp) (throw 'exit-search nil))
+ (forward-char)))))))
+ (evil-ex-delete-hl 'evil-ex-substitute)
+ (delete-overlay evil-ex-substitute-overlay)
+ (goto-char (if count-only orig-point last-point))
+ (move-marker orig-point nil)
+ (move-marker end-marker nil)
+
+ (when use-reveal
+ (evil-revert-reveal reveal-open-spots)))
+
+ (evil--ex-substitute-final-message nreplaced flags)
+
+ (if (and (= nreplaced 0) evil-ex-point)
+ (goto-char evil-ex-point)
+ (evil-first-non-blank))))
+
+(evil-define-operator evil-ex-repeat-substitute (beg end flags)
+ "Repeat last substitute command.
+This is the same as \":s//~/\"."
+ :repeat nil
+ :jump t
+ :move-point nil
+ :motion evil-line
+ (interactive "<r><a>")
+ (apply #'evil-ex-substitute beg end
+ (evil-ex-get-substitute-info (concat "//~/" flags))))
+
+(evil-define-operator evil-ex-repeat-substitute-with-flags (beg end flags)
+ "Repeat last substitute command with last flags.
+This is the same as \":s//~/&\"."
+ :repeat nil
+ :jump t
+ :move-point nil
+ :motion evil-line
+ (interactive "<r><a>")
+ (apply #'evil-ex-substitute beg end
+ (evil-ex-get-substitute-info (concat "//~/&" flags))))
+
+(evil-define-operator evil-ex-repeat-substitute-with-search (beg end flags)
+ "Repeat last substitute command with last search pattern.
+This is the same as \":s//~/r\"."
+ :repeat nil
+ :jump t
+ :move-point nil
+ :motion evil-line
+ (interactive "<r><a>")
+ (apply #'evil-ex-substitute beg end
+ (evil-ex-get-substitute-info (concat "//~/r" flags))))
+
+(evil-define-operator evil-ex-repeat-substitute-with-search-and-flags
+ (beg end flags)
+ "Repeat last substitute command with last search pattern and last flags.
+This is the same as \":s//~/&r\"."
+ :repeat nil
+ :jump t
+ :move-point nil
+ :motion evil-line
+ (interactive "<r><a>")
+ (apply #'evil-ex-substitute beg end
+ (evil-ex-get-substitute-info (concat "//~/&r" flags))))
+
+(evil-define-operator evil-ex-repeat-global-substitute ()
+ "Repeat last substitute command on the whole buffer.
+This is the same as \":%s//~/&\"."
+ :repeat nil
+ :jump t
+ :move-point nil
+ :motion evil-line
+ (interactive)
+ (apply #'evil-ex-substitute (point-min) (point-max)
+ (evil-ex-get-substitute-info (concat "//~/&"))))
+
+(declare-function hi-lock-read-face-name "hi-lock")
+(evil-define-command evil-ex-match (args &optional bang)
+ "Define a pattern to highlight in the current buffer.
+With no args, clear a highlight from the buffer
+With only an ! argument, clear all highlights from the buffer.
+With one arg, interpret as the pattern, and prompt for a face.
+With two args, interpret as :match {face} /{pattern}/.
+Unlike Vim, multiple highlights can be set at once, so there is no need for
+\":2match\" and \":3match\" Ex commands."
+ (interactive "<a><!>")
+ (unless args (setq args ""))
+ (string-match "\\` *\\([^ ]+\\)? *\\(.+\\)?\\'" args)
+ (let* ((face (match-string 1 args))
+ (search-string (match-string 2 args))
+ (raw-patterns (evil-delimited-arguments (or search-string face "")))
+ (raw-pattern (or (car raw-patterns) ""))
+ (case-fold-search ; ignore case if non-nil
+ (eq (evil-ex-regex-case raw-pattern evil-ex-search-case) 'insensitive))
+ search-upper-case ; bypass isearch-no-upper-case-p
+ (pattern-no-case (evil-ex-regex-without-case raw-pattern))
+ (pattern (if evil-ex-search-vim-style-regexp
+ (evil-transform-vim-style-regexp pattern-no-case)
+ pattern-no-case)))
+ (cond
+ ((or (not face) (string= "none" face))
+ (if bang
+ (hi-lock-unface-buffer t)
+ (call-interactively #'hi-lock-unface-buffer)))
+ ((/= 1 (length raw-patterns))
+ (user-error "Invalid pattern argument"))
+ ((not search-string)
+ (require 'hi-lock)
+ (hi-lock-face-buffer pattern (hi-lock-read-face-name)))
+ (t (hi-lock-face-buffer pattern face)))))
+
+(defun evil-keep-lines (pattern beg end)
+ "Stripped down version of `keep-lines'.
+Delete lines between BEG & END which don't match PATTERN."
+ (goto-char (min beg end))
+ (setq end
+ (progn
+ (save-excursion
+ (goto-char (max beg end))
+ (unless (or (bolp) (eobp))
+ (forward-line 0))
+ (point-marker))))
+ (save-excursion
+ (or (bolp) (forward-line 1))
+ (let ((start (point)))
+ (while (< (point) end)
+ ;; Start is first char not preserved by previous match.
+ (if (not (re-search-forward pattern end 'move))
+ (delete-region start end)
+ (let ((end (save-excursion (goto-char (match-beginning 0))
+ (forward-line 0)
+ (point))))
+ ;; Now end is first char preserved by the new match.
+ (if (< start end)
+ (delete-region start end))))
+
+ (setq start (save-excursion (forward-line 1) (point)))
+ ;; If the match was empty, avoid matching again at same place.
+ (and (< (point) end)
+ (= (match-beginning 0) (match-end 0))
+ (forward-char 1)))))
+ (set-marker end nil)
+ nil)
+
+(defun evil-flush-lines (pattern beg end)
+ "Stripped down version of `flush-lines'.
+Delete lines between BEG & END which match PATTERN."
+ (goto-char (min beg end))
+ (setq end (copy-marker (max beg end)))
+ (save-excursion
+ (while (and (< (point) end)
+ (re-search-forward pattern end t))
+ (delete-region (save-excursion (goto-char (match-beginning 0))
+ (forward-line 0)
+ (point))
+ (progn (forward-line 1) (point)))))
+ (set-marker end nil))
+
+(defun evil--ex-performant-global-delete (beg end pattern invert)
+ "Use fast functions for fast line deletion.
+Delete lines between BEG & END which match PATTERN.
+Use `evil-flush-lines' if INVERT is nil, or `evil-keep-lines' if not."
+ (goto-char end)
+ (re-search-backward pattern beg t)
+ (let ((end-marker (point-marker)))
+ (if invert
+ (evil-keep-lines pattern beg end)
+ (evil-flush-lines pattern beg end))
+ (goto-char end-marker)
+ (set-marker end-marker nil)))
+
+(evil-define-operator evil-ex-global
+ (beg end pattern command &optional invert)
+ "The Ex global command.
+\[BEG,END]global[!]/PATTERN/COMMAND"
+ :motion mark-whole-buffer
+ :move-point nil
+ (interactive "<r><g/><!>")
+ (unless pattern
+ (user-error "No pattern given"))
+ (unless command
+ (user-error "No command given"))
+ ;; TODO: `evil-ex-make-substitute-pattern' should be executed so
+ ;; :substitute can re-use :global's pattern depending on its `r'
+ ;; flag. This isn't supported currently but should be simple to add
+ (let* ((case-fold-search
+ (eq (evil-ex-regex-case pattern evil-ex-search-case) 'insensitive))
+ (pattern (evil-ex-regex-without-case pattern))
+ (command-form (evil-ex-parse command))
+ (ex-delete (eq 'evil-ex-delete (evil-ex-completed-binding (nth 2 command-form))))
+ (transient-mark-mode transient-mark-mode)
+ (deactivate-mark deactivate-mark)
+ markers)
+ (when (and pattern command)
+ (when evil-ex-search-vim-style-regexp
+ (setq pattern (evil-transform-vim-style-regexp pattern)))
+ (if (and ex-delete (not (nth 3 command-form)) (not (nth 1 command-form)))
+ (evil--ex-performant-global-delete beg end pattern invert)
+ (setq isearch-string pattern)
+ (isearch-update-ring pattern t)
+ (goto-char beg)
+ (evil-move-beginning-of-line)
+ (while (< (point) end)
+ (let ((match (re-search-forward pattern (line-end-position) t)))
+ (when (if invert (not match) match)
+ (push (move-marker (make-marker)
+ (or (and match (match-beginning 0))
+ (line-beginning-position)))
+ markers)))
+ (forward-line))
+ (setq markers (nreverse markers))
+ (unwind-protect
+ (evil-with-single-undo
+ (let ((evil--ex-global-active-p t))
+ (dolist (marker markers)
+ (goto-char marker)
+ (eval command-form t))))
+ ;; ensure that all markers are deleted afterwards,
+ ;; even in the event of failure
+ (dolist (marker markers)
+ (set-marker marker nil))
+ (run-hooks 'evil-after-global-hook))))))
+
+(evil-define-operator evil-ex-global-inverted
+ (beg end pattern command &optional invert)
+ "The Ex vglobal command.
+\[BEG,END]vglobal/PATTERN/COMMAND"
+ :motion mark-whole-buffer
+ :move-point nil
+ (interactive "<r><g/><!>")
+ (evil-ex-global beg end pattern command (not invert)))
+
+(evil-define-operator evil-ex-normal (beg end commands)
+ "The Ex normal command.
+Execute the argument as normal command on each line in the
+range. The given argument is passed straight to
+`execute-kbd-macro'. The default is the current line."
+ :motion evil-line
+ (interactive "<r><a>")
+ ;; replace ^[ by escape
+ (setq commands
+ (vconcat (mapcar (lambda (ch) (if (eq ch ?) 'escape ch))
+ commands)))
+ (let (markers evil-called-from-ex-p prefix-arg current-prefix-arg)
+ (goto-char beg)
+ (beginning-of-line)
+ (while (when (< (point) end)
+ (push (point-marker) markers)
+ (and (= (forward-line) 0) (bolp))))
+ (setq markers (nreverse markers))
+ (deactivate-mark)
+ (evil-force-normal-state)
+ (evil-with-single-undo
+ (dolist (marker markers)
+ (goto-char marker)
+ (ignore-errors (execute-kbd-macro commands))
+ (evil-force-normal-state)
+ (set-marker marker nil)))))
+
+(evil-define-motion evil-goto-char (position)
+ "Go to POSITION in the buffer.
+Default position is the beginning of the buffer."
+ :jump t
+ (interactive "<N>")
+ (goto-char (or position (point-min))))
+
+(evil-define-operator evil-ex-line-number (beg end)
+ "Print the last line number."
+ :motion mark-whole-buffer
+ :move-point nil
+ (interactive "<r>")
+ (evil-echo "%d" (count-lines (point-min) end)))
+
+(evil-define-command evil-show-file-info ()
+ "Show basic file information."
+ (let* ((nlines (count-lines (point-min) (point-max)))
+ (curr (line-number-at-pos (point)))
+ (perc (if (> nlines 0)
+ (format "%d%%" (* (/ (float curr) (float nlines)) 100.0))
+ "No lines in buffer"))
+ (file (buffer-file-name (buffer-base-buffer)))
+ (writable (and file (file-writable-p file)))
+ (readonly (if (and file (not writable)) "[readonly] " "")))
+ (if file
+ (evil-echo "\"%s\" %d %slines --%s--" file nlines readonly perc)
+ (evil-echo "%d lines --%s--" nlines perc))))
+
+(defvar sort-fold-case)
+(evil-define-operator evil-ex-sort (beg end &optional args reverse)
+ "The Ex sort command.
+\[BEG,END]sort[!] [/PATTERN/] [b][i][u][r][n][x][o]
+The following additional options are supported:
+
+ * i ignore case
+ * u remove duplicate lines
+ * r sort the contents of pattern
+ * n sort by the first decimal number
+ * x sort by the first hexadecimal number (with optional \"0x\" prefix)
+ * o sort by the first octal number
+ * b sort by the first binary number
+
+If a pattern is supplied without supplying the \"r\" option, sort
+the contents of the lines after skipping the pattern.
+If the pattern is empty, the last search pattern is used instead.
+
+The \"!\" argument means to sort in reverse order."
+ :motion mark-whole-buffer
+ :move-point nil
+ (interactive "<r><a><!>")
+ (unless args (setq args ""))
+ (let ((inhibit-field-text-motion t)
+ options sort-fold-case unique base sort-pat pat)
+ ;; Handle arguments like
+ ;; /[^,]*,/ n
+ ;; and
+ ;; nu
+ (if (or (zerop (length args)) (memq (aref args 0) '(?i ?n ?x ?o ?b ?u ?r)))
+ (setq options args)
+ (setq args (evil-delimited-arguments args 2)
+ ;; Use last search pattern when an empty pattern is provided
+ pat (if (string= (car args) "")
+ (evil-ex-pattern-regex evil-ex-search-pattern)
+ (car args))
+ options (cadr args)))
+ (cl-loop
+ for opt across options do
+ (cond
+ ((eq opt ?i) (setq sort-fold-case t))
+ ((eq opt ?b) (setq base 2))
+ ((eq opt ?o) (setq base 8))
+ ((eq opt ?n) (setq base 10))
+ ((eq opt ?x) (setq base 16))
+ ((eq opt ?r) (setq sort-pat t))
+ ((eq opt ?u) (setq unique t))
+ ((eq opt ? ))
+ (t (user-error "Invalid sort option `%c'" opt))))
+ (evil-with-restriction beg end
+ (goto-char beg)
+ (let ((num-re
+ (cond
+ ((null base) nil)
+ ((= base 2) "[01]+")
+ ((= base 8) "[0-7]+")
+ ((= base 10) "-?[0-9]+")
+ ((= base 16) "\\(-\\)?\\(?:0x\\)?\\([0-9a-f]+\\)")))
+ key-end)
+ (sort-subr
+ reverse
+ #'forward-line
+ #'end-of-line
+ (lambda ()
+ ;; Find the boundary of the key to match on the line
+ (setq key-end (line-end-position))
+ (and (> (length pat) 0)
+ ;; When matching a pattern and one doesn't exist on the line,
+ ;; skip the line
+ (re-search-forward pat key-end 'move)
+ sort-pat ; Otherwise go to the start of the key
+ (progn (setq key-end (point))
+ (goto-char (match-beginning 0))))
+ ;; Return the key for the line when sorting numbers, otherwise let
+ ;; `sort-subr' extract the key
+ (when base
+ (let ((case-fold-search t))
+ (if (not (re-search-forward num-re key-end t))
+ ;; When sorting numbers and a number doesn't exist on the
+ ;; line, place it above all the numeric lines
+ most-negative-fixnum
+ (let ((num (string-to-number
+ (buffer-substring
+ (match-beginning (if (= base 16) 2 0))
+ (match-end 0))
+ base)))
+ (if (and (= base 16) (match-beginning 1))
+ (- num)
+ num))))))
+ ;; Only called when sorting lexicographically
+ (lambda () (goto-char key-end))))
+ (when unique
+ (goto-char (point-min))
+ (let ((case-fold-search sort-fold-case)
+ prev-line-beg)
+ (while (not (eobp))
+ (if (and prev-line-beg
+ (eq 0 (compare-buffer-substrings
+ nil prev-line-beg (1- (point))
+ nil (point) (line-end-position))))
+ (delete-region (point) (line-beginning-position 2))
+ (setq prev-line-beg (point))
+ (forward-line)))))))
+ (goto-char beg))
+
+;;; Window navigation
+
+(defvar evil--window-digit nil)
+
+(defun evil--window-keep-pred ()
+ (eq 'evil-window-digit-argument this-command))
+
+(defun evil--window-reset-digit ()
+ (setq evil--window-digit nil)
+ (remove-hook 'post-command-hook #'evil--window-reset-digit))
+
+(defun evil--window-on-exit ()
+ (add-hook 'post-command-hook #'evil--window-reset-digit))
+
+(defun evil-window-digit-argument ()
+ "Like `digit-argument' but maintains the window map."
+ (interactive)
+ (unless (eq 'evil-window-digit-argument last-command)
+ (set-transient-map evil-window-map #'evil--window-keep-pred #'evil--window-on-exit))
+ (let* ((char (if (integerp last-command-event)
+ last-command-event
+ (get last-command-event 'ascii-character)))
+ (digit (- (logand char ?\177) ?0)))
+ (setq evil--window-digit (+ (* 10 (or evil--window-digit 0)) digit))))
+
+(defmacro evil-save-side-windows (&rest body)
+ "Toggle side windows, evaluate BODY, restore side windows."
+ (declare (indent defun) (debug (&rest form)))
+ (let ((sides (make-symbol "sidesvar")))
+ `(let ((,sides (and (fboundp 'window-toggle-side-windows)
+ (window-with-parameter 'window-side))))
+ ;; The compiler doesn't understand that all uses are protected
+ ;; by `fboundp' :-(
+ (declare-function window-toggle-side-windows "window")
+ (when ,sides
+ (window-toggle-side-windows))
+ (unwind-protect
+ (progn ,@body)
+ (when ,sides
+ (window-toggle-side-windows))))))
+
+(defun evil-resize-window (new-size &optional horizontal)
+ "Set the current window's width or height to NEW-SIZE.
+If HORIZONTAL is non-nil the width of the window is changed,
+otherwise its height is changed."
+ (let ((count (- new-size (if horizontal (window-width) (window-height)))))
+ (enlarge-window count horizontal)))
+
+(defun evil-move-window (side)
+ "Move the `selected-window' to SIDE.
+The state of the `selected-window' is saved along with the state
+of the window tree consisting of all the other windows. Then, all
+windows are deleted, the remaining window is split according to
+SIDE, the state of the window at SIDE is replaced with the saved
+state of the `selected-window', and, finally, the state of the
+saved window tree is reconstructed on the opposite side.
+
+SIDE has the same meaning as in `split-window'.
+
+Note, this function only operates on the window tree rooted in
+the frame's main window and effectively preserves any side
+windows (i.e. windows with a valid window-side window
+parameter)."
+ (evil-save-side-windows
+ (unless (one-window-p)
+ (save-excursion
+ (let ((w (window-state-get (selected-window))))
+ (delete-window)
+ (let ((wtree (window-state-get)))
+ (delete-other-windows)
+ (let ((subwin (selected-window))
+ ;; NOTE: SIDE is new in Emacs 24
+ (newwin (split-window nil nil side)))
+ (window-state-put wtree subwin)
+ (window-state-put w newwin)
+ (select-window newwin)))))
+ (balance-windows))))
+
+(defun evil-alternate-buffer (&optional window)
+ "Return the last buffer WINDOW has displayed other than the current one.
+This is equivalent to Vim's alternate buffer."
+ ;; If the last buffer visited has been killed, then `window-prev-buffers'
+ ;; returns a list with `window-buffer' at the head.
+ (let* ((prev-buffers (window-prev-buffers))
+ (head (car prev-buffers)))
+ (if (eq (car head) (window-buffer window))
+ (cadr prev-buffers)
+ head)))
+
+(evil-define-command evil-switch-to-windows-last-buffer ()
+ "Switch to the last open buffer of the current window."
+ :repeat nil
+ (let ((previous-place (evil-alternate-buffer)))
+ (when previous-place
+ (switch-to-buffer (car previous-place)))))
+
+(evil-define-command evil-window-delete ()
+ "Delete the current window or tab.
+If `evil-auto-balance-windows' is non-nil then all children of
+the deleted window's parent window are rebalanced."
+ (let ((p (window-parent)))
+ ;; If tabs are enabled and this is the only visible window, then attempt to
+ ;; close this tab.
+ (if (and (bound-and-true-p tab-bar-mode)
+ (null p))
+ (tab-close)
+ (delete-window)
+ (when evil-auto-balance-windows
+ ;; balance-windows raises an error if the parent does not have
+ ;; any further children (then rebalancing is not necessary anyway)
+ (ignore-errors (balance-windows p))))))
+
+(evil-define-command evil-window-split (&optional count file read-only)
+ "Split the current window horizontally, COUNT lines height,
+editing a certain FILE. The new window will be created below
+when `evil-split-window-below' is non-nil. If COUNT and
+`evil-auto-balance-windows' are both non-nil then all children
+of the parent of the splitted window are rebalanced."
+ :repeat nil
+ (interactive "<wc><f>")
+ (select-window
+ (split-window (selected-window) (when count (- count))
+ (if evil-split-window-below 'below 'above)))
+ (when (and (not count) evil-auto-balance-windows)
+ (balance-windows (window-parent)))
+ (when file
+ (funcall (if read-only #'evil-view #'evil-edit) file)))
+
+(evil-define-command evil-window-split-view (&optional count file)
+ "As with `evil-window-split' but the file is opened read-only."
+ :repeat nil
+ (interactive "<c><f>")
+ (evil-window-split count file t))
+
+(evil-define-command evil-window-vsplit (&optional count file)
+ "Split the current window vertically, COUNT columns width,
+editing a certain FILE. The new window will be created to the
+right when `evil-vsplit-window-right' is non-nil. If COUNT and
+`evil-auto-balance-windows'are both non-nil then all children
+of the parent of the splitted window are rebalanced."
+ :repeat nil
+ (interactive "<wc><f>")
+ (select-window
+ (split-window (selected-window) (when count (- count))
+ (if evil-vsplit-window-right 'right 'left)))
+ (when (and (not count) evil-auto-balance-windows)
+ (balance-windows (window-parent)))
+ (when file
+ (evil-edit file)))
+
+(evil-define-command evil-split-buffer (buffer)
+ "Split window and switch to another buffer."
+ :repeat nil
+ (interactive "<b>")
+ (evil-window-split)
+ (evil-buffer buffer))
+
+(evil-define-command evil-split-next-buffer (&optional count)
+ "Split the window and go to the COUNT-th next buffer in the buffer list."
+ :repeat nil
+ (interactive "p")
+ (evil-window-split)
+ (next-buffer count))
+
+(evil-define-command evil-split-prev-buffer (&optional count)
+ "Split window and go to the COUNT-th prev buffer in the buffer list."
+ :repeat nil
+ (interactive "p")
+ (evil-window-split)
+ (previous-buffer count))
+
+(evil-define-command evil-window-left (count)
+ "Move the cursor to new COUNT-th window left of the current one."
+ :repeat nil
+ (interactive "<w>")
+ (dotimes (_ count)
+ (windmove-left)))
+
+(evil-define-command evil-window-right (count)
+ "Move the cursor to new COUNT-th window right of the current one."
+ :repeat nil
+ (interactive "<w>")
+ (dotimes (_ count)
+ (windmove-right)))
+
+(evil-define-command evil-window-up (count)
+ "Move the cursor to new COUNT-th window above the current one."
+ :repeat nil
+ (interactive "<w>")
+ (dotimes (_ (or count 1))
+ (windmove-up)))
+
+(evil-define-command evil-window-down (count)
+ "Move the cursor to new COUNT-th window below the current one."
+ :repeat nil
+ (interactive "<w>")
+ (dotimes (_ (or count 1))
+ (windmove-down)))
+
+(evil-define-command evil-window-bottom-right ()
+ "Move the cursor to bottom-right window."
+ :repeat nil
+ (let ((last-sibling (frame-root-window)))
+ (while (and last-sibling (not (window-live-p last-sibling)))
+ (setq last-sibling (window-last-child last-sibling)))
+ (when last-sibling
+ (select-window last-sibling))))
+
+(evil-define-command evil-window-top-left ()
+ "Move the cursor to top-left window."
+ :repeat nil
+ (let ((first-child (window-child (frame-root-window))))
+ (while (and first-child (not (window-live-p first-child)))
+ (setq first-child (window-child first-child)))
+ (when first-child
+ (select-window
+ first-child))))
+
+(evil-define-command evil-window-mru ()
+ "Move the cursor to the previous (last accessed) buffer in another window.
+More precisely, it selects the most recently used buffer that is
+shown in some other window, preferably of the current frame, and
+is different from the current one."
+ :repeat nil
+ (catch 'done
+ (dolist (buf (buffer-list (selected-frame)))
+ (let ((win (get-buffer-window buf)))
+ (when (and (not (eq buf (current-buffer)))
+ win
+ (not (eq win (selected-window))))
+ (select-window win)
+ (throw 'done nil))))))
+
+(evil-define-command evil-window-next (count)
+ "Move the cursor to the next window in the cyclic order.
+With COUNT go to the count-th window in the order starting from
+top-left."
+ :repeat nil
+ (interactive "<wc>")
+ (if (not count)
+ (other-window +1)
+ (evil-window-top-left)
+ (other-window (1- (min count (length (window-list)))))))
+
+(evil-define-command evil-window-prev (count)
+ "Move the cursor to the previous window in the cyclic order.
+With COUNT go to the count-th window in the order starting from
+top-left."
+ :repeat nil
+ (interactive "<wc>")
+ (if (not count)
+ (other-window -1)
+ (evil-window-top-left)
+ (other-window (1- (min count (length (window-list)))))))
+
+(evil-define-command evil-window-new (count file)
+ "Split the current window horizontally
+and open a new buffer or edit a certain FILE."
+ :repeat nil
+ (interactive "<wc><f>")
+ (let ((new-window (split-window (selected-window) (when count (- count))
+ (if evil-split-window-below 'below 'above))))
+ (when (and (not count) evil-auto-balance-windows)
+ (balance-windows (window-parent)))
+ (select-window new-window)
+ (evil-buffer-new file)))
+
+(evil-define-command evil-window-vnew (count file)
+ "Split the current window vertically
+and open a new buffer name or edit a certain FILE."
+ :repeat nil
+ (interactive "<wc><f>")
+ (let ((new-window (split-window (selected-window) (when count (- count))
+ (if evil-vsplit-window-right 'right 'left))))
+ (when (and (not count) evil-auto-balance-windows)
+ (balance-windows (window-parent)))
+ (select-window new-window)
+ (evil-buffer-new file)))
+
+(evil-define-command evil-buffer-new (&optional file)
+ "Edit a new unnamed buffer or FILE."
+ :repeat nil
+ (interactive "<f>")
+ (if file
+ (evil-edit file)
+ (let ((buffer (generate-new-buffer "*new*")))
+ (set-buffer-major-mode buffer)
+ (set-window-buffer nil buffer))))
+
+(evil-define-command evil-window-increase-height (count)
+ "Increase current window height by COUNT."
+ :repeat nil
+ (interactive "<w>")
+ (enlarge-window count))
+
+(evil-define-command evil-window-decrease-height (count)
+ "Decrease current window height by COUNT."
+ :repeat nil
+ (interactive "<w>")
+ (enlarge-window (- count)))
+
+(evil-define-command evil-window-increase-width (count)
+ "Increase current window width by COUNT."
+ :repeat nil
+ (interactive "<w>")
+ (enlarge-window count t))
+
+(evil-define-command evil-window-decrease-width (count)
+ "Decrease current window width by COUNT."
+ :repeat nil
+ (interactive "<w>")
+ (enlarge-window (- count) t))
+
+(evil-define-command evil-window-set-height (count)
+ "Set the height of the current window to COUNT."
+ :repeat nil
+ (interactive "<wc>")
+ (evil-resize-window (or count (frame-height)) nil))
+
+(evil-define-command evil-window-set-width (count)
+ "Set the width of the current window to COUNT."
+ :repeat nil
+ (interactive "<wc>")
+ (evil-resize-window (or count (frame-width)) t))
+
+(evil-define-command evil-ex-resize (arg)
+ "The ex :resize command.
+
+If ARG is a signed positive integer, increase the current window
+height by ARG.
+
+If ARG is a signed negative integer, decrease the current window
+height by ARG.
+
+If ARG is a positive integer without explicit sign, set the current
+window height to ARG.
+
+If ARG is empty, maximize the current window height."
+ (interactive "<a>")
+ (if (or (not arg) (= 0 (length arg)))
+ (evil-window-set-height nil)
+ (let ((n (string-to-number arg)))
+ (if (> n 0)
+ (if (= ?+ (aref arg 0))
+ (evil-window-increase-height n)
+ (evil-window-set-height n))
+ (evil-window-decrease-height (- n))))))
+
+(evil-define-command evil-window-rotate-upwards ()
+ "Rotate the windows according to the current cyclic ordering."
+ :repeat nil
+ (evil-save-side-windows
+ (let ((wlist (window-list))
+ (slist (mapcar #'window-state-get (window-list))))
+ (setq slist (append (cdr slist) (list (car slist))))
+ (while (and wlist slist)
+ (window-state-put (car slist) (car wlist))
+ (setq wlist (cdr wlist)
+ slist (cdr slist)))
+ (select-window (car (window-list))))))
+
+(evil-define-command evil-window-rotate-downwards ()
+ "Rotate the windows according to the current cyclic ordering."
+ :repeat nil
+ (evil-save-side-windows
+ (let ((wlist (window-list))
+ (slist (mapcar #'window-state-get (window-list))))
+ (setq slist (append (last slist) slist))
+ (while (and wlist slist)
+ (window-state-put (car slist) (car wlist))
+ (setq wlist (cdr wlist)
+ slist (cdr slist)))
+ (select-window (car (window-list))))))
+
+(evil-define-command evil-window-exchange (&optional count)
+ "Exchange the current window with the next, or the COUNT-th, one."
+ :repeat nil
+ (interactive "<wc>")
+ (let ((original-window (selected-window)))
+ (evil-window-next count)
+ (if (fboundp 'window-swap-states)
+ (window-swap-states nil original-window t)
+ (let* ((other-window (selected-window))
+ (original-state (window-state-get original-window))
+ (other-state (window-state-get other-window)))
+ (window-state-put other-state original-window t)
+ (window-state-put original-state other-window t)))))
+
+(evil-define-command evil-window-move-very-top ()
+ "Close the current window, split the upper-left one horizontally
+and redisplay the current buffer there."
+ :repeat nil
+ (evil-move-window 'above))
+
+(evil-define-command evil-window-move-far-left ()
+ "Close the current window, split the upper-left one vertically
+and redisplay the current buffer there."
+ :repeat nil
+ (evil-move-window 'left))
+
+(evil-define-command evil-window-move-far-right ()
+ "Close the current window, split the lower-right one vertically
+and redisplay the current buffer there."
+ :repeat nil
+ (evil-move-window 'right))
+
+(evil-define-command evil-window-move-very-bottom ()
+ "Close the current window, split the lower-right one horizontally
+and redisplay the current buffer there."
+ :repeat nil
+ (evil-move-window 'below))
+
+;;; Tab commands
+
+(evil-define-command evil-tab-next (arg)
+ "Switch to the next tab.
+If ARG is non-nil, parse ARG as an index and go to the tab at that
+index."
+ :repeat nil
+ (interactive "<c>")
+ (if arg
+ (tab-bar-select-tab arg)
+ (tab-bar-switch-to-next-tab)))
+
+;;; Mouse handling
+
+;; Large parts of this code are taken from mouse.el which is
+;; distributed with GNU Emacs
+(defun evil-mouse-drag-region (start-event)
+ "Set the region to the text that the mouse is dragged over.
+Highlight the drag area as you move the mouse.
+This must be bound to a button-down mouse event.
+
+If the click is in the echo area, display the `*Messages*' buffer.
+
+START-EVENT should be the event that started the drag."
+ (interactive "e")
+ ;; Give temporary modes such as isearch a chance to turn off.
+ (run-hooks 'mouse-leave-buffer-hook)
+ (evil-mouse-drag-track start-event t))
+(evil-set-command-property 'evil-mouse-drag-region :keep-visual t)
+
+;; Make sure `touch-screen-handle-touch' processes touch screen gestures by
+;; ignoring `evil-mouse-drag-region' (bound to `down-mouse-1') during mouse
+;; click emulation.
+(put 'evil-mouse-drag-region 'ignored-mouse-command t)
+
+(defun evil-mouse-drag-track (start-event &optional
+ do-mouse-drag-region-post-process)
+ "Track mouse drags by highlighting area between point and cursor.
+The region will be defined with mark and point.
+DO-MOUSE-DRAG-REGION-POST-PROCESS should only be used by
+`mouse-drag-region'."
+ (mouse-minibuffer-check start-event)
+ (setq mouse-selection-click-count-buffer (current-buffer))
+ (deactivate-mark)
+ (let* ((scroll-margin 0) ; Avoid margin scrolling (Bug#9541).
+ (original-window (selected-window))
+ ;; We've recorded what we needed from the current buffer and
+ ;; window, now let's jump to the place of the event, where things
+ ;; are happening.
+ (_ (mouse-set-point start-event))
+ (echo-keystrokes 0)
+ (start-posn (event-start start-event))
+ (start-point (posn-point start-posn))
+ (start-window (posn-window start-posn))
+ (start-window-start (window-start start-window))
+ (start-hscroll (window-hscroll start-window))
+ (bounds (window-edges start-window))
+ (make-cursor-line-fully-visible nil)
+ (top (nth 1 bounds))
+ (bottom (if (or (window-minibuffer-p start-window)
+ (not mode-line-format))
+ (nth 3 bounds)
+ ;; Don't count the mode line.
+ (1- (nth 3 bounds))))
+ (on-link (and mouse-1-click-follows-link
+ (or mouse-1-click-in-non-selected-windows
+ (eq start-window original-window))
+ ;; Use start-point before the intangibility
+ ;; treatment, in case we click on a link inside an
+ ;; intangible text.
+ (mouse-on-link-p start-posn)))
+ (click-count (1- (event-click-count start-event)))
+ (remap-double-click (and on-link
+ (eq mouse-1-click-follows-link 'double)
+ (= click-count 1)))
+ ;; Suppress automatic hscrolling, because that is a nuisance
+ ;; when setting point near the right fringe (but see below).
+ (auto-hscroll-mode-saved auto-hscroll-mode)
+ (auto-hscroll-mode nil)
+ event end end-point)
+
+ (setq mouse-selection-click-count click-count)
+ ;; In case the down click is in the middle of some intangible text,
+ ;; use the end of that text, and put it in START-POINT.
+ (if (< (point) start-point)
+ (goto-char start-point))
+ (setq start-point (point))
+ (if remap-double-click
+ (setq click-count 0))
+
+ (setq click-count (mod click-count 4))
+
+ ;; activate correct visual state
+ (let ((range (evil-mouse-start-end start-point start-point click-count)))
+ (set-mark (nth 0 range))
+ (goto-char (nth 1 range)))
+
+ (cond
+ ((= click-count 0)
+ (when (evil-visual-state-p) (evil-exit-visual-state)))
+ ((= click-count 1)
+ (evil-visual-char)
+ (evil-visual-post-command))
+ ((= click-count 2)
+ (evil-visual-line)
+ (evil-visual-post-command))
+ ((= click-count 3)
+ (evil-visual-block)
+ (evil-visual-post-command)))
+
+ ;; Track the mouse until we get a non-movement event.
+ (track-mouse
+ (while (progn
+ (setq event (read-key))
+ (or (mouse-movement-p event)
+ (memq (car-safe event) '(switch-frame select-window))))
+ (unless (evil-visual-state-p)
+ (cond
+ ((= click-count 0) (evil-visual-char))
+ ((= click-count 1) (evil-visual-char))
+ ((= click-count 2) (evil-visual-line))
+ ((= click-count 3) (evil-visual-block))))
+
+ (evil-visual-pre-command)
+ (unless (memq (car-safe event) '(switch-frame select-window))
+ ;; Automatic hscrolling did not occur during the call to
+ ;; `read-event'; but if the user subsequently drags the
+ ;; mouse, go ahead and hscroll.
+ (let ((auto-hscroll-mode auto-hscroll-mode-saved))
+ (redisplay))
+ (setq end (event-end event)
+ end-point (posn-point end))
+ (if (and (eq (posn-window end) start-window)
+ (integer-or-marker-p end-point))
+ (evil-mouse--drag-set-mark-and-point start-point
+ end-point click-count)
+ (let ((mouse-row (cdr (cdr (mouse-position)))))
+ (cond
+ ((null mouse-row))
+ ((< mouse-row top)
+ (mouse-scroll-subr start-window (- mouse-row top)
+ nil start-point))
+ ((>= mouse-row bottom)
+ (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
+ nil start-point))))))
+ (evil-visual-post-command)))
+
+ ;; Store the fact that the current region was set by the mouse
+ (setq evil--region-from-mouse t)
+
+ ;; Handle the terminating event if possible.
+ (when (consp event)
+ ;; Ensure that point is on the end of the last event.
+ (when (and (setq end-point (posn-point (event-end event)))
+ (eq (posn-window end) start-window)
+ (integer-or-marker-p end-point)
+ (/= start-point end-point))
+ (evil-mouse--drag-set-mark-and-point start-point
+ end-point click-count))
+
+ ;; Find its binding.
+ (let* ((fun (key-binding (vector (car event))))
+ (do-multi-click (and (> (event-click-count event) 0)
+ (functionp fun)
+ (not (memq fun '(mouse-set-point
+ mouse-set-region))))))
+ (if (and (or (/= (mark) (point))
+ (= click-count 1) ; word selection
+ (and (memq (evil-visual-type) '(line block))))
+ (not do-multi-click))
+
+ ;; If point has moved, finish the drag.
+ (let (last-command this-command)
+ (and mouse-drag-copy-region
+ do-mouse-drag-region-post-process
+ (let (deactivate-mark)
+ (evil-visual-expand-region)
+ (copy-region-as-kill (mark) (point))
+ (evil-visual-contract-region))))
+
+ ;; If point hasn't moved, run the binding of the
+ ;; terminating up-event.
+ (if do-multi-click
+ (goto-char start-point)
+ (deactivate-mark))
+ (when (and (functionp fun)
+ (= start-hscroll (window-hscroll start-window))
+ ;; Don't run the up-event handler if the window
+ ;; start changed in a redisplay after the
+ ;; mouse-set-point for the down-mouse event at
+ ;; the beginning of this function. When the
+ ;; window start has changed, the up-mouse event
+ ;; contains a different position due to the new
+ ;; window contents, and point is set again.
+ (or end-point
+ (= (window-start start-window)
+ start-window-start)))
+ (when (and on-link
+ (= start-point (point))
+ (evil-mouse--remap-link-click-p start-event event))
+ ;; If we rebind to mouse-2, reselect previous selected
+ ;; window, so that the mouse-2 event runs in the same
+ ;; situation as if user had clicked it directly. Fixes
+ ;; the bug reported by juri@jurta.org on 2005-12-27.
+ (if (or (vectorp on-link) (stringp on-link))
+ (setq event (aref on-link 0))
+ (select-window original-window)
+ (setcar event 'mouse-2)
+ ;; If this mouse click has never been done by the
+ ;; user, it doesn't have the necessary property to be
+ ;; interpreted correctly.
+ (put 'mouse-2 'event-kind 'mouse-click)))
+ (push event unread-command-events)))))))
+
+;; This function is a plain copy of `mouse--drag-set-mark-and-point',
+;; which is only available in Emacs 24
+(defun evil-mouse--drag-set-mark-and-point (start click click-count)
+ (let* ((range (evil-mouse-start-end start click click-count))
+ (beg (nth 0 range))
+ (end (nth 1 range)))
+ (cond ((eq (mark) beg)
+ (goto-char end))
+ ((eq (mark) end)
+ (goto-char beg))
+ ((< click (mark))
+ (set-mark end)
+ (goto-char beg))
+ (t
+ (set-mark beg)
+ (goto-char end)))))
+
+;; This function is a plain copy of `mouse--remap-link-click-p',
+;; which is only available in Emacs 23
+(defun evil-mouse--remap-link-click-p (start-event end-event)
+ (or (and (eq mouse-1-click-follows-link 'double)
+ (= (event-click-count start-event) 2))
+ (and
+ (not (eq mouse-1-click-follows-link 'double))
+ (= (event-click-count start-event) 1)
+ (= (event-click-count end-event) 1)
+ (or (not (integerp mouse-1-click-follows-link))
+ (let ((t0 (posn-timestamp (event-start start-event)))
+ (t1 (posn-timestamp (event-end end-event))))
+ (and (integerp t0) (integerp t1)
+ (if (> mouse-1-click-follows-link 0)
+ (<= (- t1 t0) mouse-1-click-follows-link)
+ (< (- t0 t1) mouse-1-click-follows-link))))))))
+
+(defun evil-mouse-start-end (start end mode)
+ "Return a list of region bounds based on START and END according to MODE.
+If MODE is not 1 then set point to (min START END), mark to (max
+START END). If MODE is 1 then set point to start of word at (min
+START END), mark to end of word at (max START END)."
+ (evil-sort start end)
+ (setq mode (mod mode 4))
+ (if (/= mode 1) (list start end)
+ (list
+ (save-excursion
+ (goto-char (min (point-max) (1+ start)))
+ (if (zerop (forward-thing evil-mouse-word -1))
+ (let ((bpnt (point)))
+ (forward-thing evil-mouse-word +1)
+ (if (> (point) start) bpnt (point)))
+ (point-min)))
+ (save-excursion
+ (goto-char end)
+ (1-
+ (if (zerop (forward-thing evil-mouse-word +1))
+ (let ((epnt (point)))
+ (forward-thing evil-mouse-word -1)
+ (if (<= (point) end) epnt (point)))
+ (point-max)))))))
+
+;;; State switching
+
+(evil-define-command evil-exit-emacs-state (&optional buffer message)
+ "Exit Emacs state.
+Changes the state to the previous state, or to Normal state
+if the previous state was Emacs state."
+ :keep-visual t
+ :suppress-operator t
+ (interactive '(nil t))
+ (with-current-buffer (or buffer (current-buffer))
+ (when (evil-emacs-state-p)
+ (evil-change-to-previous-state buffer message)
+ (when (evil-emacs-state-p)
+ (evil-normal-state (and message 1))))))
+
+(defun evil--restore-repeat-hooks ()
+ "No insert-state repeat info is recorded after executing in normal state.
+Restore the disabled repeat hooks on insert-state exit."
+ (evil-repeat-stop)
+ (add-hook 'pre-command-hook #'evil-repeat-pre-hook)
+ (add-hook 'post-command-hook #'evil-repeat-post-hook)
+ (remove-hook 'evil-insert-state-exit-hook #'evil--restore-repeat-hooks))
+
+(defvar evil--execute-normal-return-state nil
+ "The state to return to after executing in normal state.")
+
+(evil-define-local-var evil--execute-normal-eol-pos nil
+ "Point position if it was at EOL before `evil-execute-in-normal-state'.")
+
+(defun evil-execute-in-normal-state ()
+ "Execute the next command in Normal state."
+ (interactive)
+ (let ((buf (current-buffer))
+ (state evil-state))
+ (evil-with-delay (not (memq this-command
+ '(nil
+ evil-execute-in-normal-state
+ evil-replace-state
+ evil-use-register
+ evil-window-digit-argument
+ digit-argument
+ negative-argument
+ universal-argument
+ universal-argument-minus
+ universal-argument-more
+ universal-argument-other-key)))
+ post-command-hook
+ (with-current-buffer buf
+ ;; If cursor was after EOL before CTRL-O and is now at EOL,
+ ;; put it after EOL.
+ (and (or (when evil--execute-normal-eol-pos
+ (= (1+ (point)) (save-excursion
+ (goto-char evil--execute-normal-eol-pos)
+ (set-marker evil--execute-normal-eol-pos nil)
+ (line-end-position))))
+ (and (eq (or goal-column temporary-goal-column) most-positive-fixnum)
+ (memq this-command '(next-line previous-line))))
+ (not (eolp))
+ (not (memq this-command
+ '(evil-insert evil-beginning-of-line evil-first-non-blank)))
+ (forward-char))
+ (unless (memq evil-state '(replace insert))
+ (evil-change-state state))
+ (when (eq 'insert evil-state)
+ (remove-hook 'pre-command-hook #'evil-repeat-pre-hook)
+ (remove-hook 'post-command-hook #'evil-repeat-post-hook)
+ (add-hook 'evil-insert-state-exit-hook #'evil--restore-repeat-hooks))
+ (setq evil-execute-normal-keys nil))))
+ (setq evil-insert-count nil
+ evil--execute-normal-return-state evil-state
+ evil--execute-normal-eol-pos (when (eolp) (point-marker))
+ evil-execute-normal-keys (this-command-keys))
+ (let (evil-move-cursor-back) (evil-normal-state))
+ (evil-echo "Switched to Normal state for the next command..."))
+
+(defun evil-stop-execute-in-emacs-state ()
+ (when (and (not (eq this-command #'evil-execute-in-emacs-state))
+ (not (minibufferp)))
+ (remove-hook 'post-command-hook #'evil-stop-execute-in-emacs-state)
+ (when (buffer-live-p evil-execute-in-emacs-state-buffer)
+ (with-current-buffer evil-execute-in-emacs-state-buffer
+ (if (and (eq evil-previous-state 'visual)
+ (not (use-region-p)))
+ (progn
+ (evil-change-to-previous-state)
+ (evil-exit-visual-state))
+ (evil-change-to-previous-state))))
+ (setq evil-execute-in-emacs-state-buffer nil)))
+
+(evil-define-command evil-execute-in-emacs-state ()
+ "Execute the next command in Emacs state."
+ (add-hook 'post-command-hook #'evil-stop-execute-in-emacs-state t)
+ (setq evil-execute-in-emacs-state-buffer (current-buffer))
+ (cond
+ ((evil-visual-state-p)
+ (let ((mrk (mark))
+ (pnt (point)))
+ (evil-emacs-state)
+ (set-mark mrk)
+ (goto-char pnt)))
+ (t
+ (evil-emacs-state)))
+ (evil-echo "Switched to Emacs state for the next command ..."))
+
+(defun evil-exit-visual-and-repeat (event)
+ "Exit insert state and repeat event.
+This special command should be used if some command called from
+visual state should actually be called in normal-state. The main
+reason for doing this is that the repeat system should *not*
+record the visual state information for some command. This
+command should be bound to exactly the same event in visual state
+as the original command is bound in normal state. EVENT is the
+event that triggered the execution of this command."
+ (interactive "e")
+ (when (evil-visual-state-p)
+ (evil-exit-visual-state)
+ (push event unread-command-events)))
+(evil-declare-ignore-repeat 'evil-exit-visual-and-repeat)
+
+(evil-define-command evil-retab (tabstop)
+ "Convert all tabs to spaces or the other way around.
+Replace all sequences of white-space containing a <Tab> with new
+strings of white-space using the new TABSTOP value given.
+If you do not specify a new TABSTOP size or it is zero, Evil uses the
+current value of `tab-width'."
+ (interactive "<a>")
+ (unless (or (not tabstop) (string-match-p "^[0-9]*$" tabstop))
+ (user-error "Invalid argument: %s" tabstop))
+ (let ((beg (if (use-region-p) (region-beginning) (point-min)))
+ (end (if (use-region-p) (region-end) (point-max)))
+ (retab (if indent-tabs-mode #'tabify #'untabify))
+ (tab-width (cond ((not tabstop) tab-width)
+ ((equal tabstop "0") tab-width)
+ (t (string-to-number tabstop)))))
+ (funcall retab beg end)))
+
+(provide 'evil-commands)
+
+;;; evil-commands.el ends here
diff --git a/.config/emacs/lisp/evil/evil-common.el b/.config/emacs/lisp/evil/evil-common.el
new file mode 100644
index 0000000..4aa1416
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-common.el
@@ -0,0 +1,3843 @@
+;;; evil-common.el --- Common functions and utilities -*- lexical-binding: t -*-
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'evil-vars)
+(require 'rect)
+(require 'thingatpt)
+(require 'cl-lib)
+
+(declare-function evil-visual-state-p "evil-states")
+(declare-function evil-visual-restore "evil-states")
+(declare-function evil-motion-state "evil-states")
+(declare-function evil-replace-state-p "evil-states")
+(declare-function evil-set-jump "evil-jumps")
+
+;;; Compatibility with different Emacs versions
+
+;; x-set-selection and x-get-selection have been deprecated since 25.1
+;; by gui-set-selection and gui-get-selection
+(defalias 'evil-get-selection
+ (if (fboundp 'gui-get-selection) 'gui-get-selection 'x-get-selection))
+(defalias 'evil-set-selection
+ (if (fboundp 'gui-set-selection) 'gui-set-selection 'x-set-selection))
+
+(defmacro evil-with-delay (condition hook &rest body)
+ "Execute BODY when CONDITION becomes true, checking with HOOK.
+HOOK can be a simple symbol or of the form (HOOK APPEND LOCAL NAME)
+where:
+NAME specifies the name of the entry added to HOOK.
+If APPEND is non-nil, the entry is appended to the hook.
+If LOCAL is non-nil, the buffer-local value of HOOK is modified."
+ (declare (debug (form sexp body)) (indent 2))
+ (cl-destructuring-bind (hook-sym &optional append local name)
+ (mapcar #'macroexp-quote (if (consp hook) hook (list hook)))
+ (macroexp-let2* nil
+ ((fun-name `(make-symbol
+ ,(or name (format "evil-delay-in-%s" hook-sym))))
+ ;; `apply-partially' is used in case this macro is expanded
+ ;; (via `evil-define-key') in a file which still does not
+ ;; activate `lexical-binding'.
+ (fun `(apply-partially
+ (lambda (name &rest _)
+ (when ,(or condition t)
+ (remove-hook ,hook-sym name ,local)
+ ,@body
+ t))
+ ,fun-name)))
+ `(unless ,(and condition `(funcall ,fun))
+ (progn (fset ,fun-name ,fun)
+ ,@(when local `((put ,fun-name 'permanent-local-hook t)))
+ (add-hook ,hook-sym ,fun-name ,append ,local))))))
+
+(defun evil-delay (condition form hook &optional append local name)
+ "Execute FORM when CONDITION becomes true, checking with HOOK.
+NAME specifies the name of the entry added to HOOK. If APPEND is
+non-nil, the entry is appended to the hook. If LOCAL is non-nil,
+the buffer-local value of HOOK is modified."
+ (declare (obsolete evil-with-delay "1.15.0") (indent 2))
+ (eval `(evil-with-delay ,condition (,hook ,append ,local ,name) ,form) t))
+
+;;; List functions
+
+(defmacro evil--add-to-alist (alist &rest elements)
+ "Add the association of KEY and VAL to the value of ALIST.
+If the list already contains an entry for KEY, update that entry;
+otherwise prepend it to the list.
+
+\(fn ALIST [KEY VAL]...)"
+ `(progn
+ ,@(cl-loop
+ for (key val) on elements by #'cddr collect
+ (if (< emacs-major-version 26)
+ (macroexp-let2* nil ((k key) (p `(assoc ,k ,alist)))
+ `(if ,p (setcdr ,p ,val)
+ (push (cons ,k ,val) ,alist)))
+ `(setf (alist-get ,key ,alist nil nil #'equal) ,val)))
+ ,alist))
+
+;; custom version of `delete-if'
+(defun evil-filter-list (predicate list &optional pointer)
+ "Delete by side-effect all items satisfying PREDICATE in LIST.
+Stop when reaching POINTER. If the first item satisfies PREDICATE,
+there is no way to remove it by side-effect; therefore, write
+\(setq foo (evil-filter-list #\\='predicate foo)) to be sure of
+changing the value of `foo'."
+ (let ((tail list) elt head)
+ (while (and tail (not (eq tail pointer)))
+ (setq elt (car tail))
+ (cond
+ ((funcall predicate elt)
+ (setq tail (cdr tail))
+ (if head
+ (setcdr head tail)
+ (setq list tail)))
+ (t
+ (setq head tail
+ tail (cdr tail)))))
+ list))
+
+(defun evil-member-if (predicate list &optional pointer)
+ "Find the first item satisfying PREDICATE in LIST.
+Stop when reaching POINTER, which should point at a link
+in the list."
+ (let (elt)
+ (catch 'done
+ (while (and (consp list) (not (eq list pointer)))
+ (setq elt (car list))
+ (if (funcall predicate elt)
+ (throw 'done elt)
+ (setq list (cdr list)))))))
+
+(defun evil-member-recursive-if (predicate tree)
+ "Find the first item satisfying PREDICATE in TREE."
+ (declare (obsolete nil "1.15.0"))
+ (cond
+ ((funcall predicate tree)
+ tree)
+ ((listp tree)
+ (catch 'done
+ (dolist (elt tree)
+ (when (setq elt (evil-member-recursive-if predicate elt))
+ (throw 'done elt)))))))
+
+(defun evil-concat-lists (&rest sequences)
+ "Concatenate lists, removing duplicates.
+Elements are compared with `eq'."
+ (let (result)
+ (dolist (sequence sequences)
+ (dolist (elt sequence)
+ (push elt result)))
+ (nreverse (cl-remove-duplicates result :test #'eq))))
+
+(defun evil-concat-alists (&rest sequences)
+ "Concatenate association lists, removing duplicates.
+An alist is a list of cons cells (KEY . VALUE) where each key
+may occur only once. Later values overwrite earlier values."
+ (let (result)
+ (dolist (sequence sequences)
+ (dolist (elt sequence)
+ (setq result (assq-delete-all (car-safe elt) result))
+ (push elt result)))
+ (nreverse result)))
+
+(defun evil-concat-plists (&rest sequences)
+ "Concatenate property lists, removing duplicates.
+A property list is a list (:KEYWORD1 VALUE1 :KEYWORD2 VALUE2...)
+where each keyword may occur only once. Later values overwrite
+earlier values."
+ (let (result)
+ (dolist (sequence sequences result)
+ (while sequence
+ (setq result
+ (plist-put result (pop sequence) (pop sequence)))))))
+
+(defun evil-concat-keymap-alists (&rest sequences)
+ "Concatenate keymap association lists, removing duplicates.
+A keymap alist is a list of cons cells (VAR . MAP) where each keymap
+may occur only once, but where the variables may be repeated
+\(e.g., (VAR . MAP1) (VAR . MAP2) is allowed). The order matters,
+with the highest priority keymaps being listed first."
+ (let (result)
+ (dolist (sequence sequences)
+ (dolist (elt sequence)
+ (unless (rassq (cdr-safe elt) result)
+ (push elt result))))
+ (nreverse result)))
+
+(defun evil-plist-delete (prop plist)
+ "Delete by side effect the property PROP from PLIST.
+If PROP is the first property in PLIST, there is no way
+to remove it by side-effect; therefore, write
+\(setq foo (evil-plist-delete :prop foo)) to be sure of
+changing the value of `foo'."
+ (let ((tail plist) elt head)
+ (while tail
+ (setq elt (car tail))
+ (cond
+ ((eq elt prop)
+ (setq tail (cdr (cdr tail)))
+ (if head
+ (setcdr (cdr head) tail)
+ (setq plist tail)))
+ (t
+ (setq head tail
+ tail (cdr (cdr tail))))))
+ plist))
+
+(defun evil-get-property (alist key &optional prop)
+ "Return property PROP for KEY in ALIST.
+ALIST is an association list with entries of the form
+\(KEY . PLIST), where PLIST is a property list.
+If PROP is nil, return all properties for KEY.
+If KEY is t, return an association list of keys
+and their PROP values."
+ (declare (obsolete nil "1.15.0"))
+ (cond
+ ((null prop)
+ (cdr (assq key alist)))
+ ((eq key t)
+ (let (result val)
+ (dolist (entry alist result)
+ (setq key (car entry)
+ val (cdr entry))
+ (when (plist-member val prop)
+ (setq val (plist-get val prop))
+ (push (cons key val) result)))))
+ (t
+ (plist-get (cdr (assq key alist)) prop))))
+
+(defun evil-put-property (alist-var key prop val &rest properties)
+ "Set PROP to VAL for KEY in ALIST-VAR.
+ALIST-VAR points to an association list with entries of the form
+\(KEY . PLIST), where PLIST is a property list storing PROP and VAL."
+ (declare (obsolete nil "1.15.0"))
+ (set alist-var
+ (let* ((alist (symbol-value alist-var))
+ (plist (cdr (assq key alist))))
+ (setq plist (plist-put plist prop val))
+ (when properties
+ (setq plist (evil-concat-plists plist properties)
+ val (car (last properties))))
+ (setq alist (assq-delete-all key alist))
+ (push (cons key plist) alist)))
+ val)
+
+(defun evil-state-property (state prop &optional value)
+ "Return the value of property PROP for STATE.
+PROP is a keyword as used by `evil-define-state'. STATE is the state's
+symbolic name. If VALUE is non-nil and the value is a variable, return
+the value of that variable.
+
+If STATE is t, return an association list of states and their PROP
+values instead."
+ (if (eq state t)
+ (cl-loop for (key . plist) in evil-state-properties with result do
+ (let ((p (plist-member plist prop)))
+ (when p (push (cons key (cadr p)) result)))
+ finally return result)
+ (let ((val (plist-get (cdr (assq state evil-state-properties)) prop)))
+ (if (and value (symbolp val) (boundp val))
+ (symbol-value val)
+ val))))
+
+(eval-and-compile (defalias 'evil-swap #'cl-rotatef))
+
+(defmacro evil-sort (&rest vars)
+ "Sort the symbol values of VARS.
+Place the smallest value in the first argument and the largest in the
+last, sorting in between."
+ (if (= (length vars) 2)
+ `(when (> ,@vars) (evil-swap ,@vars))
+ (let ((sorted (make-symbol "sortvar")))
+ `(let ((,sorted (sort (list ,@vars) #'<)))
+ (setq ,@(apply #'nconc
+ (mapcar (lambda (var) (list var `(pop ,sorted)))
+ vars)))))))
+
+(defun evil-vector-to-string (vector)
+ "Turn VECTOR into a string, changing <escape> to \"\\e\"."
+ (mapconcat (lambda (c) (if (eq c 'escape) "\e" (list c)))
+ vector
+ ""))
+
+;;; Command properties
+
+(defmacro evil-define-command (command &rest body)
+ "Define a command COMMAND.
+
+\(fn COMMAND (ARGS...) DOC [[KEY VALUE]...] BODY...)"
+ (declare (indent defun)
+ (doc-string 3)
+ (debug (&define name
+ [&optional lambda-list]
+ [&optional stringp]
+ [&rest keywordp sexp]
+ [&optional ("interactive" [&rest form])]
+ def-body)))
+ (let ((interactive '(interactive))
+ args doc doc-form keys)
+ ;; collect arguments
+ (when (listp (car body))
+ (setq args (pop body)))
+ ;; collect docstring
+ (cond ((stringp (car body)) (setq doc (pop body)))
+ ((eq (car-safe (car body)) #'format) (setq doc-form (pop body))))
+ ;; collect keywords
+ (while (keywordp (car body))
+ (let* ((key (pop body))
+ (arg (pop body)))
+ (setq keys (plist-put keys key arg)))) ; TODO: add keyword check
+ ;; collect `interactive' form
+ (when (eq (caar body) 'interactive)
+ (cl-destructuring-bind (form . attrs)
+ (apply #'evil-interactive-form (cdr (pop body)))
+ (setq interactive `(interactive ,form)
+ keys (evil-concat-plists keys attrs))))
+ `(progn
+ ;; the compiler does not recognize `defun' inside `let'
+ ,(when (and command body)
+ `(defun ,command ,args
+ ,@(when doc `(,doc))
+ ,interactive
+ ,@body))
+ ,(when (and command doc-form)
+ `(put ',command 'function-documentation ,doc-form))
+ ;; set command properties for symbol or lambda function
+ (let ((func ,(if (and (null command) body)
+ `(lambda ,args
+ ,interactive
+ ,@body)
+ `#',command)))
+ (apply #'evil-set-command-properties func ',keys)
+ func))))
+
+(define-obsolete-variable-alias
+ 'evil-command-properties 'evil--command-properties "1.15.0")
+(defvar evil--command-properties nil
+ "Specifications made by `evil-define-command'.")
+
+(defun evil-command-properties (command)
+ "Return the Evil command property list for COMMAND.
+See also `evil-get-command-property'."
+ (if (symbolp command) (get command 'evil--command-plist)
+ (cdr (assq command evil--command-properties))))
+(define-obsolete-function-alias
+ 'evil-get-command-properties #'evil-command-properties "1.15.0")
+
+(gv-define-setter evil-command-properties (val command)
+ `(if (symbolp ,command) (put ,command 'evil--command-plist ,val)
+ ,(macroexp-let2 nil p `(assq ,command evil--command-properties)
+ `(if ,p (setcdr ,p ,val)
+ (push (cons ,command ,val) evil--command-properties)))))
+
+(defalias 'evil-has-command-properties-p #'evil-command-properties
+ "Whether Evil properties are defined for COMMAND.
+See also `evil-has-command-property-p'.")
+
+(defun evil-has-command-property-p (command property)
+ "Whether COMMAND has Evil PROPERTY.
+See also `evil-has-command-properties-p'."
+ (plist-member (evil-command-properties command) property))
+
+(defun evil-get-command-property (command property &optional default)
+ "Return the value of Evil PROPERTY of COMMAND.
+If the command does not have the property, return DEFAULT.
+See also `evil-get-command-properties'."
+ (let ((p (plist-member (evil-command-properties command) property)))
+ (if p (cadr p) default)))
+
+(defun evil-add-command-properties (command &rest properties)
+ "Set each Evil command property KEY to its VAL for COMMAND.
+To replace existing properties, use `evil-set-command-properties'.
+
+\(fn COMMAND [KEY VAL]...)"
+ (let ((props (evil-command-properties command)))
+ (while properties
+ (setq props (plist-put props (pop properties) (pop properties))))
+ (setf (evil-command-properties command) props)))
+
+(defalias 'evil-set-command-property #'evil-add-command-properties
+ "Set PROPERTY to VALUE for COMMAND.
+To set multiple properties at once, see
+`evil-set-command-properties' and `evil-add-command-properties'.
+
+\(fn COMMAND PROPERTY VALUE)")
+(defalias 'evil-put-command-property #'evil-set-command-property)
+
+(defun evil-set-command-properties (command &rest properties)
+ "Replace all of COMMAND's properties with PROPERTIES.
+PROPERTIES should be a property list.
+This erases all previous properties; to only add properties,
+use `evil-set-command-property'."
+ (setf (evil-command-properties command) properties))
+
+(defun evil-remove-command-properties (command &rest properties)
+ "Remove PROPERTIES from COMMAND.
+PROPERTIES should be a list of properties (:PROP1 :PROP2 ...).
+If PROPERTIES is the empty list, all properties are removed."
+ (let (plist)
+ (when properties
+ (setq plist (evil-command-properties command))
+ (dolist (property properties)
+ (setq plist (evil-plist-delete property plist))))
+ (apply #'evil-set-command-properties command plist)))
+
+(defun evil-yank-handler (&optional motion)
+ "Return the yank handler for MOTION.
+MOTION defaults to the current motion."
+ (evil-get-command-property (or motion evil-this-motion) :yank-handler))
+
+(defun evil-declare-motion (command)
+ "Declare COMMAND to be a movement function.
+This ensures that it behaves correctly in visual state."
+ (evil-add-command-properties command :keep-visual t :repeat 'motion))
+
+(defun evil-declare-repeat (command)
+ "Declare COMMAND to be repeatable."
+ (evil-add-command-properties command :repeat t))
+
+(defun evil-declare-not-repeat (command)
+ "Declare COMMAND to be nonrepeatable."
+ (evil-add-command-properties command :repeat nil))
+(defalias 'evil-declare-ignore-repeat #'evil-declare-not-repeat)
+
+(defun evil-declare-change-repeat (command)
+ "Declare COMMAND to be repeatable by buffer changes rather than
+keystrokes."
+ (evil-add-command-properties command :repeat 'change))
+
+(defun evil-declare-insert-at-point-repeat (command)
+ "Declare COMMAND to be repeatable by buffer changes."
+ (evil-add-command-properties command :repeat 'insert-at-point))
+
+(defun evil-declare-abort-repeat (command)
+ "Declare COMMAND to be nonrepeatable."
+ (evil-add-command-properties command :repeat 'abort))
+
+(defun evil-delimited-arguments (string &optional count)
+ "Parse STRING as a sequence of delimited arguments.
+Return a list of COUNT strings, or as many arguments as the string
+contains. The first non-blank character is taken to be the delimiter.
+If some arguments are missing from STRING, the resulting list is
+padded with nil values. Two delimiters following directly after each
+other gives an empty string."
+ (unless count (setq count -1))
+ (let ((idx 0) delim regexp result)
+ (when (string-match "^[[:space:]]*\\([^[:space:]]\\)" string)
+ (setq delim (match-string 1 string)
+ regexp (format "%s\\(\\(?:\\\\.\\|[^%s]\\)*\\)"
+ (regexp-quote delim) delim))
+ (while (and (/= count 0) (string-match regexp string idx)
+ (/= (match-beginning 1) (length string)))
+ (setq idx (match-end 0)
+ count (1- count))
+ (push
+ (if (when (= count 0)
+ (not (string-match-p
+ (concat (regexp-quote delim) "[[:space:]]*$")
+ string idx)))
+ (substring string (match-beginning 1))
+ (match-string 1 string))
+ result)))
+ (dotimes (_ count) (push nil result))
+ (nreverse result)))
+
+(defun evil-concat-charsets (&rest sets)
+ "Concatenate character sets.
+A character set is the part between [ and ] in a regular expression.
+If any character set is complemented, the result is also complemented."
+ (let ((bracket "") (complement "") (hyphen "") result)
+ (dolist (set sets)
+ (when (string-match-p "^\\^" set)
+ (setq set (substring set 1)
+ complement "^"))
+ (when (string-match-p "^]" set)
+ (setq set (substring set 1)
+ bracket "]"))
+ (when (string-match-p "^-" set)
+ (setq set (substring set 1)
+ hyphen "-"))
+ (setq result (concat result set)))
+ (format "%s%s%s%s" complement bracket hyphen result)))
+
+;;; Key sequences
+
+(defun evil-keypress-parser (&optional input)
+ "Read from keyboard or INPUT and build a command description.
+Return (CMD COUNT), where COUNT is the numeric prefix argument.
+Both COUNT and CMD may be nil."
+ (when input (setq unread-command-events (append input unread-command-events)))
+ (let (count negative)
+ (catch 'done
+ (while t
+ (let ((seq (read-key-sequence "")))
+ (when seq
+ (let ((cmd (key-binding seq)))
+ (cond
+ ((null cmd) (throw 'done (list nil nil)))
+ ((arrayp cmd) ; keyboard macro, recursive call
+ (let ((cmd (evil-keypress-parser cmd)))
+ (throw 'done
+ (list (car cmd)
+ (if (or count (cadr cmd))
+ (list (car cmd) (* (or count 1)
+ (or (cadr cmd) 1))))))))
+ ((or (eq cmd #'digit-argument)
+ (and (equal seq "0") count))
+ (let* ((event (aref seq (1- (length seq))))
+ (char (or (when (characterp event) event)
+ (when (symbolp event)
+ (get event 'ascii-character))))
+ (digit (when (integerp char) (- (logand char ?\177) ?0))))
+ (setq count (+ (* 10 (or count 0)) digit))))
+ ((eq cmd #'negative-argument)
+ (setq negative (not negative)))
+ (t
+ (throw 'done (list cmd
+ (and count
+ (* count
+ (if negative -1 1))))))))))))))
+
+(defun evil-read-key (&optional prompt)
+ "Read a key from the keyboard.
+Translates it according to the input method."
+ (let ((old-global-map (current-global-map))
+ (new-global-map (make-sparse-keymap))
+ (overriding-terminal-local-map nil)
+ (overriding-local-map evil-read-key-map)
+ seq char cmd)
+ (unwind-protect
+ (condition-case nil
+ (progn
+ (define-key new-global-map [menu-bar]
+ (lookup-key global-map [menu-bar]))
+ (define-key new-global-map [tab-bar]
+ (lookup-key global-map [tab-bar]))
+ (define-key new-global-map [tool-bar]
+ (lookup-key global-map [tool-bar]))
+ (setq new-global-map
+ (append new-global-map
+ (list (make-char-table 'display-table
+ 'self-insert-command))))
+ (use-global-map new-global-map)
+ (setq seq (read-key-sequence prompt nil t)
+ char (aref seq 0)
+ cmd (key-binding seq))
+ (while (arrayp cmd)
+ (setq char (aref cmd 0)
+ cmd (key-binding cmd)))
+ (cond
+ ((eq cmd 'self-insert-command) char)
+ (cmd (call-interactively cmd))
+ (t (user-error "No replacement character typed"))))
+ (quit
+ (when (fboundp 'evil-repeat-abort)
+ (evil-repeat-abort))
+ (signal 'quit nil)))
+ (use-global-map old-global-map))))
+
+(defun evil-read-quoted-char ()
+ "Command that calls `read-quoted-char'.
+This command can be used wherever `read-quoted-char' is required
+as a command. Its main use is in the `evil-read-key-map'."
+ (interactive)
+ (read-quoted-char))
+
+(defvar evil-digraph-read-key-keymap
+ (let ((map (make-sparse-keymap))
+ (n ?0))
+ (while (<= n ?9)
+ (define-key map (vector (intern (concat "kp-" (string n)))) nil)
+ (cl-incf n))
+ map)
+ "By default, used to exclude otherwise disabled fallbacks.")
+
+(declare-function evil-digraph "evil-digraphs")
+(defun evil-read-digraph-char-with-overlay (overlay)
+ "Read two chars, displaying the first in OVERLAY, replacing \"?\".
+Return the digraph from `evil-digraph', else return second char."
+ (interactive)
+ (unwind-protect
+ (let ((read-key-empty-map
+ (let ((map (copy-keymap evil-digraph-read-key-keymap)))
+ (set-keymap-parent map read-key-empty-map)
+ ;; Disable read-key-sequence unbound fallbacks, e.g. downcasing
+ (define-key map [t] 'dummy)
+ map))
+ char1 char2)
+ ;; create overlay prompt
+ (overlay-put overlay 'invisible t)
+ (overlay-put overlay 'after-string
+ #("?" 0 1 (face minibuffer-prompt cursor 1)))
+ (setq char1 (read-key))
+ (overlay-put overlay 'after-string
+ (propertize (char-to-string char1)
+ 'face 'minibuffer-prompt
+ 'cursor 1))
+ (setq char2 (read-key))
+
+ (or (evil-digraph (list char1 char2))
+ ;; use the last character if undefined
+ char2))
+ (delete-overlay overlay)))
+
+(defun evil-read-digraph-char (&optional hide-chars)
+ "Read two keys from keyboard forming a digraph.
+This function creates an overlay at (point), hiding the next
+HIDE-CHARS characters. HIDE-CHARS defaults to 1."
+ (interactive)
+ (let ((overlay (make-overlay
+ (point) (min (+ (point) (or hide-chars 1))
+ (point-max)))))
+ (evil-read-digraph-char-with-overlay overlay)))
+
+(defun evil-read-motion (&optional motion count type modifier)
+ "Read a MOTION, motion COUNT and motion TYPE from the keyboard.
+The type may be overridden with MODIFIER, which may be a type
+or a Visual selection as defined by `evil-define-visual-selection'.
+Return a list (MOTION COUNT [TYPE])."
+ (let (command prefix)
+ (setq evil-this-type-modified nil)
+ (unless motion
+ (while (progn
+ (setq command (evil-keypress-parser)
+ motion (pop command)
+ prefix (pop command))
+ (when prefix
+ (setq count
+ (if count
+ (string-to-number
+ (concat (number-to-string count)
+ (number-to-string prefix)))
+ prefix)))
+ ;; if the command is a type modifier, read more
+ (when (rassq motion evil-visual-alist)
+ (setq modifier
+ (or modifier
+ (car (rassq motion evil-visual-alist))))))))
+ (when modifier
+ (setq type (or type (evil-type motion 'exclusive)))
+ (cond
+ ((eq modifier 'char)
+ ;; TODO: this behavior could be less hard-coded
+ (setq type (if (eq type 'exclusive) 'inclusive 'exclusive)))
+ (t (setq type modifier)))
+ (setq evil-this-type-modified type))
+ (list motion count type)))
+
+(defun evil-mouse-events-p (keys)
+ "Return non-nil iff KEYS contains a mouse event."
+ (cl-loop for key across keys thereis
+ (or (mouse-event-p key)
+ (mouse-movement-p key))))
+
+(defun evil-extract-count (keys)
+ "Split the key-sequence KEYS into prefix-argument and the rest.
+Return the list (PREFIX CMD SEQ REST), where PREFIX is the
+prefix count, CMD the command to be executed, SEQ the subsequence
+calling CMD, and REST is all remaining events in the
+key-sequence. PREFIX and REST may be nil if they do not exist.
+If a command is bound to some keyboard macro, it is expanded
+recursively."
+ (catch 'done
+ (let ((len (length keys))
+ (beg 0)
+ (end 1)
+ found-prefix)
+ (while (<= end len)
+ (let* ((seq (substring keys beg end))
+ (cmd (key-binding seq)))
+ (cond
+ ((memq cmd '(undefined nil))
+ (user-error "No command bound to `%s'" seq))
+ ((arrayp cmd) ; keyboard macro, replace command with macro
+ (setq keys (vconcat (substring keys 0 beg)
+ cmd
+ (substring keys end))
+ end (1+ beg)
+ len (length keys)))
+ ((functionp cmd)
+ (if (or (memq cmd '(digit-argument negative-argument))
+ (and found-prefix
+ (equal (vconcat seq) (vector ?0))))
+ ;; skip those commands
+ (setq found-prefix t ; found at least one prefix argument
+ beg end
+ end (1+ end))
+ ;; a real command, finish
+ (throw 'done
+ (list (unless (zerop beg)
+ (string-to-number
+ (concat (substring keys 0 beg))))
+ cmd
+ seq
+ (when (< end len)
+ (substring keys end))))))
+ (t ; append a further event
+ (setq end (1+ end))))))
+ (user-error "Key sequence contains no complete binding"))))
+
+(defun evil-extract-append (file-or-append)
+ "Return an (APPEND . FILENAME) pair based on FILE-OR-APPEND.
+FILE-OR-APPEND should either be a filename or a \">> FILE\"
+directive. APPEND will be t if FILE-OR-APPEND is an append
+directive and nil otherwise. FILENAME will be the extracted
+filename."
+ (if (and (stringp file-or-append)
+ (string-match "\\(>> *\\)" file-or-append))
+ (cons t (substring file-or-append (match-end 1)))
+ (cons nil file-or-append)))
+
+(defun evil-set-keymap-prompt (map prompt)
+ "Set the prompt-string of MAP to PROMPT."
+ (delq (keymap-prompt map) map)
+ (when prompt
+ (setcdr map (cons prompt (cdr map)))))
+
+(defun evil-lookup-key (map key)
+ "Return non-nil value if KEY is bound in MAP."
+ (let ((definition (lookup-key map key)))
+ (unless (numberp definition) ; in-band error
+ definition)))
+
+;;; Display
+
+(defun evil-set-cursor (specs)
+ "Change the cursor's apperance according to SPECS.
+SPECS may be a cursor type as per `cursor-type', a color
+string as passed to `set-cursor-color', a zero-argument
+function for changing the cursor, or a list of the above.
+
+If SPECS is nil, this function does not have an effect;
+pass (list nil) instead to indicate a nil `cursor-type'
+\(i.e., to disable the cursor)."
+ (unless (and (not (functionp specs))
+ (listp specs)
+ (null (cdr-safe (last specs))))
+ (setq specs (list specs)))
+ (dolist (spec specs)
+ (cond
+ ((functionp spec)
+ (ignore-errors (funcall spec)))
+ ((stringp spec)
+ (evil-set-cursor-color spec))
+ (t
+ (setq cursor-type spec)))))
+
+(defun evil-set-cursor-color (color)
+ "Set the cursor color to COLOR."
+ (unless (equal (frame-parameter nil 'cursor-color) color)
+ ;; `set-cursor-color' forces a redisplay, so only
+ ;; call it when the color actually changes
+ (set-cursor-color color)))
+
+(defun evil-refresh-cursor (&optional state buffer)
+ "Refresh the cursor for STATE in BUFFER.
+BUFFER defaults to the current buffer. If STATE is nil the
+cursor type is either `evil-force-cursor' or the current state."
+ (defvar evil-local-mode)
+ (when evil-local-mode
+ (let* ((state (or state evil-force-cursor evil-state 'normal))
+ (default (or evil-default-cursor t))
+ (cursor (evil-state-property state :cursor t))
+ (color (or (and (stringp cursor) cursor)
+ (and (listp cursor) (evil-member-if #'stringp cursor))
+ (frame-parameter nil 'cursor-color))))
+ (with-current-buffer (or buffer (current-buffer))
+ ;; if both STATE and `evil-default-cursor'
+ ;; specify a color, don't set it twice
+ (evil-set-cursor (if (and color (listp default))
+ (cl-remove-if #'stringp default)
+ default))
+ (evil-set-cursor cursor)))))
+
+(defmacro evil-save-cursor (&rest body)
+ "Save the current cursor; execute BODY; restore the cursor."
+ (declare (indent defun) (debug t) (obsolete nil "1.15.0"))
+ `(let ((cursor cursor-type)
+ (color (frame-parameter (selected-frame) 'cursor-color))
+ (inhibit-quit t))
+ (unwind-protect
+ (progn ,@body)
+ (setq cursor-type cursor)
+ (evil-set-cursor-color color))))
+
+(defun evil-echo (string &rest args)
+ "Display an unlogged message in the echo area.
+That is, the message is not logged in the *Messages* buffer.
+\(To log the message, just use `message'.)"
+ (unless evil-no-display
+ (let (message-log-max)
+ (apply #'message string args))))
+
+(defun evil-echo-area-save ()
+ "Save the current echo area in `evil-echo-area-message'."
+ (setq evil-echo-area-message (current-message)))
+
+(defun evil-echo-area-restore ()
+ "Restore the echo area from `evil-echo-area-message'.
+Does not restore if `evil-write-echo-area' is non-nil."
+ (unless evil-write-echo-area
+ (if evil-echo-area-message
+ (message "%s" evil-echo-area-message)
+ (message nil)))
+ (setq evil-echo-area-message nil
+ evil-write-echo-area nil))
+
+;; toggleable version of `with-temp-message'
+(defmacro evil-save-echo-area (&rest body)
+ "Save the echo area; execute BODY; restore the echo area.
+Intermittent messages are not logged in the *Messages* buffer."
+ (declare (indent defun) (debug t))
+ `(let ((inhibit-quit t)
+ evil-echo-area-message evil-write-echo-area)
+ (evil-echo-area-save)
+ (unwind-protect
+ (progn ,@body)
+ (evil-echo-area-restore))))
+
+(defmacro evil-without-display (&rest body)
+ "Execute BODY without Evil displays.
+Inhibits echo area messages, mode line updates and cursor changes."
+ (declare (indent defun)
+ (debug t))
+ `(let ((evil-no-display t))
+ ,@body))
+
+(defun evil-count-lines (beg end)
+ "Return absolute line-number-difference betweeen BEG and END.
+This should give the same results no matter where on the line BEG
+and END are."
+ (if (= beg end)
+ 0
+ (let ((end-at-bol (save-excursion (goto-char (max beg end))
+ (bolp))))
+ (if end-at-bol
+ (count-lines beg end)
+ (1- (count-lines beg end))))))
+
+;;; Movement
+
+(defun evil-normalize-position (pos)
+ "Return POS if it does not exceed the buffer boundaries.
+If POS is less than `point-min', return `point-min'.
+Is POS is more than `point-max', return `point-max'.
+If POS is a marker, return its position."
+ (cond
+ ((not (number-or-marker-p pos))
+ pos)
+ ((< pos (point-min))
+ (point-min))
+ ((> pos (point-max))
+ (point-max))
+ ((markerp pos)
+ (marker-position pos))
+ (t
+ pos)))
+
+(defmacro evil-save-goal-column (&rest body)
+ "Restore the goal column after execution of BODY.
+See also `evil-save-column'."
+ (declare (indent defun)
+ (debug t))
+ `(let ((goal-column goal-column)
+ (temporary-goal-column temporary-goal-column))
+ ,@body))
+
+(defmacro evil-save-column (&rest body)
+ "Restore the column after execution of BODY.
+See also `evil-save-goal-column'."
+ (declare (indent defun)
+ (debug t))
+ `(let ((col (current-column)))
+ (evil-save-goal-column
+ ,@body
+ (move-to-column col))))
+
+(defun evil--stick-to-eol-p ()
+ "Called by vertical movement commands to help determine cursor position."
+ (and evil-track-eol
+ (eq (or goal-column temporary-goal-column) most-positive-fixnum)
+ (memq last-command '(next-line previous-line))))
+
+(defun evil-eolp ()
+ "Like `eolp' but accounts for `evil-move-beyond-eol' being nil."
+ (ignore-errors
+ (save-excursion
+ (unless (or evil-move-beyond-eol (memq evil-state '(insert replace)))
+ (forward-char))
+ (eolp))))
+
+(defmacro evil-ensure-column (&rest body)
+ "Execute BODY so that column after execution is correct.
+If `evil-start-of-line' is nil, treat BODY as if it were a `next-line' command.
+This mostly copies the approach of Emacs' `line-move-1', but is modified
+so it is more compatible with Evil's notion of EOL tracking."
+ (declare (indent defun) (debug t))
+ `(progn
+ (unless evil-start-of-line
+ (setq this-command 'next-line
+ temporary-goal-column
+ (cond ((memq last-command '(next-line previous-line))
+ temporary-goal-column)
+ ((and track-eol (eolp) (not (bolp))) most-positive-fixnum)
+ (t (current-column)))))
+ ,@body
+ (if evil-start-of-line
+ (evil-first-non-blank)
+ (line-move-to-column
+ (or goal-column
+ (if (consp temporary-goal-column)
+ ;; Guard against a negative value as `temporary-goal-column'
+ ;; may have a negative component when both `whitespace-mode'
+ ;; and `display-line-numbers-mode' are enabled (#1297).
+ (max 0 (+ (truncate (car temporary-goal-column))
+ (cdr temporary-goal-column)))
+ temporary-goal-column))))))
+
+(defun evil-narrow (beg end)
+ "Restrict the buffer to BEG and END.
+BEG or END may be nil, specifying a one-sided restriction including
+`point-min' or `point-max'. See also `evil-with-restriction.'"
+ (declare (obsolete nil "1.15.0"))
+ (narrow-to-region
+ (if beg (max beg (point-min)) (point-min))
+ (if end (min end (point-max)) (point-max))))
+
+(defmacro evil-with-restriction (beg end &rest body)
+ "Execute BODY with the buffer narrowed to BEG and END.
+BEG or END may be nil to specify a one-sided restriction."
+ (declare (indent 2) (debug t))
+ `(save-restriction
+ (let ((evil-restriction-stack
+ (cons (cons (point-min) (point-max)) evil-restriction-stack)))
+ (narrow-to-region (or ,beg (point-min)) (or ,end (point-max)))
+ ,@body)))
+
+(defmacro evil-without-restriction (&rest body)
+ "Execute BODY with the top-most narrowing removed.
+This works only if the previous narrowing has been generated by
+`evil-with-restriction'."
+ (declare (indent defun) (debug t))
+ `(save-restriction
+ (widen)
+ (narrow-to-region (car (car evil-restriction-stack))
+ (cdr (car evil-restriction-stack)))
+ (let ((evil-restriction-stack (cdr evil-restriction-stack)))
+ ,@body)))
+
+(defmacro evil-narrow-to-field (&rest body)
+ "Narrow to the current field."
+ (declare (indent defun)
+ (debug t))
+ `(evil-with-restriction (field-beginning) (field-end)
+ ,@body))
+
+(defun evil-move-beginning-of-line (&optional arg)
+ "Move to the beginning of the line as displayed.
+Like `move-beginning-of-line', but retains the goal column."
+ (evil-save-goal-column
+ (move-beginning-of-line arg)
+ (beginning-of-line)))
+
+(defun evil-move-end-of-line (&optional arg)
+ "Move to the end of the line as displayed.
+Like `move-end-of-line', but retains the goal column."
+ (evil-save-goal-column
+ (move-end-of-line arg)
+ (end-of-line)))
+
+(defun evil-adjust-cursor (&optional _)
+ "Move point one character back if at the end of a non-empty line.
+This behavior is controlled by `evil-move-beyond-eol'."
+ (and (not evil-move-beyond-eol)
+ (eolp)
+ (evil-move-cursor-back t)))
+
+(defun evil-move-cursor-back (&optional force)
+ "Move point one character back within the current line.
+Contingent on the variable `evil-move-cursor-back' or the FORCE
+argument. Movement is constrained to the current field."
+ (or (not (or evil-move-cursor-back force))
+ (bolp)
+ (when (bound-and-true-p visual-line-mode)
+ (= (point) (save-excursion (vertical-motion 0) (point))))
+ (goto-char (constrain-to-field (1- (point)) (point)))))
+
+(defun evil-line-position (line &optional column)
+ "Return the position of LINE.
+If COLUMN is specified, return its position on the line.
+A negative number means the end of the line."
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (when (numberp column)
+ (if (< column 0)
+ (forward-line)
+ (move-to-column column)))
+ (point)))
+
+(defun evil-column (&optional pos)
+ "Return the horizontal position of POS.
+POS defaults to point."
+ (save-excursion
+ (when pos
+ (goto-char pos))
+ (current-column)))
+
+(defun evil-move-to-column (column &optional dir force)
+ "Move point to column COLUMN in the current line.
+Places point at left of the tab character (at the right if DIR
+is non-nil) and returns point."
+ (interactive "p")
+ (move-to-column column force)
+ (unless force
+ (when (or (not dir) (and (numberp dir) (< dir 1)))
+ (when (> (current-column) column)
+ (evil-move-cursor-back))))
+ (point))
+
+(defmacro evil-loop (spec &rest body)
+ "Loop with countdown variable.
+Evaluate BODY with VAR counting down from COUNT to 0.
+COUNT can be negative, in which case VAR counts up instead.
+The return value is the value of VAR when the loop
+terminates, which is 0 if the loop completes successfully.
+RESULT specifies a variable for storing this value.
+
+\(fn (VAR COUNT [RESULT]) BODY...)"
+ (declare (indent defun) (debug dolist) (obsolete nil "1.15.0"))
+ (let* ((i (make-symbol "loopvar"))
+ (var (pop spec))
+ (count (pop spec))
+ (result (pop spec)))
+ (setq var (or (unless (eq var result) var) i)
+ result (or result var))
+ `(let ((,var ,count))
+ (setq ,result ,var)
+ (while (/= ,var 0)
+ ,@body
+ (if (> ,var 0)
+ (setq ,var (1- ,var))
+ (setq ,var (1+ ,var)))
+ (setq ,result ,var))
+ ,var)))
+
+;;; Motions
+
+(defmacro evil-motion-loop (spec &rest body)
+ "Loop a certain number of times.
+Evaluate BODY repeatedly COUNT times with VAR bound to 1 or -1,
+depending on the sign of COUNT. Set RESULT, if specified, to the
+number of unsuccessful iterations, which is 0 if the loop completes
+successfully. This is also the return value.
+
+Each iteration must move point; if point does not change, the loop
+immediately quits.
+
+\(fn (VAR COUNT [RESULT]) BODY...)"
+ (declare (indent defun)
+ (debug ((symbolp form &optional symbolp) body)))
+ (let* ((var (or (pop spec) (make-symbol "unitvar")))
+ (count (or (pop spec) 0))
+ (result (or (pop spec) var))
+ (i (make-symbol "loopvar")))
+ `(let* ((,i ,count)
+ (,var (if (< ,i 0) -1 1)))
+ (while (and (/= ,i 0)
+ (/= (point) (progn ,@body (point))))
+ (setq ,i (if (< ,i 0) (1+ ,i) (1- ,i))))
+ (setq ,result ,i))))
+
+(defun evil-signal-at-bob-or-eob (&optional count)
+ "Signal error if `point' is at boundaries.
+If `point' is at bob and COUNT is negative this function signals
+`beginning-of-buffer'. If `point' is at eob and COUNT is positive
+this function signals `end-of-buffer'. This function should be used
+in motions. COUNT defaults to 1."
+ (setq count (or count 1))
+ (cond
+ ((< count 0) (evil-signal-at-bob))
+ ((> count 0) (evil-signal-at-eob))))
+
+(defun evil-signal-at-bob ()
+ "Signal `beginning-of-buffer' if `point' is at bob.
+This function should be used in backward motions. If `point' is at
+bob so that no further backward motion is possible the error
+`beginning-of-buffer' is raised."
+ (when (bobp) (signal 'beginning-of-buffer nil)))
+
+(defun evil-signal-at-eob ()
+ "Signal `end-of-buffer' if `point' is at eob.
+This function should be used in forward motions. If `point' is close
+to eob so that no further forward motion is possible the error
+`end-of-buffer' is raised. This is the case if `point' is at
+`point-max' or if is one position before `point-max',
+`evil-move-beyond-eol' is nil and `point' is not at the end
+of a line. The latter is necessary because `point' cannot be
+moved to `point-max' if `evil-move-beyond-eol' is nil and
+the last line in the buffer is not empty."
+ (when (or (eobp)
+ (and (not (eolp))
+ (not evil-move-beyond-eol)
+ (save-excursion (forward-char) (eobp))))
+ (signal 'end-of-buffer nil)))
+
+(defmacro evil-with-hproject-point-on-window (&rest body)
+ "Project point after BODY to current window.
+If point is on a position left or right of the current window
+then it is moved to the left and right boundary of the window,
+respectively. If `auto-hscroll-mode' is non-nil then the left and
+right positions are increased or decreased, respectively, by
+`horizontal-margin' so that no automatic scrolling occurs."
+ (declare (indent defun)
+ (debug t))
+ (let ((diff (make-symbol "diff"))
+ (left (make-symbol "left"))
+ (right (make-symbol "right")))
+ `(let ((,diff (if auto-hscroll-mode (1+ hscroll-margin) 0))
+ auto-hscroll-mode)
+ ,@body
+ (let* ((,left (+ (window-hscroll) ,diff))
+ (,right (+ (window-hscroll) (window-width) (- ,diff) -1)))
+ (move-to-column (min (max (current-column) ,left) ,right))))))
+
+(defun evil-forward-not-thing (thing &optional count)
+ "Move point to the end or beginning of the complement of THING."
+ (evil-motion-loop (dir (or count 1))
+ (let (bnd)
+ (cond
+ ((> dir 0)
+ (while (and (setq bnd (bounds-of-thing-at-point thing))
+ (< (point) (cdr bnd)))
+ (goto-char (cdr bnd)))
+ ;; no thing at (point)
+ (if (zerop (forward-thing thing))
+ ;; now at the end of the next thing
+ (let ((bnd (bounds-of-thing-at-point thing)))
+ (if (or (< (car bnd) (point)) ; end of a thing
+ (= (car bnd) (cdr bnd))) ; zero width thing
+ (goto-char (car bnd))
+ ;; beginning of yet another thing, go back
+ (forward-thing thing -1)))
+ (goto-char (point-max))))
+ (t
+ (while (and (not (bobp))
+ (setq bnd (progn (backward-char) (bounds-of-thing-at-point thing)))
+ (< (point) (cdr bnd)))
+ (goto-char (car bnd)))
+ ;; either bob or no thing at point
+ (goto-char
+ (if (and (not (bobp))
+ (zerop (forward-thing thing -1))
+ (setq bnd (bounds-of-thing-at-point thing)))
+ (cdr bnd)
+ (point-min))))))))
+
+(defun evil-bounds-of-not-thing-at-point (thing &optional which)
+ "Return the bounds of a complement of THING at point.
+If there is a THING at point nil is returned. Otherwise if WHICH
+is nil or 0 a cons cell (BEG . END) is returned. If WHICH is
+negative the beginning is returned. If WHICH is positive the END
+is returned."
+ (let ((pnt (point)))
+ (let ((beg (save-excursion
+ (and (zerop (forward-thing thing -1))
+ (forward-thing thing))
+ (if (> (point) pnt) (point-min) (point))))
+ (end (save-excursion
+ (and (zerop (forward-thing thing))
+ (forward-thing thing -1))
+ (if (< (point) pnt) (point-max) (point)))))
+ (when (and (<= beg (point) end) (< beg end))
+ (cond
+ ((or (not which) (zerop which)) (cons beg end))
+ ((< which 0) beg)
+ ((> which 0) end))))))
+
+(defun evil-forward-nearest (count &rest forwards)
+ "Move point forward to the first of several motions.
+FORWARDS is a list of forward motion functions (i.e. each moves
+point forward to the next end of a text object (if passed a +1)
+or backward to the preceeding beginning of a text object (if
+passed a -1)). This function calls each of these functions once
+and moves point to the nearest of the resulting positions. If
+COUNT is positive point is moved forward COUNT times, if negative
+point is moved backward -COUNT times."
+ (evil-motion-loop (dir (or count 1))
+ (let ((pnt (point))
+ (nxt (if (< dir 0) (point-min) (point-max))))
+ (dolist (fwd forwards)
+ (goto-char pnt)
+ (ignore-errors
+ (evil-with-restriction
+ (when (< dir 0)
+ (save-excursion
+ (goto-char nxt)
+ (line-beginning-position 0)))
+ (when (> dir 0)
+ (save-excursion
+ (goto-char nxt)
+ (line-end-position 2)))
+ (and (zerop (funcall fwd dir))
+ (/= (point) pnt)
+ (if (< dir 0) (> (point) nxt) (< (point) nxt))
+ (setq nxt (point))))))
+ (goto-char nxt))))
+
+(defun bounds-of-evil-string-at-point (&optional state)
+ "Return the bounds of a string at point.
+If STATE is given it used a parsing state at point."
+ (save-excursion
+ (let ((state (or state (syntax-ppss))))
+ (when (nth 3 state)
+ (cons (nth 8 state)
+ (when (parse-partial-sexp
+ (point) (point-max) nil nil state 'syntax-table)
+ (point)))))))
+(put 'evil-string 'bounds-of-thing-at-point #'bounds-of-evil-string-at-point)
+
+(defun bounds-of-evil-comment-at-point ()
+ "Return the bounds of a string at point."
+ (save-excursion
+ (let ((state (syntax-ppss)))
+ (when (nth 4 state)
+ (cons (nth 8 state)
+ (when (parse-partial-sexp
+ (point) (point-max) nil nil state 'syntax-table)
+ (point)))))))
+(put 'evil-comment 'bounds-of-thing-at-point #'bounds-of-evil-comment-at-point)
+
+;; The purpose of this function is to provide line motions which
+;; preserve the column. This is how `previous-line' and `next-line'
+;; work, but unfortunately the behaviour is hard-coded: if and only if
+;; the last command was `previous-line' or `next-line', the column is
+;; preserved. Furthermore, in contrast to Vim, when we cannot go
+;; further, those motions move point to the beginning resp. the end of
+;; the line (we never want point to leave its column). The code here
+;; comes from simple.el, and I hope it will work in future.
+(declare-function evil-end-of-visual-line "evil-commands")
+(defun evil-line-move (count &optional noerror)
+ "Like `line-move' but conserves the column.
+Signal an error at buffer boundaries unless NOERROR is non-nil."
+ (setq this-command (if (< count 0) 'previous-line 'next-line))
+ (let ((last-command
+ ;; Reset tmp goal column between visual/logical movement
+ (when (or (eq line-move-visual (consp temporary-goal-column))
+ (eq temporary-goal-column most-positive-fixnum))
+ last-command))
+ (opoint (point)))
+ (if (and line-move-visual
+ (eq temporary-goal-column most-positive-fixnum)
+ (memq last-command '(next-line previous-line)))
+ (let (temporary-goal-column) (evil-end-of-visual-line (1+ count)))
+ (condition-case err
+ (line-move count)
+ ((beginning-of-buffer end-of-buffer)
+ (let* ((raw-col (or goal-column
+ (car-safe temporary-goal-column)
+ temporary-goal-column))
+ (col (if (numberp raw-col) (max 0 raw-col) 0)))
+ (line-move-finish col opoint (< count 0)))
+ (or noerror (/= (point) opoint) (signal (car err) (cdr err))))))))
+
+(defun evil-forward-syntax (syntax &optional count)
+ "Move point to the end or beginning of a sequence of characters in SYNTAX.
+Stop on reaching a character not in SYNTAX."
+ (let ((notsyntax (if (= (aref syntax 0) ?^)
+ (substring syntax 1)
+ (concat "^" syntax))))
+ (evil-motion-loop (dir (or count 1))
+ (cond
+ ((< dir 0)
+ (skip-syntax-backward notsyntax)
+ (skip-syntax-backward syntax))
+ (t
+ (skip-syntax-forward notsyntax)
+ (skip-syntax-forward syntax))))))
+
+(defun evil-forward-chars (chars &optional count)
+ "Move point to the end or beginning of a sequence of CHARS.
+CHARS is a character set as inside [...] in a regular expression."
+ (let ((notchars (if (= (aref chars 0) ?^)
+ (substring chars 1)
+ (concat "^" chars))))
+ (evil-motion-loop (dir (or count 1))
+ (cond
+ ((< dir 0)
+ (skip-chars-backward notchars)
+ (skip-chars-backward chars))
+ (t
+ (skip-chars-forward notchars)
+ (skip-chars-forward chars))))))
+
+(defun evil-up-block (beg end &optional count)
+ "Move point to the end or beginning of text enclosed by BEG and END.
+BEG and END should be regular expressions matching the opening
+and closing delimiters, respectively. If COUNT is greater than
+zero point is moved forward otherwise it is moved
+backwards. Whenever an opening delimiter is found the COUNT is
+increased by one, if a closing delimiter is found the COUNT is
+decreased by one. The motion stops when COUNT reaches zero. The
+match-data reflects the last successful match (that caused COUNT
+to reach zero). The behaviour of this functions is similar to
+`up-list'."
+ (let* ((count (or count 1))
+ (forwardp (> count 0))
+ (dir (if forwardp +1 -1)))
+ (catch 'done
+ (while (not (zerop count))
+ (let* ((pnt (point))
+ (cl (save-excursion
+ (and (re-search-forward (if forwardp end beg) nil t dir)
+ (or (/= pnt (point))
+ (progn
+ ;; zero size match, repeat search from
+ ;; the next position
+ (forward-char dir)
+ (re-search-forward (if forwardp end beg) nil t dir)))
+ (point))))
+ (match (match-data t))
+ (op (save-excursion
+ (and (not (equal beg end))
+ (re-search-forward (if forwardp beg end) cl t dir)
+ (or (/= pnt (point))
+ (progn
+ ;; zero size match, repeat search from
+ ;; the next position
+ (forward-char dir)
+ (re-search-forward (if forwardp beg end) cl t dir)))
+ (point)))))
+ (cond
+ ((not cl)
+ (goto-char (if forwardp (point-max) (point-min)))
+ (set-match-data nil)
+ (throw 'done count))
+ (t
+ (if op
+ (progn
+ (setq count (if forwardp (1+ count) (1- count)))
+ (goto-char op))
+ (setq count (if forwardp (1- count) (1+ count)))
+ (if (zerop count) (set-match-data match))
+ (goto-char cl))))))
+ 0)))
+
+(defun evil-up-paren (open close &optional count)
+ "Move point to the end or beginning of balanced parentheses.
+OPEN and CLOSE should be characters identifying the opening and
+closing parenthesis, respectively. If COUNT is greater than zero
+point is moved forward otherwise it is moved backwards. Whenever
+an opening delimiter is found the COUNT is increased by one, if a
+closing delimiter is found the COUNT is decreased by one. The
+motion stops when COUNT reaches zero. The match-data reflects the
+last successful match (that caused COUNT to reach zero)."
+ ;; Always use the default `forward-sexp-function'. This is important
+ ;; for modes that use a custom one like `python-mode'.
+ ;; (addresses #364)
+ (let (forward-sexp-function up-list-function)
+ (with-syntax-table (copy-syntax-table (syntax-table))
+ (modify-syntax-entry open (format "(%c" close))
+ (modify-syntax-entry close (format ")%c" open))
+ (let ((rest (evil-motion-loop (dir count)
+ (let ((pnt (point)))
+ (condition-case nil
+ (cond
+ ((> dir 0)
+ (while (progn
+ (up-list dir t)
+ (/= (char-before) close))))
+ (t
+ (while (progn
+ (up-list dir t)
+ (/= (char-after) open)))))
+ (error (goto-char pnt)))))))
+ (cond
+ ((= rest count) (set-match-data nil))
+ ((> count 0) (set-match-data (list (1- (point)) (point))))
+ (t (set-match-data (list (point) (1+ (point))))))
+ rest))))
+
+(defun evil-up-xml-tag (&optional count)
+ "Move point to the end or beginning of balanced xml tags.
+If COUNT is greater than zero point is moved forward otherwise it is moved
+backwards. Whenever an opening delimiter is found the COUNT is increased by
+one, if a closing delimiter is found the COUNT is decreased by one. The motion
+stops when COUNT reaches zero. The match data reflects the last successful
+match (that caused COUNT to reach zero)."
+ (let* ((dir (if (> (or count 1) 0) +1 -1))
+ (count (abs (or count 1)))
+ (op (if (> dir 0) 1 2))
+ (cl (if (> dir 0) 2 1))
+ (orig (point))
+ pnt tags match)
+ (catch 'done
+ (while (> count 0)
+ ;; find the previous opening tag
+ (while
+ (and (setq match
+ (re-search-forward
+ "<\\([^/ >\n]+\\)\\(?:=>?\\|[^\"/>]\\|\"[^\"]*\"\\)*?>\\|</\\([^>]+?\\)>"
+ nil t dir))
+ (cond
+ ((match-beginning op)
+ (push (match-string op) tags))
+ ((null tags) nil) ; free closing tag
+ ((and (< dir 0)
+ (string= (car tags) (match-string cl)))
+ ;; in backward direction we only accept matching
+ ;; tags. If the current tag is a free opener
+ ;; without matching closing tag, the subsequent
+ ;; test will make us ignore this tag
+ (pop tags))
+ ((and (> dir 0))
+ ;; non matching openers are considered free openers
+ (while (and tags
+ (not (string= (car tags)
+ (match-string cl))))
+ (pop tags))
+ (pop tags)))))
+ (unless (setq match (and match (match-data t)))
+ (setq match nil)
+ (throw 'done count))
+ ;; found closing tag, look for corresponding opening tag
+ (cond
+ ((> dir 0)
+ (setq pnt (match-end 0))
+ (goto-char (match-beginning 0)))
+ (t
+ (setq pnt (match-beginning 0))
+ (goto-char (match-end 0))))
+ (let* ((tag (match-string cl))
+ (refwd (concat "<\\(/\\)?"
+ (regexp-quote tag)
+ "\\(?:>\\|[ \n]\\(?:[^\"/>]\\|\"[^\"]*\"\\)*?>\\)"))
+ (cnt 1))
+ (while (and (> cnt 0) (re-search-backward refwd nil t dir))
+ (setq cnt (+ cnt (if (match-beginning 1) dir (- dir)))))
+ (if (zerop cnt) (setq count (1- count) tags nil))
+ (goto-char pnt)))
+ (if (> count 0)
+ (set-match-data nil)
+ (set-match-data match)
+ (goto-char (if (> dir 0) (match-end 0) (match-beginning 0)))))
+ ;; if not found, set to point-max/point-min
+ (unless (zerop count)
+ (set-match-data nil)
+ (goto-char (if (> dir 0) (point-max) (point-min)))
+ (if (/= (point) orig) (setq count (1- count))))
+ (* dir count)))
+
+(defun evil-forward-quote (quote &optional count)
+ "Move point to the end or beginning of a string.
+QUOTE is the character delimiting the string. If COUNT is greater
+than zero point is moved forward otherwise it is moved
+backwards."
+ (let (reset-parser)
+ (with-syntax-table (copy-syntax-table (syntax-table))
+ (unless (= (char-syntax quote) ?\")
+ (modify-syntax-entry quote "\"")
+ (setq reset-parser t))
+ ;; global parser state is out of state, use local one
+ (let* ((pnt (point))
+ (state (save-excursion
+ (beginning-of-defun)
+ (parse-partial-sexp (point) pnt nil nil (syntax-ppss))))
+ (bnd (bounds-of-evil-string-at-point state)))
+ (when (and bnd (< (point) (cdr bnd)))
+ ;; currently within a string
+ (if (> count 0)
+ (progn
+ (goto-char (cdr bnd))
+ (setq count (1- count)))
+ (goto-char (car bnd))
+ (setq count (1+ count))))
+ ;; forward motions work with local parser state
+ (cond
+ ((> count 0)
+ ;; no need to reset global parser state because we only use
+ ;; the local one
+ (setq reset-parser nil)
+ (catch 'done
+ (while (and (> count 0) (not (eobp)))
+ (setq state (parse-partial-sexp
+ (point) (point-max) nil nil state 'syntax-table))
+ (cond
+ ((nth 3 state)
+ (setq bnd (bounds-of-thing-at-point 'evil-string))
+ (goto-char (cdr bnd))
+ (setq count (1- count)))
+ ((eobp) (goto-char pnt) (throw 'done nil))))))
+ ((< count 0)
+ ;; need to update global cache because of backward motion
+ (setq reset-parser (and reset-parser (point)))
+ (save-excursion
+ (beginning-of-defun)
+ (syntax-ppss-flush-cache (point)))
+ (catch 'done
+ (while (and (< count 0) (not (bobp)))
+ (setq pnt (point))
+ (while (and (not (bobp))
+ (or (eobp) (/= (char-after) quote)))
+ (backward-char))
+ (cond
+ ((setq bnd (bounds-of-thing-at-point 'evil-string))
+ (goto-char (car bnd))
+ (setq count (1+ count)))
+ ((bobp) (goto-char pnt) (throw 'done nil))
+ (t (backward-char))))))
+ (t (setq reset-parser nil)))))
+ (when reset-parser
+ ;; reset global cache
+ (save-excursion
+ (goto-char reset-parser)
+ (beginning-of-defun)
+ (syntax-ppss-flush-cache (point))))
+ count))
+
+;;; Thing-at-point motion functions for Evil text objects and motions
+(defun forward-evil-empty-line (&optional count)
+ "Move forward COUNT empty lines."
+ (setq count (or count 1))
+ (cond
+ ((> count 0)
+ (while (and (> count 0) (not (eobp)))
+ (when (and (bolp) (eolp))
+ (setq count (1- count)))
+ (forward-line 1)))
+ (t
+ (while (and (< count 0) (not (bobp))
+ (zerop (forward-line -1)))
+ (when (and (bolp) (eolp))
+ (setq count (1+ count))))))
+ count)
+
+(defun forward-evil-space (&optional count)
+ "Move forward COUNT whitespace sequences [[:space:]]+."
+ (evil-forward-chars "[:space:]" count))
+
+(defun forward-evil-word (&optional count)
+ "Move forward COUNT words.
+Moves point COUNT words forward or (- COUNT) words backward if
+COUNT is negative. Point is placed after the end of the word (if
+forward) or at the first character of the word (if backward). A
+word is a sequence of word characters matching
+\[[:word:]] (recognized by `forward-word'), a sequence of
+non-whitespace non-word characters '[^[:word:]\\n\\r\\t\\f ]', or
+an empty line matching ^$."
+ (evil-forward-nearest
+ count
+ #'(lambda (&optional cnt)
+ (let ((word-separating-categories evil-cjk-word-separating-categories)
+ (word-combining-categories evil-cjk-word-combining-categories)
+ (pnt (point)))
+ (forward-word cnt)
+ (if (= pnt (point)) cnt 0)))
+ #'(lambda (&optional cnt)
+ (evil-forward-chars "^[:word:]\n\r\t\f " cnt))
+ #'forward-evil-empty-line))
+
+(defun forward-evil-WORD (&optional count)
+ "Move forward COUNT \"WORDS\".
+Moves point COUNT WORDS forward or (- COUNT) WORDS backward if
+COUNT is negative. Point is placed after the end of the WORD (if
+forward) or at the first character of the WORD (if backward). A
+WORD is a sequence of non-whitespace characters
+'[^\\n\\r\\t\\f ]', or an empty line matching ^$."
+ (evil-forward-nearest count
+ #'(lambda (&optional cnt)
+ (evil-forward-chars "^\n\r\t\f " cnt))
+ #'forward-evil-empty-line))
+
+(defun forward-evil-symbol (&optional count)
+ "Move forward COUNT symbols.
+Moves point COUNT symbols forward or (- COUNT) symbols backward
+if COUNT is negative. Point is placed after the end of the
+symbol (if forward) or at the first character of the symbol (if
+backward). A symbol is either determined by `forward-symbol', or
+is a sequence of characters not in the word, symbol or whitespace
+syntax classes."
+ (evil-forward-nearest
+ count
+ #'(lambda (&optional cnt)
+ (evil-forward-syntax "^w_->" cnt))
+ #'(lambda (&optional cnt)
+ (let ((pnt (point)))
+ (forward-symbol cnt)
+ (if (= pnt (point)) cnt 0)))
+ #'forward-evil-empty-line))
+
+(defun forward-evil-defun (&optional count)
+ "Move forward COUNT defuns.
+Moves point COUNT defuns forward or (- COUNT) defuns backward
+if COUNT is negative. A defun is defined by
+`beginning-of-defun' and `end-of-defun' functions."
+ (evil-motion-loop (dir (or count 1))
+ (if (> dir 0) (end-of-defun) (beginning-of-defun))))
+
+(defun forward-evil-sentence (&optional count)
+ "Move forward COUNT sentences.
+Moves point COUNT sentences forward or (- COUNT) sentences
+backward if COUNT is negative. This function is the same as
+`forward-sentence' but returns the number of sentences that could
+NOT be moved over."
+ (evil-motion-loop (dir (or count 1))
+ (ignore-errors (forward-sentence dir))))
+
+(defun forward-evil-paragraph (&optional count)
+ "Move forward COUNT paragraphs.
+Moves point COUNT paragraphs forward or (- COUNT) paragraphs backward
+if COUNT is negative. A paragraph is defined by
+`start-of-paragraph-text' and `forward-paragraph' functions."
+ (evil-motion-loop (dir (or count 1))
+ (cond
+ ((> dir 0) (forward-paragraph))
+ ((not (bobp)) (start-of-paragraph-text) (beginning-of-line)))))
+
+(defvar evil-forward-quote-char ?\"
+ "The character to be used by `forward-evil-quote'.")
+
+(defun forward-evil-quote (&optional count)
+ "Move forward COUNT strings.
+The quotation character is specified by the global variable
+`evil-forward-quote-char'. This character is passed to
+`evil-forward-quote'."
+ (evil-forward-quote evil-forward-quote-char count))
+
+(defun forward-evil-quote-simple (&optional count)
+ "Move forward COUNT strings.
+The quotation character is specified by the global variable
+`evil-forward-quote-char'. This functions uses Vim's rules
+parsing from the beginning of the current line for quotation
+characters. It should only be used when looking for strings
+within comments and buffer *must* be narrowed to the comment."
+ (let ((dir (if (> (or count 1) 0) 1 -1))
+ (ch evil-forward-quote-char)
+ (pnt (point))
+ (cnt 0))
+ (beginning-of-line)
+ ;; count number of quotes before pnt
+ (while (< (point) pnt)
+ (when (= (char-after) ch)
+ (setq cnt (1+ cnt)))
+ (forward-char))
+ (setq cnt (- (* 2 (abs count)) (mod cnt 2)))
+ (cond
+ ((> dir 0)
+ (while (and (not (eolp)) (not (zerop cnt)))
+ (when (= (char-after) ch) (setq cnt (1- cnt)))
+ (forward-char))
+ (when (not (zerop cnt)) (goto-char (point-max))))
+ (t
+ (while (and (not (bolp)) (not (zerop cnt)))
+ (when (= (char-before) ch) (setq cnt (1- cnt)))
+ (forward-char -1))
+ (when (not (zerop cnt)) (goto-char (point-min)))))
+ (/ cnt 2)))
+
+;;; Motion functions
+(defun evil-forward-beginning (thing &optional count)
+ "Move forward to beginning of THING.
+The motion is repeated COUNT times."
+ (setq count (or count 1))
+ (if (< count 0)
+ (forward-thing thing count)
+ (let ((bnd (bounds-of-thing-at-point thing))
+ rest)
+ (when (and bnd (< (point) (cdr bnd)))
+ (goto-char (cdr bnd)))
+ (ignore-errors
+ (when (zerop (setq rest (forward-thing thing count)))
+ (when (and (bounds-of-thing-at-point thing)
+ (not (bobp))
+ ;; handle final empty line
+ (not (and (bolp) (eobp))))
+ (backward-char))
+ (beginning-of-thing thing)))
+ rest)))
+
+(defun evil-backward-beginning (thing &optional count)
+ "Move backward to beginning of THING.
+The motion is repeated COUNT times. This is the same as calling
+`evil-backward-beginning' with -COUNT."
+ (evil-forward-beginning thing (- (or count 1))))
+
+(defun evil-forward-end (thing &optional count)
+ "Move forward to end of THING.
+The motion is repeated COUNT times."
+ (setq count (or count 1))
+ (if (> count 0)
+ (progn (unless (eobp) (forward-char))
+ (prog1 (forward-thing thing count)
+ (unless (bobp) (backward-char))))
+ (let ((bnd (bounds-of-thing-at-point thing))
+ rest)
+ (when (and bnd (< (point) (cdr bnd) ))
+ (goto-char (car bnd)))
+ (ignore-errors
+ (when (zerop (setq rest (forward-thing thing count)))
+ (end-of-thing thing)
+ (backward-char)))
+ rest)))
+
+(defun evil-backward-end (thing &optional count)
+ "Move backward to end of THING.
+The motion is repeated COUNT times. This is the same as calling
+`evil-backward-end' with -COUNT."
+ (evil-forward-end thing (- (or count 1))))
+
+(defun evil-forward-word (&optional count)
+ "Move by words.
+Moves point COUNT words forward or (- COUNT) words backward if
+COUNT is negative. This function is the same as `forward-word'
+but returns the number of words by which point could *not* be
+moved."
+ (setq count (or count 1))
+ (let* ((dir (if (>= count 0) +1 -1))
+ (count (abs count)))
+ (while (and (> count 0)
+ (forward-word dir))
+ (setq count (1- count)))
+ count))
+
+(defun evil-in-comment-p (&optional pos)
+ "Check if POS is within a comment according to current syntax.
+If POS is nil, (point) is used. The return value is the beginning
+position of the comment."
+ (setq pos (or pos (point)))
+ (let ((chkpos
+ (cond
+ ((eobp) pos)
+ ((= (char-syntax (char-after)) ?<) (1+ pos))
+ ((and (not (zerop (logand (car (syntax-after (point)))
+ (ash 1 16))))
+ (not (zerop (logand (or (car (syntax-after (1+ (point)))) 0)
+ (ash 1 17)))))
+ (+ pos 2))
+ ((and (not (zerop (logand (car (syntax-after (point)))
+ (ash 1 17))))
+ (not (zerop (logand (or (car (syntax-after (1- (point)))) 0)
+ (ash 1 16)))))
+ (1+ pos))
+ (t pos))))
+ (let ((syn (save-excursion (syntax-ppss chkpos))))
+ (and (nth 4 syn) (nth 8 syn)))))
+
+(defun evil-looking-at-start-comment (&optional move)
+ "Return t if point is at the start of a comment.
+Point must be on one of the opening characters of a block comment
+according to the current syntax table. Futhermore, these
+characters must been parsed as opening characters, i.e. they
+won't be considered as comment starters inside a string or
+possibly another comment. Point is moved to the first character
+of the comment opener if MOVE is non-nil."
+ (cond
+ ((= (point) (point-max)) nil)
+ ;; one character opener
+ ((= (char-syntax (char-after)) ?<)
+ (equal (point) (evil-in-comment-p (1+ (point)))))
+ ;; two character opener on first char
+ ((and (not (zerop (logand (car (syntax-after (point)))
+ (ash 1 16))))
+ (not (zerop (logand (or (car (syntax-after (1+ (point)))) 0)
+ (ash 1 17)))))
+ (equal (point) (evil-in-comment-p (+ 2 (point)))))
+ ;; two character opener on second char
+ ((and (not (zerop (logand (car (syntax-after (point)))
+ (ash 1 17))))
+ (not (zerop (logand (or (car (syntax-after (1- (point)))) 0)
+ (ash 1 16)))))
+ (and (equal (1- (point)) (evil-in-comment-p (1+ (point))))
+ (prog1 t (when move (backward-char)))))))
+
+(defun evil-looking-at-end-comment (&optional move)
+ "Return t if point is at the end of a comment.
+Point must be on one of the opening characters of a block comment
+according to the current syntax table. Futhermore, these
+characters must been parsed as opening characters, i.e. they
+won't be considered as comment starters inside a string or
+possibly another comment. Point is moved right after the comment
+closer if MOVE is non-nil."
+ (cond
+ ;; one char closer
+ ((= (char-syntax (char-after)) ?>)
+ (and (evil-in-comment-p) ; in comment
+ (not (evil-in-comment-p (1+ (point))))
+ (prog1 t (when move (forward-char)))))
+ ;; two char closer on first char
+ ((and (not (zerop (logand (car (syntax-after (point)))
+ (ash 1 18))))
+ (not (zerop (logand (or (car (syntax-after (1+ (point)))) 0)
+ (ash 1 19)))))
+ (and (evil-in-comment-p)
+ (not (evil-in-comment-p (+ (point) 2)))
+ (prog1 t (when move (forward-char 2)))))
+ ;; two char closer on second char
+ ((and (not (zerop (logand (car (syntax-after (point)))
+ (ash 1 19))))
+ (not (zerop (logand (or (car (syntax-after (1- (point)))) 0)
+ (ash 1 18)))))
+ (and (evil-in-comment-p)
+ (not (evil-in-comment-p (1+ (point))))
+ (prog1 t (when move (forward-char)))))))
+
+(defun evil-insert-newline-above ()
+ "Insert a new line above point and place point in that line
+with regard to indentation."
+ (evil-narrow-to-field
+ (evil-move-beginning-of-line)
+ (insert (if use-hard-newlines hard-newline "\n"))
+ (forward-line -1)
+ (back-to-indentation)))
+
+(defun evil-insert-newline-below ()
+ "Insert a new line below point and place point in that line
+with regard to indentation."
+ (evil-narrow-to-field
+ (evil-move-end-of-line)
+ (insert (if use-hard-newlines hard-newline "\n"))
+ (back-to-indentation)))
+
+;;; Markers
+
+(defun evil-global-marker-p (char)
+ "Whether CHAR denotes a global marker."
+ (or (and (>= char ?A) (<= char ?Z))
+ (assq char (default-value 'evil-markers-alist))))
+
+(defun evil-set-marker (char &optional pos advance)
+ "Set the marker denoted by CHAR to position POS.
+POS defaults to the current position of point.
+If ADVANCE is t, the marker advances when inserting text at it;
+otherwise, it stays behind."
+ (interactive (list (read-char)))
+ (catch 'done
+ (let ((marker (evil-get-marker char t)) alist)
+ (unless (markerp marker)
+ (cond
+ ((eq marker 'evil-visual-beginning)
+ (setq marker evil-visual-mark))
+ ((eq marker 'evil-visual-goto-end)
+ (setq marker evil-visual-point))
+ ((and marker (symbolp marker) (boundp marker))
+ (set marker (or (symbol-value marker) (make-marker)))
+ (setq marker (symbol-value marker)))
+ ((eq marker 'evil-jump-backward-swap)
+ (evil-set-jump)
+ (throw 'done nil))
+ ((functionp marker)
+ (user-error "Cannot set special marker `%c'" char))
+ ((evil-global-marker-p char)
+ (setq alist (default-value 'evil-markers-alist)
+ marker (make-marker))
+ (evil--add-to-alist alist char marker)
+ (setq-default evil-markers-alist alist))
+ (t
+ (setq marker (make-marker))
+ (evil--add-to-alist evil-markers-alist char marker))))
+ (add-hook 'kill-buffer-hook #'evil-swap-out-markers nil t)
+ (set-marker-insertion-type marker advance)
+ (set-marker marker (or pos (point))))))
+(evil-set-command-properties #'evil-set-marker :suppress-operator t)
+
+(defun evil-get-marker (char &optional raw)
+ "Return the marker denoted by CHAR.
+This is either a marker object as returned by `make-marker',
+a number, a cons cell (FILE . POS) with FILE being a string
+and POS a number, or nil. If RAW is non-nil, then the
+return value may also be a variable, a movement function,
+or a marker object pointing nowhere."
+ (let ((marker (cdr (assq char (if (evil-global-marker-p char)
+ (default-value 'evil-markers-alist)
+ evil-markers-alist)))))
+ (if raw
+ marker
+ (when (and (symbolp marker) (boundp marker))
+ (setq marker (symbol-value marker)))
+ (when (functionp marker)
+ (save-excursion
+ (save-window-excursion
+ (funcall marker)
+ (setq marker (move-marker (make-marker) (point))))))
+ (if (markerp marker)
+ (if (eq (marker-buffer marker) (current-buffer))
+ (marker-position marker)
+ (when (marker-buffer marker) marker))
+ marker))))
+
+(defun evil-swap-out-markers ()
+ "Turn markers into file references when the buffer is killed."
+ (when buffer-file-name
+ (dolist (entry evil-markers-alist)
+ (and (markerp (cdr entry))
+ (eq (marker-buffer (cdr entry)) (current-buffer))
+ (setcdr entry (cons buffer-file-name
+ (marker-position (cdr entry))))))))
+(put 'evil-swap-out-markers 'permanent-local-hook t)
+
+(defvar calc-multiplication-has-precedence)
+(defun evil--eval-expr (input)
+ "Eval INPUT and return stringified result, if of a suitable type.
+If INPUT starts with a number, +, -, or . use `calc-eval' instead."
+ (let* ((calcable-p (string-match-p "\\`[[:space:]]*[0-9+.-]" input))
+ (result (if calcable-p
+ (let ((calc-multiplication-has-precedence nil))
+ (calc-eval input))
+ (eval (car (read-from-string input)) t))))
+ (cond
+ ((stringp result) result)
+ ((or (numberp result) (symbolp result))
+ (format "%s" result))
+ ((sequencep result)
+ (mapconcat (lambda (x) (format "%s" x)) result "\n"))
+ (t (user-error "Using `%s' as a string" (type-of result))))))
+
+(defvar evil-paste-clear-minibuffer-first nil
+ "`evil-paste-before' cannot have `delete-minibuffer-contents' called before
+it fetches certain registers becuase this would trigger various ex-updates,
+sometimes moving point, so `C-a' `C-w' etc. would miss their intended target.")
+
+(defun evil-ex-remove-default ()
+ "Remove the default text shown in the ex minibuffer.
+When Ex starts, the previous command is shown enclosed in
+parenthesis. This function removes this text when the first key
+is pressed."
+ (when (and (not (eq this-command 'exit-minibuffer))
+ (/= (minibuffer-prompt-end) (point-max)))
+ (when (eq this-command 'evil-ex-delete-backward-char)
+ (setq this-command 'ignore))
+ (if (eq this-original-command 'evil-paste-from-register)
+ (setq evil-paste-clear-minibuffer-first t)
+ (delete-minibuffer-contents)))
+ (remove-hook 'pre-command-hook #'evil-ex-remove-default t))
+
+(defun evil-get-register (register &optional noerror)
+ "Return contents of REGISTER.
+Signal an error if empty, unless NOERROR is non-nil.
+
+The following special registers are supported.
+ \" the unnamed register
+ * the clipboard contents
+ + the clipboard contents
+ <C-w> the word at point (ex mode only)
+ <C-a> the WORD at point (ex mode only)
+ <C-o> the symbol at point (ex mode only)
+ <C-f> the current file at point (ex mode only)
+ % the current file name (read only)
+ # the alternate file name (read only)
+ / the last search pattern (read only)
+ : the last command line (read only)
+ . the last inserted text (read only)
+ - the last small (less than a line) delete
+ _ the black hole register
+ = the expression register (read only)"
+ (unless (characterp register) (error "Invalid register `%S'" register))
+ (condition-case err
+ (or (cond
+ ((eq register ?\")
+ (current-kill 0))
+ ((<= ?1 register ?9)
+ (let ((reg (- register ?1)))
+ (and (< reg (length kill-ring))
+ (current-kill reg t))))
+ ((memq register '(?* ?+))
+ (let ((what (if (eq register ?*) 'PRIMARY 'CLIPBOARD)))
+ (if (eval-when-compile (>= emacs-major-version 29))
+ (gui--selection-value-internal what)
+ ;; The following code is based on `x-selection-value-internal'
+ ;; (now `gui--selection-value-internal') circa Emacs 24. We're
+ ;; unsure why exactly it's duplicated here, and it's possible
+ ;; it needn't be for newer versions of Emacs.
+ (let ((request-type (or (bound-and-true-p x-select-request-type)
+ '(UTF8_STRING COMPOUND_TEXT STRING)))
+ text)
+ (unless (consp request-type)
+ (setq request-type (list request-type)))
+ (while (and request-type (not text))
+ (setq text (ignore-errors
+ (evil-get-selection what (pop request-type)))))
+ (when text
+ (remove-text-properties 0 (length text) '(foreign-selection nil) text))
+ text))))
+ ((eq register ?\C-W)
+ (with-current-buffer
+ (or evil-ex-original-buffer
+ (let ((w (minibuffer-selected-window))) (and w (window-buffer w)))
+ (user-error "Register <C-w> is only available in Ex state"))
+ (thing-at-point 'evil-word)))
+ ((eq register ?\C-A)
+ (with-current-buffer
+ (or evil-ex-original-buffer
+ (let ((w (minibuffer-selected-window))) (and w (window-buffer w)))
+ (user-error "Register <C-a> is only available in Ex state"))
+ (thing-at-point 'evil-WORD)))
+ ((eq register ?\C-O)
+ (with-current-buffer
+ (or evil-ex-original-buffer
+ (let ((w (minibuffer-selected-window))) (and w (window-buffer w)))
+ (user-error "Register <C-o> is only available in Ex state"))
+ (thing-at-point 'evil-symbol)))
+ ((eq register ?\C-F)
+ (with-current-buffer
+ (or evil-ex-original-buffer
+ (let ((w (minibuffer-selected-window))) (and w (window-buffer w)))
+ (user-error "Register <C-f> is only available in Ex state"))
+ (thing-at-point 'filename)))
+ ((eq register ?\C-L)
+ (with-current-buffer
+ (or evil-ex-original-buffer
+ (let ((w (minibuffer-selected-window))) (and w (window-buffer w)))
+ (user-error "Register <C-l> is only available in Ex state"))
+ (replace-regexp-in-string "\n\\'" "" (thing-at-point 'line))))
+ ((eq register ?%)
+ (or (buffer-file-name
+ (or evil-ex-original-buffer
+ (let ((w (minibuffer-selected-window))) (and w (window-buffer w)))))
+ (user-error "No file name")))
+ ((= register ?#)
+ (or (with-current-buffer (other-buffer) (buffer-file-name))
+ (user-error "No file name")))
+ ((eq register ?/)
+ (defvar evil-search-module)
+ (or (car (cond
+ ((eq evil-search-module 'evil-search) evil-ex-search-history)
+ (isearch-regexp regexp-search-ring)
+ (t search-ring)))
+ (user-error "No previous regular expression")))
+ ((eq register ?:)
+ (or (car evil-ex-history) (user-error "No previous command line")))
+ ((eq register ?.) evil-last-insertion)
+ ((eq register ?-) evil-last-small-deletion)
+ ((eq register ?=)
+ (let ((enable-recursive-minibuffers t))
+ (setq evil-last-=-register-input
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (when evil-last-=-register-input
+ (add-hook 'pre-command-hook #'evil-ex-remove-default nil t)))
+ (read-from-minibuffer
+ "="
+ (and evil-last-=-register-input
+ (propertize evil-last-=-register-input 'face 'shadow))
+ evil-eval-map
+ nil
+ 'evil-eval-history
+ evil-last-=-register-input
+ t)))
+ (evil--eval-expr evil-last-=-register-input)))
+ ((eq register ?_) "") ; the black hole register
+ (t (setq register (downcase register))
+ (get-register register)))
+ (user-error "Register `%c' is empty" register))
+ (error (unless noerror (signal (car err) (cdr err))))))
+
+(defun evil-append-register (register text)
+ "Append TEXT to the contents of REGISTER."
+ (let ((content (get-register register)))
+ (set-register
+ register
+ (cond
+ ((not content) text)
+ ;; if the register does not contain a string treat it as a vector
+ ((not (stringp content)) (vconcat content text))
+ ;; some non-trivial yank-handler -> always switch to line handler
+ ((or (text-property-not-all
+ 0 (length content) 'yank-handler nil content)
+ (text-property-not-all
+ 0 (length text) 'yank-handler nil text))
+ ;; ensure complete lines
+ (setq text
+ (concat
+ content
+ (and (> (length content) 0)
+ (/= (aref content (1- (length content))) ?\n)
+ "\n")
+ text
+ (and (> (length text) 0)
+ (/= (aref text (1- (length text))) ?\n)
+ "\n")))
+ (put-text-property 0 (length text) 'yank-handler '(evil-yank-line-handler)
+ text)
+ text)
+ (t (concat content text))))))
+
+(defun evil-set-register (register text)
+ "Set the contents of REGISTER to TEXT.
+If REGISTER is an upper case character then TEXT is appended to that
+register instead of replacing its content."
+ (cond
+ ((not (characterp register)) (user-error "Invalid register"))
+ ;; don't allow modification of read-only registers
+ ((member register '(?: ?. ?%))
+ (user-error "Can't modify read-only register"))
+ ((eq register ?\") (kill-new text))
+ ((<= ?1 register ?9)
+ (if (null kill-ring)
+ (kill-new text)
+ (let ((kill-ring-yank-pointer kill-ring-yank-pointer)
+ interprogram-paste-function
+ interprogram-cut-function)
+ (current-kill (- register ?1))
+ (setcar kill-ring-yank-pointer text))))
+ ((eq register ?*) (evil-set-selection 'PRIMARY text))
+ ((eq register ?+) (evil-set-selection 'CLIPBOARD text))
+ ((eq register ?-) (setq evil-last-small-deletion text))
+ ((eq register ?_) nil) ; the black hole register
+ ((and (<= ?A register) (<= register ?Z))
+ (evil-append-register (downcase register) text))
+ (t (set-register register text))))
+
+(defun evil-register-list ()
+ "Return an alist of all registers, but only those named
+with number or character. Registers with symbol or string in names are ignored
+to keep Vim compatibility with register jumps."
+ (sort (append (mapcar (lambda (reg) (cons reg (evil-get-register reg t)))
+ '(?\" ?* ?+ ?% ?# ?/ ?: ?. ?-
+ ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
+ (list (cons ?= evil-last-=-register-input))
+ (cl-remove-if-not (lambda (reg) (number-or-marker-p (car reg))) register-alist)
+ nil)
+ #'car-less-than-car))
+
+(defsubst evil-kbd-macro-suppress-motion-error ()
+ "Return non-nil if a motion error should be suppressed.
+Whether the motion error should be suppressed depends on the
+variable `evil-kbd-macro-suppress-motion-error'."
+ (or (and defining-kbd-macro
+ (memq evil-kbd-macro-suppress-motion-error '(t record)))
+ (and executing-kbd-macro
+ (memq evil-kbd-macro-suppress-motion-error '(t replay)))))
+
+;;; Region
+
+;; `set-mark' does too much at once
+(defun evil-move-mark (pos)
+ "Set buffer's mark to POS.
+If POS is nil, delete the mark."
+ (set-marker (mark-marker) pos))
+
+(defun evil-save-transient-mark-mode ()
+ "Save Transient Mark mode and make it buffer-local.
+Any changes to Transient Mark mode are now local to the current
+buffer, until `evil-restore-transient-mark-mode' is called.
+
+Variables pertaining to Transient Mark mode are listed in
+`evil-transient-vars', and their values are stored in
+`evil-transient-vals'."
+ (dolist (var evil-transient-vars)
+ (when (and (boundp var)
+ (not (assq var evil-transient-vals)))
+ (push (list var (symbol-value var)
+ (local-variable-p var))
+ evil-transient-vals)
+ (make-variable-buffer-local var)
+ (put var 'permanent-local t))))
+
+(defun evil-restore-transient-mark-mode ()
+ "Restore Transient Mark mode.
+This presupposes that `evil-save-transient-mark-mode' has been
+called earlier. If Transient Mark mode was disabled before but
+enabled in the meantime, this function disables it; if it was
+enabled before but disabled in the meantime, this function
+enables it.
+
+The earlier settings of Transient Mark mode are stored in
+`evil-transient-vals'."
+ (let (entry local var val)
+ (while (setq entry (pop evil-transient-vals))
+ (setq var (pop entry)
+ val (pop entry)
+ local (pop entry))
+ (unless local
+ (kill-local-variable var))
+ (unless (equal (symbol-value var) val)
+ (if (fboundp var)
+ (funcall var (if val 1 -1))
+ (setq var val))))))
+
+;; In theory, an active region implies Transient Mark mode, and
+;; disabling Transient Mark mode implies deactivating the region.
+;; In practice, Emacs never clears `mark-active' except in Transient
+;; Mark mode, so we define our own toggle functions to make things
+;; more predictable.
+(defun evil-transient-mark (&optional arg)
+ "Toggle Transient Mark mode.
+Ensure that the region is properly deactivated.
+Enable with positive ARG, disable with negative ARG."
+ (unless (numberp arg)
+ (setq arg (if transient-mark-mode -1 1)))
+ (cond
+ ((< arg 1)
+ (evil-active-region -1)
+ ;; Transient Mark mode cannot be disabled
+ ;; while CUA mode is enabled
+ (when (fboundp 'cua-mode)
+ (cua-mode -1))
+ (when transient-mark-mode
+ (transient-mark-mode -1)))
+ (t
+ (unless transient-mark-mode
+ (evil-active-region -1)
+ (transient-mark-mode 1)))))
+
+(defun evil-active-region (&optional arg)
+ "Toggle active region.
+Ensure that Transient Mark mode is properly enabled.
+Enable with positive ARG, disable with negative ARG."
+ (unless (numberp arg)
+ (setq arg (if (region-active-p) -1 1)))
+ (cond
+ ((and (< arg 1))
+ (when (or transient-mark-mode mark-active)
+ (setq mark-active nil
+ deactivate-mark nil)
+ (when (boundp 'cua--explicit-region-start)
+ (setq cua--explicit-region-start nil))
+ (run-hooks 'deactivate-mark-hook)))
+ (t
+ (evil-transient-mark 1)
+ (when deactivate-mark
+ (setq deactivate-mark nil))
+ (unless (mark t)
+ (evil-move-mark (point)))
+ (unless (region-active-p)
+ (set-mark (mark t)))
+ (when (boundp 'cua--explicit-region-start)
+ (setq cua--explicit-region-start t)))))
+
+(defmacro evil-with-transient-mark-mode (&rest body)
+ "Execute BODY with Transient Mark mode.
+Then restore Transient Mark mode to its previous setting."
+ (declare (indent defun)
+ (debug t))
+ `(let ((inhibit-quit t)
+ evil-transient-vals)
+ (unwind-protect
+ (progn
+ (evil-save-transient-mark-mode)
+ (evil-transient-mark 1)
+ ,@body)
+ (evil-restore-transient-mark-mode))))
+
+(defmacro evil-with-active-region (beg end &rest body)
+ "Execute BODY with an active region from BEG to END."
+ (declare (indent 2)
+ (debug t))
+ `(let ((beg ,beg) (end ,end)
+ evil-transient-vals)
+ (evil-with-transient-mark-mode
+ (save-excursion
+ (evil-active-region 1)
+ (evil-move-mark beg)
+ (goto-char end)
+ ,@body))))
+
+(defun evil-exchange-point-and-mark ()
+ "Exchange point and mark without activating the region."
+ (let* ((point (point))
+ (mark (or (mark t) point)))
+ (set-marker (mark-marker) point)
+ (goto-char mark)))
+
+(defun evil-apply-on-block (func beg end pass-columns &rest args)
+ "Call FUNC for each line of a block selection.
+The selection is specified by the region BEG and END. FUNC must
+take at least two arguments, the beginning and end of each
+line. If PASS-COLUMNS is non-nil, these values are the columns,
+otherwise they are buffer positions. Extra arguments to FUNC may
+be passed via ARGS."
+ (let (startcol startpt endcol endpt)
+ (save-excursion
+ (goto-char beg)
+ (setq startcol (current-column)
+ startpt (line-beginning-position))
+ (goto-char end)
+ (setq endcol (current-column))
+ (forward-line 1)
+ (setq endpt (point-marker))
+ ;; ensure the start column is the left one.
+ (evil-sort startcol endcol)
+ ;; maybe extend up to EOL
+ (when (and (memq last-command '(next-line previous-line evil-use-register))
+ (eq temporary-goal-column most-positive-fixnum))
+ (goto-char startpt)
+ (while (< (point) endpt)
+ (setq endcol (max endcol (evil-column (line-end-position))))
+ (forward-line 1)))
+ ;; start looping over lines
+ (goto-char startpt)
+ (while (< (point) endpt)
+ (if pass-columns
+ (apply func startcol endcol args)
+ (apply func
+ (save-excursion (evil-move-to-column startcol))
+ (save-excursion (evil-move-to-column endcol t))
+ args))
+ (forward-line 1)))))
+
+(defun evil-apply-on-rectangle (function start end &rest args)
+ "Like `apply-on-rectangle' but maybe extends to eol.
+If `temporary-goal-column' is set to a big number, then the
+region of each line is extended to the end of each line. The end
+column is set to the maximal column in all covered lines."
+ (apply #'evil-apply-on-block function start end t args))
+
+;;; Insertion
+
+(defun evil-track-last-insertion (beg end old-len)
+ "Track the last insertion range and its text.
+BEG, END and OLD-LEN are as for `after-change-functions'.
+The insertion range is stored as a pair of buffer positions in
+`evil-current-insertion'."
+ ;; For deletions left of, or insertions right of the end of the last
+ ;; insertion (with any changes in between), extend or contract the
+ ;; insertion range as appropriate. Otherwise, start a new range.
+ (if (when evil-current-insertion
+ (let ((ins-beg (car evil-current-insertion))
+ (ins-end (cdr evil-current-insertion)))
+ (and (<= ins-beg beg)
+ (or (= (+ beg old-len) ins-end)
+ (when (evil-replace-state-p) (= beg ins-end))))))
+ ;; Ignore insertion of previous char from Backspace in Replace state
+ (unless (and (eq this-command 'evil-replace-backspace) (= old-len 0))
+ (setcdr evil-current-insertion end))
+ (setq evil-current-insertion (cons beg end))))
+(put 'evil-track-last-insertion 'permanent-local-hook t)
+
+(defun evil-start-track-last-insertion ()
+ "Start tracking the last insertion."
+ (setq evil-current-insertion nil)
+ (add-hook 'after-change-functions #'evil-track-last-insertion nil t))
+
+(defun evil-stop-track-last-insertion ()
+ "Stop tracking the last insertion.
+The tracked insertion is set to `evil-last-insertion'."
+ (setq evil-last-insertion
+ (and evil-current-insertion
+ ;; Check whether the insertion range is a valid buffer
+ ;; range. If a buffer modification is done from within
+ ;; another change hook or modification-hook (yasnippet
+ ;; does this using overlay modification-hooks), then the
+ ;; insertion information may be invalid. There is no way
+ ;; to detect this situation, but at least we should
+ ;; ensure that no error occurs (see bug #272).
+ (>= (car evil-current-insertion) (point-min))
+ (<= (cdr evil-current-insertion) (point-max))
+ (buffer-substring-no-properties (car evil-current-insertion)
+ (cdr evil-current-insertion))))
+ (remove-hook 'after-change-functions #'evil-track-last-insertion t))
+
+;;; Paste
+
+(defun evil-yank-characters (beg end &optional register yank-handler)
+ "Save the characters defined by the region BEG and END in the kill-ring."
+ (let ((text (filter-buffer-substring beg end)))
+ (when yank-handler
+ (put-text-property 0 (length text) 'yank-handler (list yank-handler) text))
+ (when register
+ (evil-set-register register text))
+ (when evil-was-yanked-without-register
+ (evil-set-register ?0 text)) ; "0 register contains last yanked text
+ (unless (eq register ?_)
+ (kill-new text))))
+
+(defun evil-yank-lines (beg end &optional register yank-handler)
+ "Save the lines in the region BEG and END into the kill-ring."
+ (let ((text (filter-buffer-substring beg end))
+ (yank-handler (list (or yank-handler #'evil-yank-line-handler)
+ nil
+ t)))
+ ;; Ensure the text ends with a newline. This is required
+ ;; if the deleted lines were the last lines in the buffer.
+ (when (or (zerop (length text))
+ (/= (aref text (1- (length text))) ?\n))
+ (setq text (concat text "\n")))
+ (put-text-property 0 (length text) 'yank-handler yank-handler text)
+ (when register
+ (evil-set-register register text))
+ (when evil-was-yanked-without-register
+ (evil-set-register ?0 text)) ; "0 register contains last yanked text
+ (unless (eq register ?_)
+ (kill-new text))))
+
+(defun evil-yank-rectangle (beg end &optional register yank-handler)
+ "Save the rectangle defined by region BEG and END into the kill-ring."
+ (let ((lines (list nil)))
+ (evil-apply-on-rectangle #'extract-rectangle-line beg end lines)
+ ;; We remove spaces from the beginning and the end of the next.
+ ;; Spaces are inserted explicitly in the yank-handler in order to
+ ;; NOT insert lines full of spaces.
+ (setq lines (nreverse (cdr lines)))
+ ;; `text' is used as default insert text when pasting this rectangle
+ ;; in another program, e.g., using the X clipboard.
+ (let ((yank-handler (list (or yank-handler #'evil-yank-block-handler)
+ lines
+ t
+ #'evil-delete-yanked-rectangle))
+ (text (mapconcat #'identity lines "\n")))
+ (put-text-property 0 (length text) 'yank-handler yank-handler text)
+ (when register
+ (evil-set-register register text))
+ (when evil-was-yanked-without-register
+ (evil-set-register ?0 text)) ; "0 register contains last yanked text
+ (unless (eq register ?_)
+ (kill-new text))
+ text)))
+
+(defun evil-remove-yank-excluded-properties (text)
+ "Remove `yank-excluded-properties' from TEXT."
+ (if (eq yank-excluded-properties t)
+ (set-text-properties 0 (length text) nil text)
+ (remove-list-of-text-properties 0 (length text)
+ yank-excluded-properties text)))
+
+(defun evil-yank-line-handler (text)
+ "Insert the current text linewise."
+ (let ((text (apply #'concat (make-list (or evil-paste-count 1) text)))
+ (opoint (point)))
+ (evil-remove-yank-excluded-properties text)
+ (cond
+ ((eq this-command 'evil-paste-before)
+ (evil-move-beginning-of-line)
+ (let ((beg (point)))
+ (insert text)
+ (setq evil-last-paste
+ (list 'evil-paste-before evil-paste-count opoint beg (point)))
+ (evil-set-marker ?\[ beg)
+ (evil-set-marker ?\] (1- (point)))
+ (goto-char beg))
+ (back-to-indentation))
+ ((eq this-command 'evil-paste-after)
+ (evil-move-end-of-line)
+ (let ((beg (point)))
+ (insert "\n")
+ (insert text)
+ (delete-char -1) ; delete the last newline
+ (setq evil-last-paste
+ (list 'evil-paste-after evil-paste-count opoint beg (point)))
+ (evil-set-marker ?\[ (1+ beg))
+ (evil-set-marker ?\] (point))
+ (unless evil--cursor-after
+ (goto-char (1+ beg))))
+ (back-to-indentation))
+ (t (insert text)))))
+
+(defun evil-yank-block-handler (lines)
+ "Insert the current text as block."
+ (let* ((count (or evil-paste-count 1))
+ shifted-forward
+ (col (if (and (eq this-command 'evil-paste-after)
+ (not (and (bolp) (eolp)))
+ (setq shifted-forward t))
+ (1+ (current-column))
+ (current-column)))
+ (opoint (point))
+ (first t))
+ (dolist (line lines)
+ ;; maybe we have to insert a new line at eob
+ (if first
+ (setq first nil)
+ (when (or (> (forward-line 1) 0)
+ (and (eobp) (not (bolp))))
+ (insert "\n")))
+ ;; concat multiple copies according to count
+ (setq line (apply #'concat (make-list count line)))
+ ;; trim whitespace at beginning and end
+ (string-match "\\` *\\(.*?\\) *\\'" line)
+ (let ((text (match-string 1 line))
+ (begextra (match-beginning 1))
+ (endextra (- (match-end 0) (match-end 1))))
+ ;; insert text unless we insert an empty line behind eol
+ (unless (and (< (evil-column (line-end-position)) col)
+ (string= text ""))
+ ;; if we paste behind eol, it may be sufficient to insert tabs
+ (if (< (evil-column (line-end-position)) col)
+ (move-to-column (+ col begextra) t)
+ (move-to-column col t)
+ (insert (make-string begextra ?\s)))
+ (evil-remove-yank-excluded-properties text)
+ (insert text)
+ (unless (eolp)
+ ;; text follows, so we have to insert spaces
+ (insert (make-string endextra ?\s))))))
+ (setq evil-last-paste
+ (list this-command
+ evil-paste-count
+ opoint
+ (length lines) ; number of rows
+ (* count (length (car lines))))) ; number of columns
+ (evil-set-marker ?\[ opoint)
+ (evil-set-marker ?\] (1- (point)))
+ (if evil--cursor-after
+ (backward-char)
+ (goto-char opoint)
+ (when shifted-forward (forward-char)))))
+
+(defun evil-delete-yanked-rectangle (nrows ncols)
+ "Special function to delete the block yanked by a previous paste command.
+Supplied as the `undo' element of a yank handler."
+ (let ((opoint (point))
+ (col (if (eq last-command 'evil-paste-after)
+ (1+ (current-column))
+ (current-column))))
+ (dotimes (_ nrows)
+ (delete-region (save-excursion
+ (move-to-column col)
+ (point))
+ (save-excursion
+ (move-to-column (+ col ncols))
+ (point)))
+ (unless (eobp) (forward-line)))
+ (goto-char opoint)))
+
+;; TODO: if undoing is disabled in the current buffer, paste-pop won't
+;; work. Although this is probably not a big problem, because usually
+;; buffers where `evil-paste-pop' may be useful have undoing enabled.
+;; A solution would be to temporarily enable undo when pasting and
+;; store the undo information in a special variable that does not
+;; interfere with `buffer-undo-list'.
+(defun evil-paste-pop (count)
+ "Replace the just-yanked stretch of killed text with a different stretch.
+This command is allowed only immediatly after a `yank',
+`evil-paste-before', `evil-paste-after' or `evil-paste-pop'.
+This command uses the same paste command as before, i.e., when
+used after `evil-paste-after' the new text is also yanked using
+`evil-paste-after', used with the same paste-count argument.
+
+The COUNT argument inserts the COUNTth previous kill. If COUNT
+is negative this is a more recent kill."
+ (interactive "p")
+ (unless (memq last-command
+ '(evil-paste-after
+ evil-paste-before
+ evil-visual-paste))
+ (user-error "Previous command was not an evil-paste: %s" last-command))
+ (unless evil-last-paste
+ (user-error "Previous paste command used a register"))
+ (evil-undo-pop)
+ (goto-char (nth 2 evil-last-paste))
+ (setq this-command (nth 0 evil-last-paste))
+ ;; use temporary kill-ring, so the paste cannot modify it
+ (let ((kill-ring (list (current-kill
+ (if (and (> count 0) (nth 5 evil-last-paste))
+ ;; if was visual paste then skip the
+ ;; text that has been replaced
+ (1+ count)
+ count))))
+ (kill-ring-yank-pointer kill-ring))
+ (when (eq last-command 'evil-visual-paste)
+ (let ((evil-no-display t))
+ (evil-visual-restore)))
+ (funcall (nth 0 evil-last-paste) (nth 1 evil-last-paste))
+ ;; if this was a visual paste, then mark the last paste as NOT
+ ;; being the first visual paste
+ (when (eq last-command 'evil-visual-paste)
+ (setcdr (nthcdr 4 evil-last-paste) nil))))
+
+(defun evil-paste-pop-next (count)
+ "Same as `evil-paste-pop' but with negative argument."
+ (interactive "p")
+ (evil-paste-pop (- count)))
+
+;;; Interactive forms
+
+(defun evil-match-interactive-code (interactive &optional pos)
+ "Match an interactive code at position POS in string INTERACTIVE.
+Return the first matching entry in `evil-interactive-alist', or nil."
+ (unless pos (setq pos 0))
+ (cl-loop
+ with len = (length interactive) for entry in evil-interactive-alist thereis
+ (let* ((string (car entry))
+ (end (+ pos (length string))))
+ (and (<= end len)
+ (eq (compare-strings string nil nil interactive pos end) t)
+ entry))))
+
+(defun evil-concatenate-interactive-forms (&rest forms)
+ "Concatenate interactive list expressions FORMS.
+Return a single expression where successive expressions
+are joined, if possible."
+ (let (result)
+ (when forms
+ (while (cdr forms)
+ (cond
+ ((null (car forms))
+ (pop forms))
+ ((and (eq (car (car forms)) 'list)
+ (eq (car (cadr forms)) 'list))
+ (setq forms (cons (append (car forms)
+ (cdr (cadr forms)))
+ (cdr (cdr forms)))))
+ (t (push (pop forms) result))))
+ (when (car forms)
+ (push (pop forms) result))
+ (setq result (nreverse result))
+ (cond
+ ((null result))
+ ((null (cdr result)) (car result))
+ (t `(append ,@result))))))
+
+(defun evil-interactive-string (string)
+ "Evaluate the interactive string STRING.
+The string may contain extended interactive syntax.
+The return value is a cons cell (FORM . PROPERTIES),
+where FORM is a single list-expression to be passed to
+a standard `interactive' statement, and PROPERTIES is a
+list of command properties as passed to `evil-define-command'."
+ (let ((len (length string))
+ (pos 0)
+ forms properties)
+ (while (< pos len)
+ (if (eq (aref string pos) ?\n)
+ (setq pos (1+ pos))
+ (cl-destructuring-bind (code expr . plist)
+ (or (evil-match-interactive-code string pos)
+ (user-error "Unknown interactive code: `%s'"
+ (substring string pos)))
+ (setq pos (+ pos (length code)))
+ (when (functionp expr)
+ (let ((prompt (substring
+ string pos
+ (or (string-match-p "\n" string pos) len))))
+ (setq pos (+ pos (length prompt))
+ expr `(funcall ,expr ,prompt))))
+ (setq forms (append forms (list expr))
+ properties (append properties plist)))))
+ (cons `(append ,@forms) properties)))
+
+(defun evil-interactive-form (&rest args)
+ "Evaluate interactive forms ARGS.
+The return value is a cons cell (FORM . PROPERTIES),
+where FORM is a single list-expression to be passed to
+a standard `interactive' statement, and PROPERTIES is a
+list of command properties as passed to `evil-define-command'."
+ (let (forms properties)
+ (dolist (arg args)
+ (if (not (stringp arg))
+ (setq forms (append forms (list arg)))
+ (setq arg (evil-interactive-string arg)
+ forms (append forms (cdr (car arg)))
+ properties (append properties (cdr arg)))))
+ (cons (apply #'evil-concatenate-interactive-forms forms)
+ properties)))
+
+;;; Types
+
+(defun evil-type (object &optional default)
+ "Return the type of OBJECT, or DEFAULT if none."
+ (let (type)
+ (cond
+ ((overlayp object)
+ (setq type (overlay-get object :type)))
+ ((evil-range-p object)
+ (setq type (nth 2 object)))
+ ((listp object)
+ (setq type (plist-get object :type)))
+ ((commandp object)
+ (setq type (evil-get-command-property object :type)))
+ ((symbolp object)
+ (setq type (get object 'type))))
+ (setq type (or type default))
+ (and (evil-type-p type) type)))
+
+(defun evil-set-type (object type)
+ "Set the type of OBJECT to TYPE.
+For example, (evil-set-type \\='next-line \\='line)
+will make `line' the type of the `next-line' command."
+ (cond
+ ((overlayp object)
+ (overlay-put object :type type))
+ ((evil-range-p object)
+ (evil-set-range-type object type))
+ ((listp object)
+ (plist-put object :type type))
+ ((commandp object)
+ (evil-set-command-property object :type type))
+ ((symbolp object)
+ (put object 'type type)))
+ object)
+
+(defun evil-type-property (type prop)
+ "Return property PROP for TYPE."
+ (plist-get (cdr (assq type evil-type-properties)) prop))
+
+(defun evil-type-p (sym)
+ "Whether SYM is the name of a type."
+ (assq sym evil-type-properties))
+
+(defun evil-expand (beg end type &rest properties)
+ "Expand BEG and END as TYPE with PROPERTIES.
+Return a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list."
+ (apply #'evil-transform
+ ;; don't expand if already expanded
+ (unless (plist-get properties :expanded) :expand)
+ beg end type properties))
+
+(defun evil-contract (beg end type &rest properties)
+ "Contract BEG and END as TYPE with PROPERTIES.
+Return a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list."
+ (apply #'evil-transform :contract beg end type properties))
+
+(defun evil-normalize (beg end type &rest properties)
+ "Normalize BEG and END as TYPE with PROPERTIES.
+Return a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list."
+ (apply #'evil-transform :normalize beg end type properties))
+
+(defun evil-transform (transform beg end type &rest properties)
+ "Apply TRANSFORM on BEG and END with PROPERTIES.
+Return a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list. If TRANSFORM is undefined,
+return positions unchanged."
+ (let* ((type (or type (evil-type properties)))
+ (transform (when (and type transform)
+ (evil-type-property type transform))))
+ (if transform
+ (apply transform beg end properties)
+ (apply #'evil-range beg end type properties))))
+
+(defun evil-describe (beg end type &rest properties)
+ "Return description of BEG and END with PROPERTIES.
+If no description is available, return the empty string."
+ (let* ((type (or type (evil-type properties)))
+ (properties (plist-put properties :type type))
+ (describe (evil-type-property type :string)))
+ (or (when describe
+ (apply describe beg end properties))
+ "")))
+
+;;; Ranges
+
+(defun evil-range (beg end &optional type &rest properties)
+ "Return a list (BEG END [TYPE] PROPERTIES...).
+BEG and END are buffer positions (numbers or markers),
+TYPE is a type as per `evil-type-p', and PROPERTIES is
+a property list."
+ (let ((beg (evil-normalize-position beg))
+ (end (evil-normalize-position end)))
+ (when (and (numberp beg) (numberp end))
+ (evil-sort beg end)
+ (nconc (list beg end)
+ (when (evil-type-p type) (list type))
+ properties))))
+
+(defun evil-range-p (object)
+ "Whether OBJECT is a range."
+ (and (listp object)
+ (numberp (nth 0 object))
+ (numberp (nth 1 object))))
+
+(defun evil-range-beginning (range)
+ "Return beginning of RANGE."
+ (when (evil-range-p range)
+ (let ((beg (evil-normalize-position (nth 0 range)))
+ (end (evil-normalize-position (nth 1 range))))
+ (min beg end))))
+
+(defun evil-range-end (range)
+ "Return end of RANGE."
+ (when (evil-range-p range)
+ (let ((beg (evil-normalize-position (nth 0 range)))
+ (end (evil-normalize-position (nth 1 range))))
+ (max beg end))))
+
+(defun evil-range-properties (range)
+ "Return properties of RANGE."
+ (when (evil-range-p range)
+ (nthcdr (if (evil-type range) 3 2) range)))
+
+(defalias 'evil-copy-range #'copy-sequence
+ "Return a copy of RANGE.")
+
+(defun evil-set-range (range &optional beg end type &rest properties)
+ "Set RANGE to have beginning BEG and end END.
+The TYPE and additional PROPERTIES may also be specified.
+If an argument is nil, it's not used; the previous value is retained.
+See also `evil-set-range-beginning', `evil-set-range-end',
+`evil-set-range-type' and `evil-set-range-properties'."
+ (when (evil-range-p range)
+ (let ((beg (or (evil-normalize-position beg)
+ (evil-range-beginning range)))
+ (end (or (evil-normalize-position end)
+ (evil-range-end range)))
+ (type (or type (evil-type range)))
+ (plist (evil-range-properties range)))
+ (evil-sort beg end)
+ (setq plist (evil-concat-plists plist properties))
+ (evil-set-range-beginning range beg)
+ (evil-set-range-end range end)
+ (evil-set-range-type range type)
+ (evil-set-range-properties range plist)
+ range)))
+
+(defun evil-set-range-beginning (range beg &optional copy)
+ "Set RANGE's beginning to BEG.
+If COPY is non-nil, return a copy of RANGE."
+ (when copy
+ (setq range (evil-copy-range range)))
+ (setcar range beg)
+ range)
+
+(defun evil-set-range-end (range end &optional copy)
+ "Set RANGE's end to END.
+If COPY is non-nil, return a copy of RANGE."
+ (when copy
+ (setq range (evil-copy-range range)))
+ (setcar (cdr range) end)
+ range)
+
+(defun evil-set-range-type (range type &optional copy)
+ "Set RANGE's type to TYPE.
+If COPY is non-nil, return a copy of RANGE."
+ (when copy
+ (setq range (evil-copy-range range)))
+ (if type
+ (setcdr (cdr range)
+ (cons type (evil-range-properties range)))
+ (setcdr (cdr range) (evil-range-properties range)))
+ range)
+
+(defun evil-set-range-properties (range properties &optional copy)
+ "Set RANGE's properties to PROPERTIES.
+If COPY is non-nil, return a copy of RANGE."
+ (when copy
+ (setq range (evil-copy-range range)))
+ (setcdr (if (evil-type range) (cddr range) (cdr range)) properties)
+ range)
+
+(defun evil-range-union (range1 range2 &optional type)
+ "Return the union of the ranges RANGE1 and RANGE2.
+If the ranges have conflicting types, use RANGE1's type.
+This can be overridden with TYPE."
+ (when (and (evil-range-p range1)
+ (evil-range-p range2))
+ (evil-range (min (evil-range-beginning range1)
+ (evil-range-beginning range2))
+ (max (evil-range-end range1)
+ (evil-range-end range2))
+ (or type
+ (evil-type range1)
+ (evil-type range2)))))
+
+(defun evil-subrange-p (range1 range2)
+ "Whether RANGE1 is contained within RANGE2."
+ (and (evil-range-p range1)
+ (evil-range-p range2)
+ (<= (evil-range-beginning range2)
+ (evil-range-beginning range1))
+ (>= (evil-range-end range2)
+ (evil-range-end range1))))
+
+(defun evil-select-inner-object (thing beg end type &optional count line)
+ "Return an inner text object range of COUNT objects.
+If COUNT is positive, return objects following point; if COUNT is
+negative, return objects preceding point. If one is unspecified,
+the other is used with a negative argument. THING is a symbol
+understood by `thing-at-point'. BEG, END and TYPE specify the
+current selection. If LINE is non-nil, the text object should be
+linewise, otherwise it is character wise."
+ (let* ((count (or count 1))
+ (bnd (or (let ((b (bounds-of-thing-at-point thing)))
+ (and b (< (point) (cdr b)) b))
+ (evil-bounds-of-not-thing-at-point thing)
+ (cons (point-min) (point-max)))))
+ ;; check if current object is selected
+ (when (or (not beg) (not end)
+ (> beg (car bnd))
+ (< end (cdr bnd))
+ (and (eq type 'inclusive)
+ (= (1+ beg) end))) ; empty region does not count
+ (when (or (not beg) (< (car bnd) beg)) (setq beg (car bnd)))
+ (when (or (not end) (> (cdr bnd) end)) (setq end (cdr bnd)))
+ (setq count (if (> count 0) (1- count) (1+ count))))
+ (goto-char (if (< count 0) beg end))
+ (evil-forward-nearest count
+ #'(lambda (cnt) (forward-thing thing cnt))
+ #'(lambda (cnt) (evil-forward-not-thing thing cnt)))
+ (evil-range (if (>= count 0) beg (point))
+ (if (< count 0) end (point))
+ (if line 'line type)
+ :expanded t)))
+
+(defun evil-select-inner-restricted-object (thing beg end type &optional count line)
+ "Return an inner text object range of COUNT objects.
+Selection is restricted to the current line, unless it is empty.
+If COUNT is positive, return objects following point; if COUNT is
+negative, return objects preceding point. If one is unspecified,
+the other is used with a negative argument. THING is a symbol
+understood by `thing-at-point'. BEG, END and TYPE specify the
+current selection. If LINE is non-nil, the text object should be
+linewise, otherwise it is character wise."
+ (save-restriction
+ (let ((start (line-beginning-position))
+ (end (line-end-position)))
+ (unless (= start end)
+ (narrow-to-region start end)))
+ (evil-select-inner-object thing beg end type count line)))
+
+(defun evil-select-an-object (thing beg end type count &optional line)
+ "Return an outer text object range of COUNT objects.
+If COUNT is positive, return objects following point; if COUNT is
+negative, return objects preceding point. If one is unspecified,
+the other is used with a negative argument. THING is a symbol
+understood by thing-at-point. BEG, END and TYPE specify the
+current selection. If LINE is non-nil, the text object should be
+linewise, otherwise it is character wise."
+ (let* ((dir (if (> (or count 1) 0) +1 -1))
+ (count (abs (or count 1)))
+ (objbnd (let ((b (bounds-of-thing-at-point thing)))
+ (and b (< (point) (cdr b)) b)))
+ (bnd (or objbnd
+ (evil-bounds-of-not-thing-at-point thing)
+ (cons (point-min) (point-max))))
+ addcurrent other)
+ ;; check if current object is not selected
+ (when (or (not beg) (not end)
+ (> beg (car bnd))
+ (< end (cdr bnd))
+ (and (eq type 'inclusive)
+ (= (1+ beg) end))) ; empty region does not count
+ ;; if not, enlarge selection
+ (when (or (not beg) (< (car bnd) beg)) (setq beg (car bnd)))
+ (when (or (not end) (> (cdr bnd) end)) (setq end (cdr bnd)))
+ (if objbnd (setq addcurrent t)))
+ ;; make other and (point) reflect the selection
+ (cond
+ ((> dir 0) (goto-char end) (setq other beg))
+ (t (goto-char beg) (setq other end)))
+ (cond
+ ;; do nothing more than only current is selected
+ ((not (and (= beg (car bnd)) (= end (cdr bnd)))))
+ ;; current match is thing, add whitespace
+ (objbnd
+ (let ((wsend (evil-with-restriction
+ ;; restrict to current line if we do non-line selection
+ (unless line (line-beginning-position))
+ (unless line (line-end-position))
+ (evil-bounds-of-not-thing-at-point thing dir))))
+ (cond
+ (wsend
+ ;; add whitespace at end
+ (goto-char wsend)
+ (setq addcurrent t))
+ (t
+ ;; no whitespace at end, try beginning
+ (save-excursion
+ (goto-char other)
+ (setq wsend
+ (evil-with-restriction
+ ;; restrict to current line if we do non-line selection
+ (unless line
+ (if (member thing '(evil-word evil-WORD))
+ (save-excursion (back-to-indentation) (point))
+ (line-beginning-position)))
+ (unless line (line-end-position))
+ (evil-bounds-of-not-thing-at-point thing (- dir))))
+ (when wsend (setq other wsend addcurrent t)))))))
+ ;; current match is whitespace, add thing
+ (t
+ (forward-thing thing dir)
+ (setq addcurrent t)))
+ ;; possibly count current object as selection
+ (if addcurrent (setq count (1- count)))
+ ;; move
+ (dotimes (_ count)
+ (let ((wsend (evil-bounds-of-not-thing-at-point thing dir)))
+ (if (and wsend (/= wsend (point)))
+ ;; start with whitespace
+ (forward-thing thing dir)
+ ;; start with thing
+ (forward-thing thing dir)
+ (setq wsend (evil-bounds-of-not-thing-at-point thing dir))
+ (when wsend (goto-char wsend)))))
+ ;; return range
+ (evil-range (if (> dir 0) other (point))
+ (if (< dir 0) other (point))
+ (if line 'line type)
+ :expanded t)))
+
+(defun evil-select-a-restricted-object (thing beg end type &optional count line)
+ "Return an outer text object range of COUNT objects.
+Selection is restricted to the current line, unless it is empty.
+If COUNT is positive, return objects following point; if COUNT is
+negative, return objects preceding point. If one is unspecified,
+the other is used with a negative argument. THING is a symbol
+understood by thing-at-point. BEG, END and TYPE specify the
+current selection. If LINE is non-nil, the text object should be
+linewise, otherwise it is character wise."
+ (save-restriction
+ (let ((start (line-beginning-position))
+ (end (line-end-position)))
+ (when (/= start end)
+ (narrow-to-region start end)))
+ (evil-select-an-object thing beg end type count line)))
+
+(defun evil--get-block-range (op cl selection-type)
+ "Return the exclusive range of a visual selection.
+OP and CL are pairs of buffer positions for the opening and
+closing delimiter of a range. SELECTION-TYPE is the desired type
+of selection. It is a symbol that determines which parts of the
+block are selected. If it is `inclusive' or t the returned range
+is \(cons (car OP) (cdr CL)). If it is `exclusive' or nil the
+returned range is (cons (cdr OP) (car CL)). If it is
+`exclusive-line' the returned range will skip whitespace at the
+end of the line of OP and at the beginning of the line of CL."
+ (cond
+ ((memq selection-type '(inclusive t)) (cons (car op) (cdr cl)))
+ ((memq selection-type '(exclusive nil)) (cons (cdr op) (car cl)))
+ ((eq selection-type 'exclusive-line)
+ (let ((beg (cdr op))
+ (end (car cl)))
+ (save-excursion
+ (goto-char beg)
+ (when (and (eolp) (not (eobp)))
+ (setq beg (line-beginning-position 2)))
+ (goto-char end)
+ (skip-chars-backward " \t")
+ (when (bolp)
+ (setq end (point))
+ (goto-char beg)
+ (when (and (not (bolp)) (< beg end))
+ (setq end (1- end)))))
+ (cons beg end)))
+ (t (user-error "Unknown selection-type `%s'" selection-type))))
+
+(defun evil-select-block (thing beg end type count
+ &optional
+ selection-type
+ countcurrent
+ fixedscan)
+ "Return a range (BEG END) of COUNT delimited text objects.
+BEG END TYPE are the currently selected (visual) range. The
+delimited object must be given by THING-up function (see
+`evil-up-block').
+
+SELECTION-TYPE is symbol that determines which parts of the block
+are selected. If it is `inclusive' or t OPEN and CLOSE are
+included in the range. If it is `exclusive' or nil the delimiters
+are not contained. If it is `exclusive-line' the delimiters are
+not included as well as adjacent whitespace until the beginning
+of the next line or the end of the previous line. If the
+resulting selection consists of complete lines only and visual
+state is not active, the returned selection is linewise.
+
+If COUNTCURRENT is non-nil an objected is counted if the current
+selection matches that object exactly.
+
+Usually scanning for the surrounding block starts at (1+ beg)
+and (1- end). If this might fail due to the behavior of THING
+then FIXEDSCAN can be set to t. In this case the scan starts at
+BEG and END. One example where this might fail is if BEG and END
+are the delimiters of a string or comment."
+ (save-excursion
+ (save-match-data
+ (let* ((orig-beg beg)
+ (orig-end end)
+ (beg (or beg (point)))
+ (end (or end (point)))
+ (count (abs (or count 1)))
+ op cl op-end cl-end)
+ ;; We always assume at least one selected character.
+ (if (= beg end) (setq end (1+ end)))
+ ;; We scan twice: starting at (1+ beg) forward and at (1- end)
+ ;; backward. The resulting selection is the smaller one.
+ (goto-char (if fixedscan beg (1+ beg)))
+ (when (and (zerop (funcall thing +1)) (match-beginning 0))
+ (setq cl (cons (match-beginning 0) (match-end 0)))
+ (goto-char (car cl))
+ (when (and (zerop (funcall thing -1)) (match-beginning 0))
+ (setq op (cons (match-beginning 0) (match-end 0)))))
+ ;; start scanning from end
+ (goto-char (if fixedscan end (1- end)))
+ (when (and (zerop (funcall thing -1)) (match-beginning 0))
+ (setq op-end (cons (match-beginning 0) (match-end 0)))
+ (goto-char (cdr op-end))
+ (when (and (zerop (funcall thing +1)) (match-beginning 0))
+ (setq cl-end (cons (match-beginning 0) (match-end 0)))))
+ ;; Bug #607: use the tightest selection that contains the
+ ;; original selection. If non selection contains the original,
+ ;; use the larger one.
+ (cond
+ ((and (not op) (not cl-end))
+ (error "No surrounding delimiters found"))
+ ((or (not op) ; first not found
+ (and cl-end ; second found
+ (>= (car op-end) (car op)) ; second smaller
+ (<= (cdr cl-end) (cdr cl))
+ (<= (car op-end) beg) ; second contains orig
+ (>= (cdr cl-end) end)))
+ (setq op op-end cl cl-end)))
+ (setq op-end op cl-end cl) ; store copy
+ ;; if the current selection contains the surrounding
+ ;; delimiters, they do not count as new selection
+ (let ((cnt (if (and orig-beg orig-end (not countcurrent))
+ (let ((sel (evil--get-block-range op cl selection-type)))
+ (if (and (<= orig-beg (car sel))
+ (>= orig-end (cdr sel)))
+ count
+ (1- count)))
+ (1- count))))
+ ;; starting from the innermost surrounding delimiters
+ ;; increase selection
+ (when (> cnt 0)
+ (setq op (progn
+ (goto-char (car op-end))
+ (funcall thing (- cnt))
+ (if (match-beginning 0)
+ (cons (match-beginning 0) (match-end 0))
+ op))
+ cl (progn
+ (goto-char (cdr cl-end))
+ (funcall thing cnt)
+ (if (match-beginning 0)
+ (cons (match-beginning 0) (match-end 0))
+ cl)))))
+ (let ((sel (evil--get-block-range op cl selection-type)))
+ (setq op (car sel)
+ cl (cdr sel)))
+ (cond
+ ((and (equal op orig-beg) (equal cl orig-end)
+ (or (not countcurrent) (/= count 1)))
+ (error "No surrounding delimiters found"))
+ ((save-excursion
+ (and (not (evil-visual-state-p))
+ (eq type 'inclusive)
+ (progn (goto-char op) (bolp))
+ (progn (goto-char cl) (bolp))))
+ (evil-range op cl 'line :expanded t))
+ (t (evil-range op cl type :expanded t)))))))
+
+(defun evil-select-paren (open close beg end type count &optional inclusive)
+ "Return a range (BEG END) of COUNT delimited text objects.
+OPEN and CLOSE specify the opening and closing delimiter,
+respectively. BEG END TYPE are the currently selected (visual)
+range. If INCLUSIVE is non-nil, OPEN and CLOSE are included in
+the range; otherwise they are excluded.
+
+If you aren't inside a pair of the opening and closing delimiters,
+it jumps you inside the next one. If there isn't one, it errors.
+
+The types of OPEN and CLOSE specify which kind of THING is used
+for parsing with `evil-select-block'. If OPEN and CLOSE are
+characters `evil-up-paren' is used. Otherwise OPEN and CLOSE
+must be regular expressions and `evil-up-block' is used.
+
+If the selection is exclusive, whitespace at the end or at the
+beginning of the selection until the end-of-line or beginning-of-line
+is ignored."
+ (condition-case nil
+ (progn
+ ;; we need special linewise exclusive selection
+ (unless inclusive (setq inclusive 'exclusive-line))
+ (cond
+ ((and (characterp open) (characterp close))
+ (let ((thing #'(lambda (&optional cnt)
+ (evil-up-paren open close cnt)))
+ (bnd (or (bounds-of-thing-at-point 'evil-string)
+ (bounds-of-thing-at-point 'evil-comment)
+ ;; If point is at the opening quote of a string,
+ ;; this must be handled as if point is within the
+ ;; string, i.e. the selection must be extended
+ ;; around the string. Otherwise
+ ;; `evil-select-block' might do the wrong thing
+ ;; because it accidentally moves point inside the
+ ;; string (for inclusive selection) when looking
+ ;; for the current surrounding block. (re #364)
+ (and (= (point) (or beg (point)))
+ (save-excursion
+ (goto-char (1+ (or beg (point))))
+ (or (bounds-of-thing-at-point 'evil-string)
+ (bounds-of-thing-at-point 'evil-comment)))))))
+ (if (not bnd)
+ (evil-select-block thing beg end type count inclusive)
+ (or (evil-with-restriction (car bnd) (cdr bnd)
+ (ignore-errors
+ (evil-select-block thing beg end type count inclusive)))
+ (save-excursion
+ (setq beg (or beg (point))
+ end (or end (point)))
+ (goto-char (car bnd))
+ (let ((extbeg (min beg (car bnd)))
+ (extend (max end (cdr bnd))))
+ (evil-select-block thing
+ extbeg extend
+ type
+ count
+ inclusive
+ (or (< extbeg beg) (> extend end))
+ t)))))))
+ (t
+ (evil-select-block #'(lambda (&optional cnt)
+ (evil-up-block open close cnt))
+ beg end type count inclusive))))
+ (error ; we aren't in the parens, so find next instance
+ (save-match-data
+ (goto-char (or (if (and count (> 0 count)) end beg)
+ (point)))
+ (let ((re (if (characterp open) (regexp-quote (string open)) open)))
+ (if (and (not (looking-at-p re))
+ (re-search-forward re nil t count))
+ (progn
+ (goto-char (match-beginning 0))
+ (let* ((mbeg (match-beginning 0))
+ (res (evil-select-paren open close mbeg mbeg
+ type nil inclusive)))
+ (if (< (car res) mbeg)
+ ;; this will error if the beginning of the found parens is before the target paren
+ ;; this prevents things such as on the line `prova ( verder "((testo)")`,
+ ;; the inputs `g2ci(` from putting your cursor inside the deleted `()` after `prova`
+ ;; without this, it would go to the second paren (the unbalanced first paren inside the quotes)
+ ;; and then do a change there, changing inside the whole paren after `prova`
+ (error "No surrounding delimiters found")
+ res)))
+ (error "No surrounding delimiters found")))))))
+
+(defun evil-select-quote-thing (thing beg end _type count &optional inclusive)
+ "Selection THING as if it described a quoted object.
+THING is typically either `evil-quote' or `evil-chars'. This
+function is called from `evil-select-quote'."
+ (save-excursion
+ (let* ((count (or count 1))
+ (dir (if (> count 0) 1 -1))
+ (bnd (let ((b (bounds-of-thing-at-point thing)))
+ (and b (< (point) (cdr b)) b)))
+ addcurrent
+ wsboth)
+ (if inclusive (setq inclusive t)
+ (when (= (abs count) 2)
+ (setq count dir)
+ (setq inclusive 'quote-only))
+ ;; never extend with exclusive selection
+ (setq beg nil end nil))
+ ;; check if the previously selected range does not contain a
+ ;; string
+ (unless (and beg end
+ (save-excursion
+ (goto-char (if (> dir 0) beg end))
+ (forward-thing thing dir)
+ (and (<= beg (point)) (< (point) end))))
+ ;; if so forget the range
+ (setq beg nil end nil))
+ ;; check if there is a current object, if not fetch one
+ (when (not bnd)
+ (unless (and (zerop (forward-thing thing dir))
+ (setq bnd (bounds-of-thing-at-point thing)))
+ (error "No quoted string found"))
+ (if (> dir 0)
+ (setq end (point))
+ (setq beg (point)))
+ (setq addcurrent t))
+ ;; check if current object is not selected
+ (when (or (not beg) (not end) (> beg (car bnd)) (< end (cdr bnd)))
+ ;; if not, enlarge selection
+ (when (or (not beg) (< (car bnd) beg)) (setq beg (car bnd)))
+ (when (or (not end) (> (cdr bnd) end)) (setq end (cdr bnd)))
+ (setq addcurrent t wsboth t))
+ ;; maybe count current element
+ (when addcurrent
+ (setq count (if (> dir 0) (1- count) (1+ count))))
+ ;; enlarge selection
+ (goto-char (if (> dir 0) end beg))
+ (when (and (not addcurrent)
+ (= count (forward-thing thing count)))
+ (error "No quoted string found"))
+ (if (> dir 0) (setq end (point)) (setq beg (point)))
+ ;; add whitespace
+ (cond
+ ((not inclusive) (setq beg (1+ beg) end (1- end)))
+ ((not (eq inclusive 'quote-only))
+ ;; try to add whitespace in forward direction
+ (goto-char (if (> dir 0) end beg))
+ (if (setq bnd (bounds-of-thing-at-point 'evil-space))
+ (if (> dir 0) (setq end (cdr bnd)) (setq beg (car bnd)))
+ ;; if not found try backward direction
+ (goto-char (if (> dir 0) beg end))
+ (if (and wsboth (setq bnd (bounds-of-thing-at-point 'evil-space)))
+ (if (> dir 0) (setq beg (car bnd)) (setq end (cdr bnd)))))))
+ (evil-range beg end
+ ;; HACK: fixes #583
+ ;; When not in visual state, an empty range is
+ ;; possible. However, this cannot be achieved with
+ ;; inclusive ranges, hence we use exclusive ranges
+ ;; in this case. In visual state the range must be
+ ;; inclusive because otherwise the selection would
+ ;; be wrong.
+ (if (evil-visual-state-p) 'inclusive 'exclusive)
+ :expanded t))))
+
+(defun evil-select-quote (quote beg end type count &optional inclusive)
+ "Return a range (BEG END) of COUNT quoted text objects.
+QUOTE specifies the quotation delimiter. BEG END TYPE are the
+currently selected (visual) range.
+
+If INCLUSIVE is nil the previous selection is ignore. If there is
+quoted string at point this object will be selected, otherwise
+the following (if (> COUNT 0)) or preceeding object (if (< COUNT
+0)) is selected. If (/= (abs COUNT) 2) the delimiting quotes are not
+contained in the range, otherwise they are contained in the range.
+
+If INCLUSIVE is non-nil the selection depends on the previous
+selection. If the currently selection contains at least one
+character that is contained in a quoted string then the selection
+is extended, otherwise it is thrown away. If there is a
+non-selected object at point then this object is added to the
+selection. Otherwise the selection is extended to the
+following (if (> COUNT 0)) or preceeding object (if (< COUNT
+0)). Any whitespace following (or preceeding if (< COUNT 0)) the
+new selection is added to the selection. If no such whitespace
+exists and the selection contains only one quoted string then the
+preceeding (or following) whitespace is added to the range. "
+ (let ((evil-forward-quote-char quote))
+ (or (let ((bnd (or (bounds-of-thing-at-point 'evil-comment)
+ (bounds-of-thing-at-point 'evil-string))))
+ (when (and bnd (< (point) (cdr bnd))
+ (/= (char-after (car bnd)) quote)
+ (/= (char-before (cdr bnd)) quote))
+ (evil-with-restriction (car bnd) (cdr bnd)
+ (ignore-errors (evil-select-quote-thing
+ 'evil-quote-simple
+ beg end type
+ count
+ inclusive)))))
+ (let ((evil-forward-quote-char quote))
+ (evil-select-quote-thing 'evil-quote
+ beg end type
+ count
+ inclusive)))))
+
+(defun evil-select-xml-tag (beg end type &optional count inclusive)
+ "Return a range (BEG END) of COUNT matching XML tags.
+If INCLUSIVE is non-nil, the tags themselves are included
+from the range."
+ (cond
+ ((and (not inclusive) (= (abs (or count 1)) 1))
+ (let ((rng (evil-select-block #'evil-up-xml-tag beg end type count nil t)))
+ (if (or (and beg (= beg (evil-range-beginning rng))
+ end (= end (evil-range-end rng))))
+ (evil-select-block #'evil-up-xml-tag beg end type count t)
+ rng)))
+ (t
+ (evil-select-block #'evil-up-xml-tag beg end type count inclusive))))
+
+(defun evil-expand-range (range &optional copy)
+ "Expand RANGE according to its type.
+Return a new range if COPY is non-nil."
+ (when copy
+ (setq range (evil-copy-range range)))
+ (unless (plist-get (evil-range-properties range) :expanded)
+ (setq range (evil-transform-range :expand range)))
+ range)
+
+(defun evil-contract-range (range &optional copy)
+ "Contract RANGE according to its type.
+Return a new range if COPY is non-nil."
+ (evil-transform-range :contract range copy))
+
+(defun evil-normalize-range (range &optional copy)
+ "Normalize RANGE according to its type.
+Return a new range if COPY is non-nil."
+ (evil-transform-range :normalize range copy))
+
+(defun evil-transform-range (transform range &optional copy)
+ "Apply TRANSFORM to RANGE according to its type.
+Return a new range if COPY is non-nil."
+ (when copy
+ (setq range (evil-copy-range range)))
+ (when (evil-type range)
+ (apply #'evil-set-range range
+ (apply #'evil-transform transform range)))
+ range)
+
+(defun evil-describe-range (range)
+ "Return description of RANGE.
+If no description is available, return the empty string."
+ (apply #'evil-describe range))
+
+;;; Undo
+
+(defvar buffer-undo-tree)
+(declare-function undo-tree-current "ext:undo-tree")
+(declare-function undo-tree-node-next "ext:undo-tree")
+(declare-function undo-tree-node-branch "ext:undo-tree")
+(declare-function undo-tree-node-branch "ext:undo-tree")
+(declare-function undo-tree-undo "ext:undo-tree")
+(declare-function undo-tree-snip-node "ext:undo-tree")
+
+(defun evil-start-undo-step (&optional continue)
+ "Start a undo step.
+All following buffer modifications are grouped together as a
+single action. If CONTINUE is non-nil, preceding modifications
+are included. The step is terminated with `evil-end-undo-step'."
+ (when (and (listp buffer-undo-list)
+ (not evil-in-single-undo))
+ (if evil-undo-list-pointer
+ (evil-refresh-undo-step)
+ (unless (or continue (null (car-safe buffer-undo-list)))
+ (undo-boundary))
+ (setq evil-undo-list-pointer (or buffer-undo-list t)))))
+
+(defun evil-end-undo-step (&optional continue)
+ "End a undo step started with `evil-start-undo-step'.
+Adds an undo boundary unless CONTINUE is specified."
+ (when (and (listp buffer-undo-list)
+ evil-undo-list-pointer
+ (not evil-in-single-undo))
+ (evil-refresh-undo-step)
+ (unless (or continue (null (car-safe buffer-undo-list)))
+ (undo-boundary))
+ (setq evil-undo-list-pointer nil)))
+
+(defun evil-refresh-undo-step ()
+ "Refresh `buffer-undo-list' entries for current undo step.
+Undo boundaries until `evil-undo-list-pointer' are removed to
+make the entries undoable as a single action. See
+`evil-start-undo-step'."
+ (when evil-undo-list-pointer
+ (setq buffer-undo-list
+ (evil-filter-list #'null buffer-undo-list evil-undo-list-pointer))
+ (setq evil-undo-list-pointer (or buffer-undo-list t))))
+
+(defmacro evil-with-undo (&rest body)
+ "Execute BODY with enabled undo.
+If undo is disabled in the current buffer, the undo information
+is stored in `evil-temporary-undo' instead of `buffer-undo-list'."
+ (declare (indent defun) (debug t))
+ (let ((undo-list (make-symbol "undo-list")))
+ `(let ((,undo-list buffer-undo-list)
+ (evil-undo-system evil-undo-system))
+ (when (eq ,undo-list t) (setq buffer-undo-list nil
+ evil-undo-system nil))
+ (unwind-protect
+ (progn ,@body)
+ ;; ensure any new undo changes we've accumulated start with
+ ;; exactly one undo boundary marker, i.e. nil
+ (when (car-safe buffer-undo-list) (push nil buffer-undo-list))
+ (if (eq ,undo-list t)
+ ;; undo is disabled, so store undo information in
+ ;; evil-temporary-undo
+ (setq evil-temporary-undo buffer-undo-list
+ buffer-undo-list t)
+ (setq evil-temporary-undo nil))))))
+
+(defmacro evil-with-single-undo (&rest body)
+ "Execute BODY as a single undo step."
+ (declare (indent defun) (debug t))
+ `(let (evil-undo-list-pointer)
+ (evil-with-undo
+ (evil-start-undo-step)
+ (unwind-protect
+ (let ((evil-in-single-undo t)) ,@body)
+ (evil-end-undo-step)))))
+
+(defun evil-undo-pop ()
+ "Undo and forget the last buffer change.
+If undo is disabled in the current buffer, use the information
+in `evil-temporary-undo' instead."
+ (if (and (eq evil-undo-system 'undo-tree)
+ (not (eq buffer-undo-list t)))
+ (let (current)
+ (undo-tree-undo)
+ (setq current (undo-tree-current buffer-undo-tree)
+ current (nth (undo-tree-node-branch current)
+ (undo-tree-node-next current)))
+ ;; Remove only if leaf to not have to adjust child buffer positions
+ (unless (undo-tree-node-next current) (undo-tree-snip-node current)))
+ (let ((paste-undo (list nil))
+ (undo-list (if (eq buffer-undo-list t)
+ evil-temporary-undo
+ buffer-undo-list)))
+ (when (or (not undo-list) (car undo-list))
+ (user-error "Can't undo previous change"))
+ (while (and undo-list (null (car undo-list)))
+ (pop undo-list)) ; remove nil
+ (while (and undo-list (car undo-list))
+ (push (pop undo-list) paste-undo))
+ (let ((buffer-undo-list (nreverse paste-undo)))
+ (evil-save-echo-area
+ (undo)))
+ (if (eq buffer-undo-list t)
+ (setq evil-temporary-undo nil)
+ (setq buffer-undo-list undo-list)))))
+
+;;; Search
+(defun evil-transform-regexp (regexp replacements-alist)
+ (replace-regexp-in-string
+ "\\\\+[^\\\\]"
+ #'(lambda (txt)
+ (let* ((b (match-beginning 0))
+ (e (match-end 0))
+ (ch (aref txt (1- e)))
+ (repl (assoc ch replacements-alist)))
+ (if (and repl (zerop (mod (length txt) 2)))
+ (concat (substring txt b (- e 2))
+ (cdr repl))
+ txt)))
+ regexp nil t))
+
+(defun evil-transform-magic (str magic quote transform &optional _start)
+ "Transform STR with magic characters.
+MAGIC is a regexp that matches all potential magic
+characters. Each occurence of CHAR as magic character within str
+is replaced by the result of calling the associated TRANSFORM
+function. TRANSFORM is a function taking two arguments, the
+character to be transformed and the rest of string after the
+character. The function should return a triple (REPLACEMENT REST
+. STOP) where REPLACEMENT is the replacement and REST is the rest
+of the string that has not been transformed. If STOP is non-nil
+then the substitution stops immediately. The replacement starts
+at position START, everything before that position is returned
+literally. The result is a pair (RESULT . REST). RESULT is a
+list containing the transformed parts in order. If two
+subsequents parts are both strings, they are concatenated. REST
+is the untransformed rest string (usually \"\" but may be more if
+TRANSFORM stopped the substitution). Which characters are
+considered as magic characters (i.e. the transformation happens
+if the character is NOT preceeded by a backslash) is determined
+by `evil-magic'. The special tokens \\v, \\V, \\m and \\M have
+always a special meaning (like in Vim) and should not be
+contained in TRANSFORMS, otherwise their meaning is overwritten.
+
+The parameter QUOTE is a quoting function applied to literal
+transformations, usually `regexp-quote' or `replace-quote'."
+ (save-match-data
+ (let ((regexp (concat "\\(?:\\`\\|[^\\]\\)\\(\\\\\\(?:\\(" magic "\\)\\|\\(.\\)\\)\\|\\(" magic "\\)\\)"))
+ (magic-chars (evil-get-magic evil-magic))
+ (evil-magic evil-magic)
+ (quote (or quote #'identity))
+ result stop)
+ (while (and (not stop) str (string-match regexp str))
+ (unless (zerop (match-beginning 1))
+ (push (substring str 0 (match-beginning 1)) result))
+ (let ((char (or (match-string 2 str)
+ (match-string 3 str)
+ (match-string 4 str)))
+ (rest (substring str (match-end 0))))
+ (cond
+ ((match-beginning 4)
+ ;; magic character without backslash
+ (if (string-match magic-chars char)
+ ;; magic, do transform
+ (let ((trans (funcall transform (aref char 0) rest)))
+ (push (car trans) result)
+ (setq str (cadr trans) stop (nthcdr 2 trans)))
+ ;; non-magic, literal transformation
+ (push (funcall quote char) result)
+ (setq str rest)))
+ ((match-beginning 2)
+ ;; magic character with backslash
+ (if (not (string-match magic-chars char))
+ ;; non-magic, do transform
+ (let ((trans (funcall transform (aref char 0) rest)))
+ (push (car trans) result)
+ (setq str (cadr trans) stop (nthcdr 2 trans)))
+ ;; magic, literal transformation
+ (push (funcall quote char) result)
+ (setq str rest)))
+ ((memq (aref char 0) '(?m ?M ?v ?V))
+ (setq evil-magic (cdr (assq (aref char 0)
+ '((?m . t)
+ (?M . nil)
+ (?v . very-magic)
+ (?V . very-nomagic)))))
+ (setq magic-chars (evil-get-magic evil-magic))
+ (setq str rest))
+ (t
+ ;; non-magic char with backslash, literal transformation
+ (push (funcall quote char) result)
+ (setq str rest)))))
+ (cond
+ ((and str (not stop))
+ (push str result)
+ (setq str ""))
+ ((not str)
+ (setq str "")))
+ ;; concatenate subsequent strings
+ ;; note that result is in reverse order
+ (let (repl)
+ (while result
+ (cond
+ ((and (stringp (car result))
+ (zerop (length (car result))))
+ (pop result))
+ ((and (stringp (car result))
+ (stringp (cadr result)))
+ (setq result (cons (concat (cadr result)
+ (car result))
+ (nthcdr 2 result))))
+ (t
+ (push (pop result) repl))))
+ (cons repl str)))))
+
+(defconst evil-vim-regexp-replacements
+ '((?n . "\n") (?r . "\r")
+ (?t . "\t") (?b . "\b")
+ (?s . "[[:space:]]") (?S . "[^[:space:]]")
+ (?d . "[[:digit:]]") (?D . "[^[:digit:]]")
+ (?x . "[[:xdigit:]]") (?X . "[^[:xdigit:]]")
+ (?o . "[0-7]") (?O . "[^0-7]")
+ (?a . "[[:alpha:]]") (?A . "[^[:alpha:]]")
+ (?l . "[a-z]") (?L . "[^a-z]")
+ (?u . "[A-Z]") (?U . "[^A-Z]")
+ (?y . "\\s") (?Y . "\\S")
+ (?\( . "\\(") (?\) . "\\)")
+ (?{ . "\\{") (?} . "\\}")
+ (?\[ . "[") (?\] . "]")
+ (?< . "\\<") (?> . "\\>")
+ (?_ . "\\_")
+ (?* . "*") (?+ . "+")
+ (?? . "?") (?= . "?")
+ (?. . ".")
+ (?` . "`") (?^ . "^")
+ (?$ . "$") (?| . "\\|")))
+
+(defconst evil-regexp-magic "[][(){}<>_dDsSxXoOaAlLuUwWyY.*+?=^$`|nrtb0-9]")
+
+(defun evil-transform-vim-style-regexp (regexp)
+ "Transform vim-style backslash codes to Emacs regexp.
+This includes the backslash codes \\d, \\D, \\s, \\S, \\x, \\X,
+\\o, \\O, \\a, \\A, \\l, \\L, \\u, \\U and \\w, \\W. The new
+codes \\y and \\Y can be used instead of the Emacs code \\s and
+\\S which have a different meaning in Vim-style."
+ (car
+ (car
+ (evil-transform-magic
+ regexp evil-regexp-magic #'regexp-quote
+ #'(lambda (char rest)
+ (let ((repl (assoc char evil-vim-regexp-replacements)))
+ (if repl
+ (list (cdr repl) rest)
+ (list (concat "\\" (char-to-string char)) rest))))))))
+
+;;; Substitute
+
+(defun evil-downcase-first (str)
+ "Return STR with the first letter downcased."
+ (if (zerop (length str))
+ str
+ (concat (downcase (substring str 0 1))
+ (substring str 1))))
+
+(defun evil-upcase-first (str)
+ "Return STR with the first letter upcased."
+ (if (zerop (length str))
+ str
+ (concat (upcase (substring str 0 1))
+ (substring str 1))))
+
+(defun evil-get-magic (magic)
+ "Return a regexp matching the magic characters according to MAGIC.
+Depending on the value of MAGIC the following characters are
+considered magic.
+ t [][{}*+?.&~$^
+ nil [][{}*+?$^
+ `very-magic' not 0-9A-Za-z_
+ `very-nomagic' empty."
+ (cond
+ ((eq magic t) "[][}{*+?.&~$^]")
+ ((eq magic 'very-magic) "[^0-9A-Za-z_]")
+ ((eq magic 'very-nomagic) "\\\\")
+ (t "[][}{*+?$^]")))
+
+;; TODO: support magic characters in patterns
+(defconst evil-replacement-magic "[eElLuU0-9&#,rnbt=]"
+ "All magic characters in a replacement string")
+
+(defun evil-compile-subreplacement (to &optional start)
+ "Convert a regexp replacement TO to Lisp from START until \\e or \\E.
+Return a pair (RESULT . REST). RESULT is a list suitable for
+`perform-replace' if necessary, the original string if not.
+REST is the unparsed remainder of TO."
+ (let ((result
+ (evil-transform-magic
+ to evil-replacement-magic #'replace-quote
+ #'(lambda (char rest)
+ (cond
+ ((eq char ?#)
+ (list '(number-to-string replace-count) rest))
+ ((eq char ?r) (list "\r" rest))
+ ((eq char ?n) (list "\n" rest))
+ ((eq char ?b) (list "\b" rest))
+ ((eq char ?t) (list "\t" rest))
+ ((memq char '(?e ?E))
+ `("" ,rest . t))
+ ((memq char '(?l ?L ?u ?U))
+ (let ((result (evil-compile-subreplacement rest))
+ (func (cdr (assoc char
+ '((?l . evil-downcase-first)
+ (?L . downcase)
+ (?u . evil-upcase-first)
+ (?U . upcase))))))
+ (list `(,func
+ (replace-quote
+ (evil-match-substitute-replacement
+ ,(car result)
+ (not case-replace))))
+ (cdr result))))
+ ((eq char ?=)
+ (when (or (zerop (length rest))
+ (not (eq (aref rest 0) ?@)))
+ (user-error "Expected @ after \\="))
+ (when (< (length rest) 2)
+ (user-error "Expected register after \\=@"))
+ (list (evil-get-register (aref rest 1))
+ (substring rest 2)))
+ ((eq char ?,)
+ (let* ((obj (read-from-string rest))
+ (result `(replace-quote ,(car obj)))
+ (end
+ ;; swallow a space after a symbol
+ (if (and (or (symbolp (car obj))
+ ;; swallow a space after 'foo,
+ ;; but not after (quote foo)
+ (and (eq (car-safe (car obj)) 'quote)
+ (not (= ?\( (aref rest 0)))))
+ (eq (string-match " " rest (cdr obj))
+ (cdr obj)))
+ (1+ (cdr obj))
+ (cdr obj))))
+ (list result (substring rest end))))
+ ((eq char ?0)
+ (list "\\&" rest))
+ (t
+ (list (concat "\\" (char-to-string char)) rest))))
+ start)))
+ (let ((rest (cdr result))
+ (result (car result)))
+ (replace-match-string-symbols result)
+ (cons (if (cdr result)
+ (cons 'concat result)
+ (or (car result) ""))
+ rest))))
+
+(defun evil-compile-replacement (to)
+ "Maybe convert a regexp replacement TO to Lisp.
+Return a list suitable for `perform-replace' if necessary, the
+original string if not. Currently the following magic characters
+in replacements are supported: 0-9&#lLuUrnbt,
+The magic character , (comma) start an Emacs-lisp expression."
+ (when (stringp to)
+ (save-match-data
+ (cons 'replace-eval-replacement
+ (car (evil-compile-subreplacement to))))))
+
+(defun evil-match-substitute-replacement (replacement &optional fixedcase string)
+ "Return REPLACEMENT as it will be inserted by `evil-replace-match'.
+If REPLACEMENT is an expression it will be evaluated to compute the
+replacement text first."
+ (match-substitute-replacement
+ (if (stringp replacement)
+ replacement
+ (funcall (car replacement)
+ (cdr replacement)
+ 0))
+ fixedcase nil string))
+
+;;; Alignment
+
+(defun evil-justify-lines (beg end justify position)
+ "Justify all lines in a range.
+BEG and END specify the range of those lines to be
+justified. JUSTIFY is either `left', `right' or `center' according
+to the justification type. POSITION is the maximal text width for
+right and center justification or the column at which the lines
+should be left-aligned for left justification."
+ (let ((fill-column position)
+ adaptive-fill-mode fill-prefix)
+ (evil-with-restriction
+ (save-excursion (goto-char beg) (line-beginning-position))
+ (save-excursion (goto-char end) (line-end-position (if (bolp) 0 1)))
+ (goto-char (point-min))
+ (while (progn
+ (if (eq justify 'left)
+ (indent-line-to position)
+ (when (re-search-forward "^[[:space:]]*" nil t)
+ (delete-region (match-beginning 0)
+ (match-end 0)))
+ (justify-current-line justify nil t))
+ (and (zerop (forward-line)) (bolp))))
+ (goto-char (point-min))
+ (back-to-indentation))))
+
+;;; View helper
+
+(defvar-local evil-list-view-select-action nil)
+
+(define-derived-mode evil-list-view-mode tabulated-list-mode
+ "Evil List View"
+ (tabulated-list-init-header)
+ (tabulated-list-print))
+
+(defun evil-list-view-goto-entry ()
+ (interactive)
+ (when (and evil-list-view-select-action
+ (not (eobp)))
+ (let* ((line (line-number-at-pos (point)))
+ (entry (elt tabulated-list-entries (1- line))))
+ (funcall evil-list-view-select-action (nth 1 entry)))))
+
+(defun evil-list-view-quit ()
+ (interactive)
+ (quit-window 'kill))
+
+(define-key evil-list-view-mode-map (kbd "q") #'evil-list-view-quit)
+(define-key evil-list-view-mode-map [follow-link] nil) ;; allows mouse-1 to be activated
+(define-key evil-list-view-mode-map [mouse-1] #'evil-list-view-goto-entry)
+(define-key evil-list-view-mode-map [return] #'evil-list-view-goto-entry)
+
+(defmacro evil-with-view-list (&rest properties)
+ "Open a new list view buffer.
+PROPERTIES is a property-list which supports the following properties:
+
+:name (required) The name of the buffer.
+:mode-name (required) The name for the mode line.
+:format (required) The value for `tabulated-list-format'.
+:entries (required) The value for `tabulated-list-entries'.
+:select-action (optional) A function for row selection.
+ It takes a single parameter, which is the
+ selected row's vector value that is
+ passed into `:entries'."
+ (declare (indent defun) (debug t))
+ `(let ((bufname (concat "*" ,(plist-get properties :name) "*"))
+ (inhibit-read-only t))
+ (and (get-buffer bufname)
+ (kill-buffer bufname))
+ (let ((buf (get-buffer-create bufname)))
+ (with-current-buffer buf
+ (setq tabulated-list-format ,(plist-get properties :format))
+ (setq tabulated-list-entries ,(plist-get properties :entries))
+ (setq evil-list-view-select-action ,(plist-get properties :select-action))
+ (evil-list-view-mode)
+ (setq mode-name ,(plist-get properties :mode-name))
+ (evil-motion-state))
+ (switch-to-buffer-other-window buf))))
+
+(provide 'evil-common)
+
+;;; evil-common.el ends here
diff --git a/.config/emacs/lisp/evil/evil-core.el b/.config/emacs/lisp/evil/evil-core.el
new file mode 100644
index 0000000..ae3f949
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-core.el
@@ -0,0 +1,1322 @@
+;;; evil-core.el --- Core functionality -*- lexical-binding: t -*-
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Evil is defined as a globalized minor mode, enabled with the toggle
+;; function `evil-mode'. This in turn enables `evil-local-mode' in
+;; every buffer, which sets up the buffer's state.
+;;
+;; Each state has its own keymaps, and these keymaps have status as
+;; "emulation keymaps" with priority over regular keymaps. Emacs
+;; maintains the following keymap hierarchy (highest priority first):
+;;
+;; * Overriding keymaps/overlay keymaps...
+;; * Emulation mode keymaps...
+;; - Evil keymaps...
+;; * Minor mode keymaps...
+;; * Local keymap (`local-set-key')
+;; * Global keymap (`global-set-key')
+;;
+;; Within this hierarchy, Evil arranges the keymaps for the current
+;; state as shown below:
+;;
+;; * Intercept keymaps...
+;; * Local state keymap
+;; * Minor-mode keymaps...
+;; * Auxiliary keymaps...
+;; * Overriding keymaps...
+;; * Global state keymap
+;; * Keymaps for other states...
+;;
+;; These keymaps are listed in `evil-mode-map-alist', which is listed
+;; in `emulation-mode-map-alist'.
+;;
+;; Most of the key bindings for a state are stored in its global
+;; keymap, which has a name such as `evil-normal-state-map'. (See the
+;; file evil-maps.el, which contains all the default key bindings.) A
+;; state also has a local keymap (`evil-normal-state-local-map'),
+;; which may contain user customizations for the current buffer.
+;; Furthermore, any Emacs mode may be assigned state bindings of its
+;; own by passing the mode's keymap to the function `evil-define-key'
+;; or `evil-define-minor-mode-key'. The former uses a specific map to
+;; define the key in while the latter associates the key with a
+;; particular mode. These mode-specific bindings are ultimately stored
+;; in so-called auxiliary and minor-mode keymaps respectively, which
+;; are sandwiched between the local keymap and the global keymap.
+;; Finally, the state may also activate the keymaps of other states
+;; (e.g., Normal state inherits bindings from Motion state).
+;;
+;; For integration purposes, a regular Emacs keymap may be "elevated"
+;; to emulation status by passing it to `evil-make-intercept-map' or
+;; `evil-make-overriding-map'. An "intercept" keymap has priority over
+;; all other Evil keymaps. (Evil uses this facility when debugging and
+;; for handling the "ESC" key in the terminal.) More common is the
+;; "overriding" keymap, which only has priority over the global state
+;; keymap. (This is useful for adapting key-heavy modes such as Dired,
+;; where all but a few keys should be left as-is and should not be
+;; shadowed by Evil's default bindings.)
+;;
+;; States are defined with the macro `evil-define-state', which
+;; creates a command for switching to the state. This command,
+;; for example `evil-normal-state' for Normal state, performs
+;; the following tasks:
+;;
+;; * Setting `evil-state' to the new state.
+;; * Refreshing the keymaps in `evil-mode-map-alist'.
+;; * Updating the mode line.
+;; - Normal state depends on `evil-normal-state-tag'.
+;; * Adjusting the cursor's appearance.
+;; - Normal state depends on `evil-normal-state-cursor'.
+;; * Displaying a message in the echo area.
+;; - Normal state depends on `evil-normal-state-message'.
+;; * Running hooks.
+;; - Normal state runs `evil-normal-state-entry-hook' when
+;; entering, and `evil-normal-state-exit-hook' when exiting.
+;;
+;; The various properties of a state can be accessed through their
+;; respective variables, or by passing a keyword and the state's name
+;; to the `evil-state-property' function. Evil defines the states
+;; Normal state ("normal"), Insert state ("insert"), Visual state
+;; ("visual"), Replace state ("replace"), Operator-Pending state
+;; ("operator"), Motion state ("motion") and Emacs state ("emacs").
+
+;;; Code:
+
+(require 'evil-common)
+
+(declare-function evil-emacs-state-p "evil-states")
+(declare-function evil-ex-p "evil-ex")
+
+(define-minor-mode evil-local-mode
+ "Minor mode for setting up Evil in a single buffer."
+ :init-value nil
+ (if evil-local-mode
+ (progn
+ (cl-pushnew 'evil-mode-map-alist emulation-mode-map-alists)
+ (evil-initialize-local-keymaps)
+ (when (minibufferp)
+ (setq-local evil-default-state 'insert)
+ (setq-local evil-echo-state nil))
+ (setq evil-input-method current-input-method)
+ (evil-initialize-state)
+ (add-hook 'input-method-activate-hook #'evil-activate-input-method t t)
+ (add-hook 'input-method-deactivate-hook #'evil-deactivate-input-method t t)
+ (add-hook 'activate-mark-hook 'evil-visual-activate-hook nil t)
+ ;; FIXME: Add these hooks buffer-locally and remove when disabling
+ (add-hook 'pre-command-hook 'evil-repeat-pre-hook)
+ (add-hook 'post-command-hook 'evil-repeat-post-hook))
+ (evil-refresh-mode-line)
+ (remove-hook 'activate-mark-hook 'evil-visual-activate-hook t)
+ (remove-hook 'input-method-activate-hook #'evil-activate-input-method t)
+ (remove-hook 'input-method-deactivate-hook #'evil-deactivate-input-method t)
+ (activate-input-method evil-input-method)
+ (evil-change-state nil)))
+
+;; Make the variable permanent local. This is particular useful in
+;; conjunction with nXhtml/mumamo because mumamo does not touch these
+;; variables.
+(put 'evil-local-mode 'permanent-local t)
+
+(defun turn-on-evil-mode ()
+ "Turn on Evil in the current buffer."
+ (interactive)
+ (evil-local-mode))
+
+(defun turn-off-evil-mode ()
+ "Turn off Evil in the current buffer."
+ (interactive)
+ (evil-local-mode -1))
+
+;; The function `evil-initialize' should only be used to initialize
+;; `evil-local-mode' from the globalized minor-mode `evil-mode'. It is
+;; called whenever evil is enabled in a buffer for the first time or
+;; when evil is active and the major-mode of the buffer changes.
+(defun evil-initialize ()
+ "Enable Evil in the current buffer, if appropriate.
+To enable Evil globally, do (evil-mode)."
+ (if evil-local-mode
+ ;; Set Evil state according to new major-mode
+ (evil-initialize-state)
+ (or (and (minibufferp) (not evil-want-minibuffer))
+ (evil-disabled-buffer-p)
+ (evil-local-mode))))
+
+(defalias 'evil--fundamental-mode #'fundamental-mode)
+
+(defvar evil--advices ())
+
+;;;###autoload (autoload 'evil-mode "evil" nil t)
+(define-globalized-minor-mode evil-mode evil-local-mode evil-initialize
+ :group 'evil)
+
+;; `define-globalized-minor-mode' supports a BODY argument but only since
+;; GNU Emacs 27.1, so resort to this ugly advice in the mean time.
+(define-advice evil-mode (:after (&optional _arg) body)
+ ;; Hooks used to not run in Fundamental buffers (bug#23827), so
+ ;; other measures are necessary to initialize Evil there. When Evil
+ ;; is enabled globally, the default value of `major-mode' is set to
+ ;; the `evil--fundamental-mode' alias, sidestepping the restriction.
+ (if evil-mode
+ (progn
+ (and (eval-when-compile (version< emacs-version "26.1"))
+ (eq (default-value 'major-mode) 'fundamental-mode)
+ (setq-default major-mode #'evil--fundamental-mode))
+ (dolist (advice evil--advices) (apply #'advice-add advice))
+ (with-no-warnings (evil-esc-mode 1)))
+ (when (eq (default-value 'major-mode) #'evil--fundamental-mode)
+ (setq-default major-mode 'fundamental-mode))
+ (pcase-dolist (`(,funname ,_where ,adfun) evil--advices)
+ (advice-remove funname adfun))
+ (with-no-warnings (evil-esc-mode -1))))
+
+(defun evil--advice-add (&rest args)
+ "Like `advice-add' for advices active only in `evil-mode'."
+ (when evil-mode (apply #'advice-add args))
+ (cl-pushnew args evil--advices :test #'equal))
+
+(defun evil-change-state (state &optional message)
+ "Change the state to STATE.
+If STATE is nil, disable all states."
+ (let ((func (evil-state-property (or state evil-state) :toggle)))
+ (when (and (functionp func)
+ (or message (not (eq state evil-state))))
+ (funcall func (if state (and message 1) -1)))))
+
+(defmacro evil-save-state (&rest body)
+ "Save the current state; execute BODY; restore the state."
+ (declare (indent defun)
+ (debug t))
+ `(let ((evil-state evil-state)
+ (evil-previous-state evil-previous-state)
+ (evil-previous-state-alist (copy-tree evil-previous-state-alist))
+ (evil-next-state evil-next-state)
+ (old-state evil-state)
+ (inhibit-quit t)
+ (buf (current-buffer)))
+ (unwind-protect
+ (progn ,@body)
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (evil-change-state old-state))))))
+
+(defmacro evil-with-state (state &rest body)
+ "Change to STATE and execute BODY without refreshing the display.
+Restore the previous state afterwards."
+ (declare (indent defun)
+ (debug t))
+ `(evil-without-display
+ (evil-save-state
+ (evil-change-state ',state)
+ ,@body)))
+
+(defun evil-initialize-state ()
+ "Set up the initial state for the current buffer.
+See also `evil-set-initial-state'."
+ (evil-change-state (evil-initial-state-for-buffer)))
+
+(defun evil-initial-state-for-buffer-name (&optional name default)
+ "Return the initial Evil state to use for a buffer with name NAME.
+Matches the name against the regular expressions in
+`evil-buffer-regexps'. If none matches, returns DEFAULT."
+ (let ((name (if (stringp name) name (buffer-name name))))
+ (when name
+ (catch 'done
+ (dolist (entry evil-buffer-regexps default)
+ (let ((regexp (car entry))
+ (state (cdr entry)))
+ (when (string-match-p regexp name)
+ (throw 'done state))))))))
+
+(defun evil-disabled-buffer-p (&optional buffer)
+ "Whether Evil should be disabled in BUFFER."
+ (null (evil-initial-state-for-buffer-name buffer 'undefined)))
+
+(defun evil-initial-state-for-buffer (&optional buffer)
+ "Return the initial Evil state to use for BUFFER.
+BUFFER defaults to the current buffer. See also `evil-initial-state'."
+ (with-current-buffer (or buffer (current-buffer))
+ (or (evil-initial-state-for-buffer-name)
+ (cl-loop for (mode) in minor-mode-map-alist
+ when (and (boundp mode) (symbol-value mode))
+ thereis (evil-initial-state mode))
+ (evil-initial-state major-mode nil t)
+ evil-default-state)))
+
+(defun evil-initial-state (mode &optional default follow-parent checked-modes)
+ "Return the Evil state to use for MODE or its alias.
+Return DEFAULT if no initial state is associated with MODE.
+The initial state for a mode can be set with
+`evil-set-initial-state'.
+
+If FOLLOW-PARENT is non-nil, also check parent modes of MODE and
+its alias. CHECKED-MODES is used internally and should not be set
+initially."
+ (when (memq mode checked-modes)
+ (error "Circular reference detected in ancestors of `%s'\n%s"
+ major-mode checked-modes))
+ (let ((mode-alias (let ((func (symbol-function mode)))
+ (when (symbolp func) func))))
+ (or (cl-dolist (entry (evil-state-property t :modes) default)
+ (let ((state (car entry))
+ (modes (symbol-value (cdr entry))))
+ (when (or (memq mode modes)
+ (and mode-alias (memq mode-alias modes)))
+ (cl-return state))))
+ (and follow-parent (get mode 'derived-mode-parent)
+ (evil-initial-state (get mode 'derived-mode-parent)
+ nil t (cons mode checked-modes)))
+ (and follow-parent mode-alias
+ (get mode-alias 'derived-mode-parent)
+ (evil-initial-state (get mode-alias 'derived-mode-parent)
+ nil t (cons mode-alias checked-modes))))))
+
+(defun evil-set-initial-state (mode state)
+ "Set the initial state for major mode MODE to STATE.
+This is the state the buffer comes up in."
+ (dolist (modes (evil-state-property t :modes))
+ (setq modes (cdr-safe modes))
+ (set modes (delq mode (symbol-value modes))))
+ (when state
+ (add-to-list (evil-state-property state :modes) mode)))
+
+(evil-define-command evil-change-to-initial-state
+ (&optional buffer message)
+ "Change the state of BUFFER to its initial state.
+This is the state the buffer came up in. If Evil is not activated
+then this function does nothing."
+ :keep-visual t
+ :suppress-operator t
+ (when evil-local-mode
+ (with-current-buffer (or buffer (current-buffer))
+ (evil-change-state (evil-initial-state-for-buffer buffer)
+ message))))
+
+(evil-define-command evil-change-to-previous-state
+ (&optional buffer message)
+ "Change the state of BUFFER to its previous state."
+ :keep-visual t
+ :repeat abort
+ :suppress-operator t
+ (with-current-buffer (or buffer (current-buffer))
+ (let ((prev-state evil-previous-state)
+ (prev-prev-state (cdr-safe (assoc evil-previous-state
+ evil-previous-state-alist))))
+ (evil-change-state nil)
+ (when prev-prev-state
+ (setq evil-previous-state prev-prev-state))
+ (evil-change-state (or prev-state evil-default-state 'normal)
+ message))))
+
+;; When a buffer is created in a low-level way, it is invisible to
+;; Evil (as well as other globalized minor modes) because no hooks are
+;; run. This is appropriate since many buffers are used for throwaway
+;; purposes. Passing the buffer to `set-window-buffer' indicates
+;; otherwise, though, so advise this function to initialize Evil.
+(evil--advice-add 'set-window-buffer :before #'evil--swb-initialize)
+(defun evil--swb-initialize (_window buffer &rest _)
+ "Initialize Evil in the displayed buffer."
+ (when (and evil-mode (get-buffer buffer))
+ (with-current-buffer buffer
+ (unless evil-local-mode
+ (save-match-data (evil-initialize))))))
+
+;; Refresh cursor color.
+;; Cursor color can only be set for each frame but not for each buffer.
+;; FIXME: Shouldn't this belong in `evil-(local-)mode'?
+(add-hook 'window-configuration-change-hook #'evil-refresh-cursor)
+(advice-add 'select-window :after #'evil--sw-refresh-cursor)
+(defun evil--sw-refresh-cursor (&rest _)
+ (evil-refresh-cursor))
+
+(defun evil-generate-mode-line-tag (&optional state)
+ "Generate the evil mode-line tag for STATE."
+ (let ((tag (evil-state-property state :tag t)))
+ (when (functionp tag)
+ (setq tag (funcall tag)))
+ ;; prepare mode-line: add tooltip
+ (if (stringp tag)
+ (propertize tag
+ 'help-echo (evil-state-property state :name)
+ 'mouse-face 'mode-line-highlight)
+ tag)))
+
+(defun evil-refresh-mode-line (&optional state)
+ "Refresh mode line tag."
+ (when (listp mode-line-format)
+ (setq evil-mode-line-tag (evil-generate-mode-line-tag state))
+ ;; refresh mode line data structure
+ ;; first remove evil from mode-line
+ (setq mode-line-format (delq 'evil-mode-line-tag mode-line-format))
+ (let ((mlpos mode-line-format)
+ pred which where)
+ ;; determine before/after which symbol the tag should be placed
+ (cond
+ ((eq evil-mode-line-format 'before)
+ (setq where 'after which 'mode-line-position))
+ ((eq evil-mode-line-format 'after)
+ (setq where 'after which 'mode-line-modes))
+ ((consp evil-mode-line-format)
+ (setq where (car evil-mode-line-format)
+ which (cdr evil-mode-line-format))))
+ ;; find the cons-cell of the symbol before/after which the tag
+ ;; should be placed
+ (while (and mlpos
+ (let ((sym (or (car-safe (car mlpos)) (car mlpos))))
+ (not (eq which sym))))
+ (setq pred mlpos
+ mlpos (cdr mlpos)))
+ ;; put evil tag at the right position in the mode line
+ (cond
+ ((not mlpos)) ;; position not found, so do not add the tag
+ ((eq where 'before)
+ (if pred
+ (setcdr pred (cons 'evil-mode-line-tag mlpos))
+ (setq mode-line-format
+ (cons 'evil-mode-line-tag mode-line-format))))
+ ((eq where 'after)
+ (setcdr mlpos (cons 'evil-mode-line-tag (cdr mlpos)))))
+ (force-mode-line-update))))
+
+;; input methods should be disabled in non-insertion states
+(defun evil-activate-input-method ()
+ "Enable input method in states with :input-method non-nil."
+ (let (input-method-activate-hook
+ input-method-deactivate-hook)
+ (when (and evil-local-mode evil-state)
+ (setq evil-input-method current-input-method)
+ (unless (evil-state-property evil-state :input-method)
+ (deactivate-input-method)))))
+(put 'evil-activate-input-method 'permanent-local-hook t)
+
+(defun evil-deactivate-input-method ()
+ "Disable input method in all states."
+ (let (input-method-activate-hook
+ input-method-deactivate-hook)
+ (when (and evil-local-mode evil-state)
+ (setq evil-input-method nil))))
+(put 'evil-deactivate-input-method 'permanent-local-hook t)
+
+(defmacro evil-without-input-method-hooks (&rest body)
+ "Execute body with evil's activate/deactivate-input-method hooks deactivated.
+This allows input methods to be used in normal-state."
+ (declare (indent defun))
+ `(unwind-protect
+ (progn
+ (remove-hook 'input-method-activate-hook #'evil-activate-input-method t)
+ (remove-hook 'input-method-deactivate-hook #'evil-deactivate-input-method t)
+ ,@body)
+ (add-hook 'input-method-activate-hook #'evil-activate-input-method nil t)
+ (add-hook 'input-method-deactivate-hook #'evil-deactivate-input-method nil t)))
+
+(evil--advice-add 'toggle-input-method :around #'evil--refresh-input-method)
+(defun evil--refresh-input-method (orig-fun &rest args)
+ "Refresh `evil-input-method'."
+ (cond
+ ((not evil-local-mode)
+ (apply orig-fun args))
+ ((evil-state-property evil-state :input-method)
+ (apply orig-fun args))
+ (t
+ (let ((current-input-method evil-input-method))
+ (apply orig-fun args)))))
+
+;; Local keymaps are implemented using buffer-local variables.
+;; However, unless a buffer-local value already exists,
+;; `define-key' acts on the variable's default (global) value.
+;; So we need to initialize the variable whenever we enter a
+;; new buffer or when the buffer-local values are reset.
+(defun evil-initialize-local-keymaps ()
+ "Initialize a buffer-local value for local keymaps as necessary.
+The initial value is that of `make-sparse-keymap'."
+ (dolist (entry evil-local-keymaps-alist)
+ (let ((map (cdr entry)))
+ (unless (and (keymapp (symbol-value map))
+ (local-variable-p map))
+ (set map (make-sparse-keymap))))))
+
+(defun evil-make-overriding-map (keymap &optional state copy)
+ "Give KEYMAP precedence over the global keymap of STATE.
+The keymap will have lower precedence than custom STATE bindings.
+If STATE is nil, give it precedence over all states.
+If COPY is t, create a copy of KEYMAP and give that
+higher precedence. See also `evil-make-intercept-map'."
+ (let ((key [override-state]))
+ (if (not copy)
+ (define-key keymap key (or state 'all))
+ (unless (keymapp copy)
+ (setq copy (assq-delete-all 'menu-bar (copy-keymap keymap))))
+ (define-key copy key (or state 'all))
+ (define-key keymap key copy))))
+
+(defun evil-make-intercept-map (keymap &optional state aux)
+ "Give KEYMAP precedence over all Evil keymaps in STATE.
+If STATE is nil, give it precedence over all states. If AUX is non-nil, make the
+auxiliary keymap corresponding to KEYMAP in STATE an intercept keymap instead of
+KEYMAP itself. See also `evil-make-overriding-map'."
+ (let ((key [intercept-state])
+ (keymap (if aux
+ (evil-get-auxiliary-keymap keymap state t t)
+ keymap)))
+ (define-key keymap key (or state 'all))))
+
+(defmacro evil-define-keymap (keymap doc &rest body)
+ "Define a keymap KEYMAP listed in `evil-mode-map-alist'.
+That means it will have precedence over regular keymaps.
+
+DOC is the documentation for the variable. BODY, if specified,
+is executed after toggling the mode. Optional keyword arguments
+may be specified before the body code:
+
+:mode VAR Mode variable. If unspecified, the variable
+ is based on the keymap name.
+:local BOOLEAN Whether the keymap should be buffer-local, that is,
+ reinitialized for each buffer.
+:func BOOLEAN Create a toggle function even if BODY is empty.
+
+\(fn KEYMAP DOC [[KEY VAL]...] BODY...)"
+ (declare (indent defun)
+ (doc-string 2)
+ (debug (&define name
+ [&optional stringp]
+ [&rest [keywordp sexp]]
+ def-body)))
+ (let ((func t)
+ arg intercept key local mode overriding)
+ (while (keywordp (car-safe body))
+ (setq key (pop body)
+ arg (pop body))
+ (cond
+ ((eq key :mode) (setq mode arg))
+ ((eq key :local) (setq local arg))
+ ((eq key :func) (setq func arg))
+ ((eq key :intercept) (setq intercept arg))
+ ((eq key :overriding) (setq overriding arg))))
+ (setq mode (or mode
+ (intern (replace-regexp-in-string
+ "\\(?:-\\(?:mode-\\)?\\(?:key\\)?map\\)?$"
+ "-mode"
+ (symbol-name keymap)))))
+ `(progn
+ (defvar ,keymap ,(unless local '(make-sparse-keymap)))
+ (unless (get ',keymap 'variable-documentation)
+ (put ',keymap 'variable-documentation ,doc))
+ (defvar ,mode nil)
+ (unless (get ',mode 'variable-documentation)
+ (put ',mode 'variable-documentation ,doc))
+ (make-variable-buffer-local ',mode)
+ (put ',mode 'permanent-local t)
+ (when ,intercept
+ (evil-make-intercept-map ,keymap))
+ (when ,overriding
+ (evil-make-overriding-map ,keymap))
+ ,@(if local
+ `((make-variable-buffer-local ',keymap)
+ (put ',keymap 'permanent-local t)
+ (evil--add-to-alist evil-local-keymaps-alist ',mode ',keymap))
+ `((evil--add-to-alist evil-global-keymaps-alist ',mode ',keymap)
+ (evil--add-to-alist evil-mode-map-alist ',mode ,keymap)))
+ ,(when (or body func)
+ `(defun ,mode (&optional arg)
+ ,@(when doc `(,doc))
+ (interactive)
+ (cond
+ ((numberp arg) (setq ,mode (> arg 0)))
+ (t (setq ,mode (not ,mode))))
+ ,@body))
+ ',keymap)))
+
+;; The ESC -> escape translation code has been provided by Stefan
+;; Monnier in the discussion of GNU Emacs bug #13793.
+(defun evil-esc-mode (&optional arg)
+ "Toggle interception of \\e (escape).
+Enable with positive ARG and disable with negative ARG.
+
+When enabled, `evil-esc-mode' modifies the entry of \\e in
+`input-decode-map'. If such an event arrives, it is translated to
+a plain `escape' event if no further event occurs within
+`evil-esc-delay' seconds. Otherwise no translation happens and
+the ESC prefix map (i.e. the map originally bound to \\e in
+`input-decode-map`) is returned."
+ (cond
+ ((or (null arg) (eq arg 0))
+ (evil-esc-mode (if evil-esc-mode -1 +1)))
+ ((> arg 0)
+ (unless evil-esc-mode
+ (setq evil-esc-mode t)
+ (add-hook 'after-make-frame-functions #'evil-init-esc)
+ (mapc #'evil-init-esc (frame-list))))
+ ((< arg 0)
+ (when evil-esc-mode
+ (remove-hook 'after-make-frame-functions #'evil-init-esc)
+ (mapc #'evil-deinit-esc (frame-list))
+ (setq evil-esc-mode nil)))))
+
+(defun evil-init-esc (frame)
+ "Update `input-decode-map' in terminal."
+ (with-selected-frame frame
+ (let ((term (frame-terminal frame)))
+ (when (and
+ (or (eq evil-intercept-esc 'always)
+ (and evil-intercept-esc
+ (eq (terminal-live-p term) t))) ; only patch tty
+ (not (terminal-parameter term 'evil-esc-map)))
+ (let ((evil-esc-map (lookup-key input-decode-map [?\e])))
+ (set-terminal-parameter term 'evil-esc-map evil-esc-map)
+ (define-key input-decode-map [?\e]
+ `(menu-item "" ,evil-esc-map :filter ,#'evil-esc)))))))
+
+(defun evil-deinit-esc (frame)
+ "Restore `input-decode-map' in terminal."
+ (with-selected-frame frame
+ (let ((term (frame-terminal frame)))
+ (when (terminal-live-p term)
+ (let ((evil-esc-map (terminal-parameter term 'evil-esc-map)))
+ (when evil-esc-map
+ (define-key input-decode-map [?\e] evil-esc-map)
+ (set-terminal-parameter term 'evil-esc-map nil)))))))
+
+(defun evil-esc (map)
+ "Translate \\e to `escape' if no further event arrives.
+This function is used to translate a \\e event either to `escape'
+or to the standard ESC prefix translation map. If \\e arrives,
+this function waits for `evil-esc-delay' seconds for another
+event. If no other event arrives, the event is translated to
+`escape', otherwise it is translated to the standard ESC prefix
+map stored in `input-decode-map'. If `evil-inhibit-esc' is
+non-nil or if evil is in emacs state, the event is always
+translated to the ESC prefix.
+
+The translation to `escape' happens only if the current command
+has indeed been triggered by \\e. In other words, this will only
+happen when the keymap is accessed from `read-key-sequence'. In
+particular, if it is access from `define-key' the returned
+mapping will always be the ESC prefix map."
+ (if (and (not evil-inhibit-esc)
+ (or evil-local-mode (evil-ex-p)
+ (active-minibuffer-window))
+ (not (evil-emacs-state-p))
+ (let ((keys (this-single-command-keys)))
+ (and (> (length keys) 0)
+ (= (aref keys (1- (length keys))) ?\e)))
+ (sit-for evil-esc-delay))
+ (prog1 [escape]
+ (when defining-kbd-macro
+ (end-kbd-macro)
+ (setq last-kbd-macro (vconcat last-kbd-macro [escape]))
+ (start-kbd-macro t t)))
+ map))
+
+(defun evil-state-p (sym)
+ "Whether SYM is the name of a state."
+ (assq sym evil-state-properties))
+
+(defun evil-state-keymaps (state &rest excluded)
+ "Return a keymap alist of keymaps activated by STATE.
+If STATE references other states in its :enable property,
+these states are recursively processed and added to the list.
+\(The EXCLUDED argument is an internal safeguard against
+infinite recursion, keeping track of processed states.)"
+ (let* ((state (or state evil-state))
+ (enable (evil-state-property state :enable))
+ (map (cons
+ (evil-state-property state :mode)
+ (evil-state-property state :keymap t)))
+ (local-map (cons
+ (evil-state-property state :local)
+ (evil-state-property state :local-keymap t)))
+ (minor-mode-maps (evil-state-minor-mode-keymaps state))
+ (aux-maps (evil-state-auxiliary-keymaps state))
+ (overriding-maps
+ (evil-state-overriding-keymaps state))
+ (intercept-maps
+ (evil-state-intercept-keymaps state))
+ (result `(,intercept-maps))
+ (remove-duplicates (null excluded)))
+ (unless (memq state enable)
+ (setq enable (cons state enable)))
+ ;; process STATE's :enable property
+ (dolist (entry enable)
+ (cond
+ ((memq entry excluded))
+ ;; the keymaps for STATE
+ ((eq entry state)
+ (setq result `(,@result
+ (,local-map)
+ ,minor-mode-maps
+ ,aux-maps
+ ,overriding-maps
+ (,map)))
+ (push state excluded))
+ ;; the keymaps for another state: call `evil-state-keymaps'
+ ;; recursively, but keep track of processed states
+ ((evil-state-p entry)
+ (setq result `(,@result
+ ,(apply #'evil-state-keymaps entry excluded))))
+ ;; a single keymap
+ ((or (keymapp entry)
+ (and (keymapp (symbol-value entry))
+ (setq entry (symbol-value entry)))
+ (setq entry (evil-keymap-for-mode entry)))
+ (setq result `(,@result
+ ((,(evil-mode-for-keymap entry t) .
+ ,entry)))))))
+ ;; postpone the expensive filtering of duplicates to the top level
+ (if remove-duplicates
+ (apply #'evil-concat-keymap-alists result)
+ (apply #'append result))))
+
+(defun evil-normalize-keymaps (&optional state)
+ "Create a buffer-local value for `evil-mode-map-alist'.
+This is a keymap alist, determined by the current state
+\(or by STATE if specified)."
+ (let ((state (or state evil-state))
+ (excluded '(nil t))
+ map mode temp)
+ ;; initialize buffer-local keymaps as necessary
+ (evil-initialize-local-keymaps)
+ ;; deactivate keymaps of previous state
+ (dolist (entry evil-mode-map-alist)
+ (setq mode (car entry)
+ map (cdr entry))
+ ;; don't deactivate overriding keymaps;
+ ;; they are toggled by their associated mode
+ (if (or (memq mode excluded)
+ (evil-intercept-keymap-p map)
+ (evil-overriding-keymap-p map)
+ (evil-auxiliary-keymap-p map)
+ (evil-minor-mode-keymap-p map))
+ (push mode excluded)
+ (and (fboundp mode) (symbol-value mode) (funcall mode -1))
+ (set mode nil)))
+ (setq evil-mode-map-alist nil)
+ ;; activate keymaps of current state
+ (when state
+ (setq temp (evil-state-keymaps state))
+ (dolist (entry temp)
+ (setq mode (car entry)
+ map (cdr entry))
+ (unless (or (and (boundp mode) (symbol-value mode))
+ ;; the minor-mode keymaps include modes that are not
+ ;; necessarily active
+ (evil-minor-mode-keymap-p map))
+ (when (fboundp mode)
+ (funcall mode 1))
+ (set mode t))
+ ;; refresh the keymap in case it has changed
+ ;; (e.g., `evil-operator-shortcut-map' is
+ ;; reset on toggling)
+ (if (or (memq mode excluded)
+ (evil-intercept-keymap-p map)
+ (evil-overriding-keymap-p map)
+ (evil-auxiliary-keymap-p map)
+ (evil-minor-mode-keymap-p map))
+ (push mode excluded)
+ (setcdr entry (or (evil-keymap-for-mode mode) map))))
+ ;; update `evil-mode-map-alist'
+ (setq evil-mode-map-alist temp))))
+
+(defun evil-mode-for-keymap (keymap &optional default)
+ "Return the minor mode associated with KEYMAP.
+Return DEFAULT if no mode is found.
+See also `evil-keymap-for-mode'."
+ (let ((map (if (keymapp keymap) keymap (symbol-value keymap)))
+ (var (when (symbolp keymap) keymap)))
+ ;; Check Evil variables first for speed purposes.
+ ;; If all else fails, check `minor-mode-map-alist'.
+ (or (when var
+ (or (car (rassq var evil-global-keymaps-alist))
+ (car (rassq var evil-local-keymaps-alist))))
+ (car (rassq map (mapcar #'(lambda (e)
+ ;; from (MODE-VAR . MAP-VAR)
+ ;; to (MODE-VAR . MAP)
+ (cons (car-safe e)
+ (symbol-value (cdr-safe e))))
+ (append evil-global-keymaps-alist
+ evil-local-keymaps-alist))))
+ (car (rassq map minor-mode-map-alist))
+ default)))
+
+(defun evil-keymap-for-mode (mode &optional variable)
+ "Return the keymap associated with MODE.
+Return the keymap variable if VARIABLE is non-nil.
+See also `evil-mode-for-keymap'."
+ (let* ((var (or (cdr (assq mode evil-global-keymaps-alist))
+ (cdr (assq mode evil-local-keymaps-alist))))
+ (map (or (symbol-value var)
+ (cdr (assq mode minor-mode-map-alist)))))
+ (if variable var map)))
+
+(defun evil-state-auxiliary-keymaps (state)
+ "Return a keymap alist of auxiliary keymaps for STATE."
+ (let ((state (or state evil-state))
+ aux result)
+ (dolist (map (current-active-maps) (nreverse result))
+ (when (setq aux (evil-get-auxiliary-keymap map state))
+ (push (cons (evil-mode-for-keymap map t) aux) result)))))
+
+(defun evil-state-minor-mode-keymaps (state)
+ "Return a keymap alist of minor-mode keymaps for STATE."
+ (cdr (assq (or state evil-state) evil-minor-mode-keymaps-alist)))
+
+(defun evil-state-overriding-keymaps (&optional state)
+ "Return a keymap alist of overriding keymaps for STATE."
+ (let* ((state (or state evil-state))
+ result)
+ (dolist (map (current-active-maps))
+ (when (setq map (evil-overriding-keymap-p map state))
+ (push (cons (evil-mode-for-keymap map t) map) result)))
+ (nreverse result)))
+
+(defun evil-state-intercept-keymaps (&optional state)
+ "Return a keymap alist of intercept keymaps for STATE."
+ (let* ((state (or state evil-state))
+ result)
+ (dolist (map (current-active-maps))
+ (when (setq map (or (evil-intercept-keymap-p map state)
+ (evil-intercept-keymap-p
+ (evil-get-auxiliary-keymap map state) state)))
+ (push (cons (evil-mode-for-keymap map t) map) result)))
+ (setq result (nreverse result))
+ result))
+
+(defun evil-set-auxiliary-keymap (map state &optional aux)
+ "Set the auxiliary keymap for MAP in STATE to AUX.
+If AUX is nil, create a new auxiliary keymap."
+ (unless aux (setq aux (make-sparse-keymap)))
+ (unless (evil-auxiliary-keymap-p aux)
+ (evil-set-keymap-prompt
+ aux (format "Auxiliary keymap for %s"
+ (or (evil-state-property state :name)
+ (format "%s state" state)))))
+ (define-key map (vector (intern (format "%s-state" state))) aux)
+ aux)
+
+(defun evil-get-auxiliary-keymap (map state &optional create ignore-parent)
+ "Get the auxiliary keymap for MAP in STATE.
+If CREATE is non-nil, create an auxiliary keymap
+if MAP does not have one. If CREATE and
+IGNORE-PARENT are non-nil then a new auxiliary
+keymap is created even if the parent of MAP has
+one already."
+ (when state
+ (let* ((key (vector (intern (format "%s-state" state))))
+ (parent-aux (when (and ignore-parent
+ (keymap-parent map))
+ (lookup-key (keymap-parent map) key)))
+ (aux (lookup-key map key)))
+ (cond
+ ((and ignore-parent
+ (equal parent-aux aux)
+ create)
+ (evil-set-auxiliary-keymap map state))
+ ((evil-auxiliary-keymap-p aux)
+ aux)
+ (create
+ (evil-set-auxiliary-keymap map state))))))
+
+(defun evil-get-minor-mode-keymap (state mode)
+ "Get the auxiliary keymap for MODE in STATE, creating one if it
+does not already exist."
+ (let ((state-entry (assq state evil-minor-mode-keymaps-alist)))
+ (if (and state-entry
+ (assq mode state-entry))
+ (cdr (assq mode state-entry))
+ (let ((map (make-sparse-keymap)))
+ (evil-set-keymap-prompt
+ map (format "Minor-mode keymap for %s in %s"
+ mode
+ (or (evil-state-property state :name)
+ (format "%s state" state))))
+ (if state-entry
+ (setcdr state-entry
+ (append (list (cons mode map)) (cdr state-entry)))
+ (push (cons state (list (cons mode map)))
+ evil-minor-mode-keymaps-alist))
+ map))))
+
+(defun evil-auxiliary-keymap-p (map)
+ "Whether MAP is an auxiliary keymap."
+ (let ((prompt (keymap-prompt map)))
+ (when prompt (string-prefix-p "Auxiliary keymap" prompt))))
+
+(defun evil-minor-mode-keymap-p (map)
+ "Whether MAP is a minor-mode keymap."
+ (let ((prompt (keymap-prompt map)))
+ (when prompt (string-prefix-p "Minor-mode keymap" prompt))))
+
+(defun evil-intercept-keymap-p (map &optional state)
+ "Whether MAP is an intercept keymap for STATE.
+If STATE is nil, it means any state."
+ (let ((entry (and (keymapp map)
+ (lookup-key map [intercept-state]))))
+ (cond
+ ((null entry) nil)
+ ((null state) map)
+ ((eq entry state) map)
+ ((eq entry 'all) map))))
+
+(defun evil-overriding-keymap-p (map &optional state)
+ "Whether MAP is an overriding keymap for STATE.
+If STATE is nil, it means any state."
+ (let ((entry (and (keymapp map)
+ (lookup-key map [override-state]))))
+ (cond
+ ((null entry) nil)
+ ((keymapp entry) (evil-overriding-keymap-p entry state))
+ ((null state) map)
+ ((eq entry state) map)
+ ((eq entry 'all) map))))
+
+(defun evil-intercept-keymap-state (map)
+ "Return the state for the intercept keymap MAP.
+A return value of t means all states."
+ (let ((state (lookup-key map [intercept-state] map)))
+ (cond
+ ((keymapp state)
+ (evil-intercept-keymap-state state))
+ ((eq state 'all)
+ t)
+ (t
+ state))))
+
+(defun evil-overriding-keymap-state (map)
+ "Return the state for the overriding keymap MAP.
+A return value of t means all states."
+ (let ((state (lookup-key map [override-state] map)))
+ (cond
+ ((keymapp state)
+ (evil-overriding-keymap-state state))
+ ((eq state 'all)
+ t)
+ (t
+ state))))
+
+(defun evil-set-leader (state key &optional localleader)
+ "Set KEY to trigger leader bindings in STATE.
+KEY should be in the form produced by `kbd'. STATE is one of
+`normal', `insert', `visual', `replace', `operator', `motion',
+`emacs', a list of one or more of these, or `nil', which means
+all of the above. If LOCALLEADER is non-nil, set the local leader
+instead."
+ (let* ((all-states '(normal insert visual replace operator motion emacs))
+ (states (cond ((null state) all-states)
+ ((consp state) state)
+ (t (list state))))
+ (leaderkey (if localleader [localleader] [leader]))
+ (binding
+ `(menu-item "" nil :filter ,(lambda (_cmd) (key-binding leaderkey)))))
+ (dolist (state states)
+ (evil-global-set-key state key binding))))
+
+(defmacro evil-define-key (state keymap key def &rest bindings)
+ "Create a STATE binding from KEY to DEF for KEYMAP.
+STATE is one of `normal', `insert', `visual', `replace',
+`operator', `motion', `emacs', or a list of one or more of
+these. Omitting a state by using `nil' corresponds to a standard
+Emacs binding using `define-key'. The remaining arguments are
+like those of `define-key'. For example:
+
+ (evil-define-key \\='normal foo-map \"a\" \\='bar)
+
+This creates a binding from `a' to `bar' in normal state, which
+is active whenever `foo-map' is active. Using nil for the state,
+the following lead to identical bindings:
+
+ (evil-define-key nil foo-map \"a\" \\='bar)
+ (define-key foo-map \"a\" \\='bar)
+
+It is possible to specify multiple states and/or bindings at
+once:
+
+ (evil-define-key \\='(normal visual) foo-map
+ \"a\" \\='bar
+ \"b\" \\='foo)
+
+If `foo-map' has not been initialized yet, this macro adds an
+entry to `after-load-functions', delaying execution as necessary.
+
+KEYMAP may also be a quoted symbol. If the symbol is `global', the
+global evil keymap corresponding to the state(s) is used, meaning
+the following lead to identical bindings:
+
+ (evil-define-key \\='normal \\='global \"a\" \\='bar)
+ (evil-global-set-key \\='normal \"a\" \\='bar)
+
+The symbol `local' may also be used, which corresponds to using
+`evil-local-set-key'. If a quoted symbol is used that is not
+`global' or `local', it is assumed to be the name of a minor
+mode, in which case `evil-define-minor-mode-key' is used.
+
+KEY is an internal Emacs representation of a key, as for
+`define-key'. To bind key sequences that use modifier keys such
+as \"C-a\" or \"M-a\", convert the key sequences using `kbd'.
+For example:
+
+ (evil-define-key \\='normal foo-map (kbd \"C-a\") \\='bar)"
+ (declare (indent defun))
+ (cond
+ ((member keymap '('global 'local))
+ `(evil-define-key* ,state ,keymap ,key ,def ,@bindings))
+ ((eq (car-safe keymap) 'quote)
+ `(evil-define-minor-mode-key ,state ,keymap ,key ,def ,@bindings))
+ (t `(evil-with-delay ,(if (symbolp keymap)
+ ;; BEWARE: Can't work for lexically scoped vars
+ `(and (boundp ',keymap) (keymapp ,keymap))
+ `(keymapp ,keymap))
+ (after-load-functions
+ t nil ,(format "evil-define-key-in-%s"
+ (if (symbolp keymap) keymap 'keymap)))
+ (with-demoted-errors "Error in evil-define-key: %S"
+ (evil-define-key* ,state ,keymap ,key ,def ,@bindings))))))
+(defalias 'evil-declare-key #'evil-define-key)
+
+(defun evil-define-key* (state keymap key def &rest bindings)
+ "Create a STATE binding from KEY to DEF for KEYMAP.
+STATE is one of normal, insert, visual, replace, operator,
+motion, emacs, or a list of one or more of these. Omitting a
+state by using nil corresponds to a standard Emacs binding using
+`define-key' The remaining arguments are like those of
+`define-key'. For example:
+
+ (evil-define-key* \\='normal foo-map \"a\" \\='bar)
+
+This creates a binding from \"a\" to bar in Normal state, which
+is active whenever foo-map is active. Using nil for the state,
+the following are equivalent:
+
+ (evil-define-key* nil foo-map \"a\" \\='bar)
+
+ (define-key foo-map \"a\" \\='bar)
+
+ It is possible to specify multiple states and/or bindings at
+ once:
+
+ (evil-define-key* \\='(normal visual) foo-map
+ \"a\" \\='bar
+ \"b\" \\='foo)
+
+KEYMAP may also be a quoted symbol. If the symbol is global, the
+global evil keymap corresponding to the state(s) is used, meaning
+the following are equivalent:
+
+ (evil-define-key* \\='normal \\='global \"a\" \\='bar)
+
+ (evil-global-set-key \\='normal \"a\" \\='bar)
+
+The symbol local may also be used, which corresponds to using
+`evil-local-set-key'.
+
+The use is nearly identical to `evil-define-key' with the
+exception that this is a function and not a macro (and so will
+not be expanded when compiled which can have unintended
+consequences). `evil-define-key*' also does not defer any
+bindings like `evil-define-key' does using `evil-with-delay'. This
+allows errors in the bindings to be caught immediately, and makes
+its behavior more predictable."
+ (declare (indent defun))
+ (let ((maps
+ (if state
+ (mapcar
+ (lambda (st)
+ (cond ((eq keymap 'global)
+ (evil-state-property st :keymap t))
+ ((eq keymap 'local)
+ (evil-state-property st :local-keymap t))
+ (t
+ (evil-get-auxiliary-keymap keymap st t t))))
+ (if (listp state) state (list state)))
+ (list
+ (cond ((eq keymap 'global)
+ global-map)
+ ((eq keymap 'local)
+ ;; see `local-set-key'
+ (or (current-local-map)
+ (let ((map (make-sparse-keymap)))
+ (use-local-map map)
+ map)))
+ (t
+ keymap))))))
+ (while key
+ (dolist (map maps)
+ (define-key map key def))
+ (setq key (pop bindings)
+ def (pop bindings)))
+ ;; ensure the prompt string comes first
+ (dolist (map maps)
+ (evil-set-keymap-prompt map (keymap-prompt map)))))
+
+(defun evil-define-minor-mode-key (state mode key def &rest bindings)
+ "Similar to `evil-define-key' but the bindings are associated
+with the minor-mode symbol MODE instead of a particular map.
+Associating bindings with a mode symbol instead of a map allows
+evil to use Emacs' built-in mechanisms to enable the bindings
+automatically when MODE is active without relying on calling
+`evil-normalize-keymaps'. Another less significant difference is
+that the bindings can be created immediately, because this
+function only uses the symbol MODE and does not rely on its
+value.
+
+See `evil-define-key' for the usage of STATE, KEY, DEF and
+BINDINGS."
+ (declare (indent defun))
+ (let ((maps (mapcar
+ (lambda (st)
+ (evil-get-minor-mode-keymap st mode))
+ (if (listp state) state (list state)))))
+ (while key
+ (dolist (map maps)
+ (define-key map key def))
+ (setq key (pop bindings)
+ def (pop bindings)))))
+
+(defmacro evil-add-hjkl-bindings (keymap &optional state &rest bindings)
+ "Add \"h\", \"j\", \"k\", \"l\" bindings to KEYMAP in STATE.
+Add additional BINDINGS if specified."
+ (declare (indent defun))
+ `(evil-define-key ,state ,keymap
+ "h" (lookup-key evil-motion-state-map "h")
+ "j" (lookup-key evil-motion-state-map "j")
+ "k" (lookup-key evil-motion-state-map "k")
+ "l" (lookup-key evil-motion-state-map "l")
+ ":" (lookup-key evil-motion-state-map ":")
+ ,@bindings))
+
+;; may be useful for programmatic purposes
+(defun evil-global-set-key (state key def)
+ "Bind KEY to DEF in STATE."
+ (define-key (evil-state-property state :keymap t) key def))
+
+(defun evil-local-set-key (state key def)
+ "Bind KEY to DEF in STATE in the current buffer."
+ (define-key (evil-state-property state :local-keymap t) key def))
+
+;; Advise these functions as they may activate an overriding keymap or
+;; a keymap with state bindings; if so, refresh `evil-mode-map-alist'.
+(advice-add 'use-global-map :after #'evil--do-normalize-keymaps)
+(advice-add 'use-local-map :after #'evil--do-normalize-keymaps)
+(defun evil--do-normalize-keymaps (&rest _)
+ "Refresh Evil keymaps."
+ (evil-normalize-keymaps))
+
+
+(defmacro evil-define-state (state doc &rest body)
+ "Define an Evil state STATE.
+DOC is a general description and shows up in all docstrings;
+the first line of the string should be the full name of the state.
+
+BODY is executed each time the state is enabled or disabled.
+
+Optional keyword arguments:
+- `:tag' - the mode line indicator, e.g. \"<T>\".
+- `:message' - string shown in the echo area when the state is
+ activated.
+- `:cursor' - default cursor specification.
+- `:enable' - list of other state keymaps to enable when in this
+ state.
+- `:entry-hook' - list of functions to run when entering this state.
+- `:exit-hook' - list of functions to run when exiting this state.
+- `:suppress-keymap' - if non-nil, effectively disables bindings to
+ `self-insert-command' by making `evil-suppress-map' the parent of
+ the global state keymap.
+
+The global keymap of this state will be `evil-test-state-map',
+the local keymap will be `evil-test-state-local-map', and so on.
+
+\(fn STATE DOC [[KEY VAL]...] BODY...)"
+ (declare (indent defun)
+ (doc-string 2)
+ (debug (&define name
+ [&optional stringp]
+ [&rest [keywordp sexp]]
+ def-body)))
+ (let* ((name (and (string-match "^\\(.+\\)\\(\\(?:.\\|\n\\)*\\)" doc)
+ (match-string 1 doc)))
+ (doc (match-string 2 doc))
+ (name (and (string-match "^\\(.+?\\)\\.?$" name)
+ (match-string 1 name)))
+ (doc (if (or (null doc) (string= doc "")) ""
+ (format "\n%s" doc)))
+ (toggle (intern (format "evil-%s-state" state)))
+ (mode (intern (format "%s-minor-mode" toggle)))
+ (keymap (intern (format "%s-map" toggle)))
+ (local (intern (format "%s-local-minor-mode" toggle)))
+ (local-keymap (intern (format "%s-local-map" toggle)))
+ (tag (intern (format "%s-tag" toggle)))
+ (message (intern (format "%s-message" toggle)))
+ (cursor (intern (format "%s-cursor" toggle)))
+ (entry-hook (intern (format "%s-entry-hook" toggle)))
+ (exit-hook (intern (format "%s-exit-hook" toggle)))
+ (modes (intern (format "%s-modes" toggle)))
+ (predicate (intern (format "%s-p" toggle)))
+ arg cursor-value enable entry-hook-value exit-hook-value
+ input-method key message-value suppress-keymap tag-value)
+ ;; collect keywords
+ (while (keywordp (car-safe body))
+ (setq key (pop body)
+ arg (pop body))
+ (cond
+ ((eq key :tag)
+ (setq tag-value arg))
+ ((eq key :message)
+ (setq message-value arg))
+ ((eq key :cursor)
+ (setq cursor-value arg))
+ ((eq key :entry-hook)
+ (setq entry-hook-value arg)
+ (unless (listp entry-hook-value)
+ (setq entry-hook-value (list entry-hook-value))))
+ ((eq key :exit-hook)
+ (setq exit-hook-value arg)
+ (unless (listp exit-hook-value)
+ (setq exit-hook-value (list exit-hook-value))))
+ ((eq key :enable)
+ (setq enable arg))
+ ((eq key :input-method)
+ (setq input-method arg))
+ ((eq key :suppress-keymap)
+ (setq suppress-keymap arg))))
+
+ ;; macro expansion
+ `(progn
+ ;; Save the state's properties in `evil-state-properties' for
+ ;; runtime lookup. Among other things, this information is used
+ ;; to determine what keymaps should be activated by the state
+ ;; (and, when processing :enable, what keymaps are activated by
+ ;; other states). We cannot know this at compile time because
+ ;; it depends on the current buffer and its active keymaps
+ ;; (to which we may have assigned state bindings), as well as
+ ;; states whose definitions may not have been processed yet.
+ (let ((plist (list
+ :name ',name
+ :toggle ',toggle
+ :mode (defvar ,mode nil
+ ,(format "Non-nil if %s is enabled.
+Use the command `%s' to change this variable." name toggle))
+ :keymap (defvar ,keymap (make-sparse-keymap)
+ ,(format "Keymap for %s." name))
+ :local (defvar ,local nil
+ ,(format "Non-nil if %s is enabled.
+Use the command `%s' to change this variable." name toggle))
+ :local-keymap (defvar ,local-keymap nil
+ ,(format "Buffer-local keymap for %s." name))
+ :tag (defvar ,tag ,tag-value
+ ,(format "Mode line tag for %s." name))
+ :message (defvar ,message ,message-value
+ ,(format "Echo area message for %s." name))
+ :cursor (defvar ,cursor ',cursor-value
+ ,(format "Cursor for %s.
+May be a cursor type as per `cursor-type', a color string as passed
+to `set-cursor-color', a zero-argument function for changing the
+cursor, or a list of the above.
+
+If set to nil, the value of `evil-default-cursor' is used; if you
+want the nil `cursor-type' (i.e., you want to disable the cursor),
+set this variable to (list nil)." name))
+ :entry-hook (defvar ,entry-hook nil
+ ,(format "Hooks to run when entering %s." name))
+ :exit-hook (defvar ,exit-hook nil
+ ,(format "Hooks to run when exiting %s." name))
+ :modes (defvar ,modes nil
+ ,(format "Modes that should come up in %s." name))
+ :input-method ',input-method
+ :predicate ',predicate
+ :enable ',enable)))
+ (evil--add-to-alist evil-state-properties ',state plist))
+
+ ,@(when suppress-keymap
+ `((set-keymap-parent ,keymap evil-suppress-map)))
+
+ (dolist (func ',entry-hook-value) (add-hook ',entry-hook func))
+ (dolist (func ',exit-hook-value) (add-hook ',exit-hook func))
+
+ (defun ,predicate (&optional state)
+ ,(format "Whether the current state is %s.
+\(That is, whether `evil-state' is `%s'.)" name state)
+ (and evil-local-mode
+ (eq (or state evil-state) ',state)))
+
+ ;; define state function
+ (defun ,toggle (&optional arg)
+ ,(format "Enable %s. Disable with negative ARG.
+If ARG is nil, don't display a message in the echo area.%s" name doc)
+ (interactive)
+ (cond
+ ((and (numberp arg) (< arg 1))
+ (setq evil-previous-state evil-state
+ evil-state nil)
+ (let ((evil-state ',state))
+ (run-hooks ',exit-hook)
+ (setq evil-state nil)
+ (evil-normalize-keymaps)
+ ,@body))
+ (t
+ (unless evil-local-mode (evil-local-mode))
+ (let ((evil-next-state ',state)
+ input-method-activate-hook input-method-deactivate-hook)
+ (evil-change-state nil)
+ (setq evil-state ',state)
+ (evil--add-to-alist evil-previous-state-alist
+ ',state evil-previous-state)
+ (let ((evil-state ',state))
+ (evil-normalize-keymaps)
+ (if ',input-method
+ (activate-input-method evil-input-method)
+ ;; BUG #475: Deactivate the current input method only
+ ;; if there is a function to deactivate it, otherwise
+ ;; an error would be raised. This strange situation
+ ;; should not arise in general and there should
+ ;; probably be a better way to handle this situation.
+ (when deactivate-current-input-method-function
+ (deactivate-input-method)))
+ (unless evil-no-display
+ (when (eq (window-buffer) (current-buffer))
+ (evil-refresh-cursor ',state))
+ (evil-refresh-mode-line ',state))
+ ,@body
+ (run-hooks ',entry-hook)
+ (when (and evil-echo-state
+ arg (not evil-no-display) ,message)
+ (if (functionp ,message)
+ (funcall ,message)
+ (evil-echo "%s" ,message))))))))
+
+ (evil-add-command-properties ',toggle :keep-visual t :suppress-operator t)
+
+ (evil-define-keymap ,keymap nil
+ :mode ,mode
+ :func nil)
+
+ (evil-define-keymap ,local-keymap nil
+ :mode ,local
+ :local t
+ :func nil)
+
+ ',state)))
+
+(provide 'evil-core)
+
+;;; evil-core.el ends here
diff --git a/.config/emacs/lisp/evil/evil-development.el b/.config/emacs/lisp/evil/evil-development.el
new file mode 100644
index 0000000..60da92d
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-development.el
@@ -0,0 +1,50 @@
+;;; evil-development.el --- Useful features for Evil developers -*- lexical-binding: t -*-
+
+;; Author: Justin Burkett <justin at burkett dot cc>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+;;; Teach imenu about evil macros
+
+(with-eval-after-load 'lisp-mode
+ (when (boundp 'lisp-imenu-generic-expression)
+ (dolist (macro '("interactive-code"
+ "type"
+ "text-object"
+ "motion"
+ "command"
+ "operator"))
+ (let ((macro-name (format "evil-%s" macro)))
+ (unless (assoc macro-name lisp-imenu-generic-expression)
+ (push (list
+ macro-name
+ (format "^\\s-*(evil-define-%s\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)"
+ macro)
+ 1)
+ lisp-imenu-generic-expression))))))
+
+(provide 'evil-development)
+
+;;; evil-development.el ends here
diff --git a/.config/emacs/lisp/evil/evil-digraphs.el b/.config/emacs/lisp/evil/evil-digraphs.el
new file mode 100644
index 0000000..2bd3687
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-digraphs.el
@@ -0,0 +1,1735 @@
+;;; evil-digraphs.el --- Digraphs -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'evil-vars)
+
+(defgroup evil-digraphs nil
+ "Digraph support based on RFC 1345."
+ :group 'evil
+ :prefix "evil-digraph-")
+
+(defcustom evil-digraphs-table-user nil
+ "List of user-defined digraphs.
+Entries have the form ((?CHAR1 ?CHAR2) . ?DIGRAPH). That is,
+a cons cell of the digraph and its character replacement,
+where the digraph is a list of two characters.
+See also `evil-digraphs-table'."
+ :type '(alist :key-type (list character character)
+ :value-type character))
+
+(defconst evil-digraphs-table
+ '(((?N ?U) . ?\x00)
+ ((?S ?H) . ?\x01)
+ ((?S ?X) . ?\x02)
+ ((?E ?X) . ?\x03)
+ ((?E ?T) . ?\x04)
+ ((?E ?Q) . ?\x05)
+ ((?A ?K) . ?\x06)
+ ((?B ?L) . ?\x07)
+ ((?B ?S) . ?\x08)
+ ((?H ?T) . ?\x09)
+ ((?L ?F) . ?\x0a)
+ ((?V ?T) . ?\x0b)
+ ((?F ?F) . ?\x0c)
+ ((?C ?R) . ?\x0d)
+ ((?S ?O) . ?\x0e)
+ ((?S ?I) . ?\x0f)
+ ((?D ?L) . ?\x10)
+ ((?D ?1) . ?\x11)
+ ((?D ?2) . ?\x12)
+ ((?D ?3) . ?\x13)
+ ((?D ?4) . ?\x14)
+ ((?N ?K) . ?\x15)
+ ((?S ?Y) . ?\x16)
+ ((?E ?B) . ?\x17)
+ ((?C ?N) . ?\x18)
+ ((?E ?M) . ?\x19)
+ ((?S ?B) . ?\x1a)
+ ((?E ?C) . ?\x1b)
+ ((?F ?S) . ?\x1c)
+ ((?G ?S) . ?\x1d)
+ ((?R ?S) . ?\x1e)
+ ((?U ?S) . ?\x1f)
+ ((?S ?P) . ?\x20)
+ ((?N ?b) . ?\x23)
+ ((?D ?O) . ?\x24)
+ ((?A ?t) . ?\x40)
+ ((?< ?\() . ?\x5b)
+ ((?/ ?/) . ?\x5c)
+ ((?\) ?>) . ?\x5d)
+ ((?' ?>) . ?\x5e)
+ ((?' ?!) . ?\x60)
+ ((?\( ?!) . ?\x7b)
+ ((?! ?!) . ?\x7c)
+ ((?! ?\)) . ?\x7d)
+ ((?' ??) . ?\x7e)
+ ((?D ?T) . ?\x7f)
+ ((?P ?A) . ?\x80)
+ ((?H ?O) . ?\x81)
+ ((?B ?H) . ?\x82)
+ ((?N ?H) . ?\x83)
+ ((?I ?N) . ?\x84)
+ ((?N ?L) . ?\x85)
+ ((?S ?A) . ?\x86)
+ ((?E ?S) . ?\x87)
+ ((?H ?S) . ?\x88)
+ ((?H ?J) . ?\x89)
+ ((?V ?S) . ?\x8a)
+ ((?P ?D) . ?\x8b)
+ ((?P ?U) . ?\x8c)
+ ((?R ?I) . ?\x8d)
+ ((?S ?2) . ?\x8e)
+ ((?S ?3) . ?\x8f)
+ ((?D ?C) . ?\x90)
+ ((?P ?1) . ?\x91)
+ ((?P ?2) . ?\x92)
+ ((?T ?S) . ?\x93)
+ ((?C ?C) . ?\x94)
+ ((?M ?W) . ?\x95)
+ ((?S ?G) . ?\x96)
+ ((?E ?G) . ?\x97)
+ ((?S ?S) . ?\x98)
+ ((?G ?C) . ?\x99)
+ ((?S ?C) . ?\x9a)
+ ((?C ?I) . ?\x9b)
+ ((?S ?T) . ?\x9c)
+ ((?O ?C) . ?\x9d)
+ ((?P ?M) . ?\x9e)
+ ((?A ?C) . ?\x9f)
+ ((?N ?S) . ?\xa0)
+ ((?! ?I) . ?\xa1)
+ ((?C ?t) . ?\xa2)
+ ((?P ?d) . ?\xa3)
+ ((?C ?u) . ?\xa4)
+ ((?Y ?e) . ?\xa5)
+ ((?B ?B) . ?\xa6)
+ ((?S ?E) . ?\xa7)
+ ((?' ?:) . ?\xa8)
+ ((?C ?o) . ?\xa9)
+ ((?- ?a) . ?\xaa)
+ ((?< ?<) . ?\xab)
+ ((?N ?O) . ?\xac)
+ ((?- ?-) . ?\xad)
+ ((?R ?g) . ?\xae)
+ ((?' ?m) . ?\xaf)
+ ((?D ?G) . ?\xb0)
+ ((?+ ?-) . ?\xb1)
+ ((?2 ?S) . ?\xb2)
+ ((?3 ?S) . ?\xb3)
+ ((?' ?') . ?\xb4)
+ ((?M ?y) . ?\xb5)
+ ((?P ?I) . ?\xb6)
+ ((?. ?M) . ?\xb7)
+ ((?' ?,) . ?\xb8)
+ ((?1 ?S) . ?\xb9)
+ ((?- ?o) . ?\xba)
+ ((?> ?>) . ?\xbb)
+ ((?1 ?4) . ?\xbc)
+ ((?1 ?2) . ?\xbd)
+ ((?3 ?4) . ?\xbe)
+ ((?? ?I) . ?\xbf)
+ ((?A ?!) . ?\xc0)
+ ((?A ?') . ?\xc1)
+ ((?A ?>) . ?\xc2)
+ ((?A ??) . ?\xc3)
+ ((?A ?:) . ?\xc4)
+ ((?A ?A) . ?\xc5)
+ ((?A ?E) . ?\xc6)
+ ((?C ?,) . ?\xc7)
+ ((?E ?!) . ?\xc8)
+ ((?E ?') . ?\xc9)
+ ((?E ?>) . ?\xca)
+ ((?E ?:) . ?\xcb)
+ ((?I ?!) . ?\xcc)
+ ((?I ?') . ?\xcd)
+ ((?I ?>) . ?\xce)
+ ((?I ?:) . ?\xcf)
+ ((?D ?-) . ?\xd0)
+ ((?N ??) . ?\xd1)
+ ((?O ?!) . ?\xd2)
+ ((?O ?') . ?\xd3)
+ ((?O ?>) . ?\xd4)
+ ((?O ??) . ?\xd5)
+ ((?O ?:) . ?\xd6)
+ ((?* ?X) . ?\xd7)
+ ((?O ?/) . ?\xd8)
+ ((?U ?!) . ?\xd9)
+ ((?U ?') . ?\xda)
+ ((?U ?>) . ?\xdb)
+ ((?U ?:) . ?\xdc)
+ ((?Y ?') . ?\xdd)
+ ((?T ?H) . ?\xde)
+ ((?s ?s) . ?\xdf)
+ ((?a ?!) . ?\xe0)
+ ((?a ?') . ?\xe1)
+ ((?a ?>) . ?\xe2)
+ ((?a ??) . ?\xe3)
+ ((?a ?:) . ?\xe4)
+ ((?a ?a) . ?\xe5)
+ ((?a ?e) . ?\xe6)
+ ((?c ?,) . ?\xe7)
+ ((?e ?!) . ?\xe8)
+ ((?e ?') . ?\xe9)
+ ((?e ?>) . ?\xea)
+ ((?e ?:) . ?\xeb)
+ ((?i ?!) . ?\xec)
+ ((?i ?') . ?\xed)
+ ((?i ?>) . ?\xee)
+ ((?i ?:) . ?\xef)
+ ((?d ?-) . ?\xf0)
+ ((?n ??) . ?\xf1)
+ ((?o ?!) . ?\xf2)
+ ((?o ?') . ?\xf3)
+ ((?o ?>) . ?\xf4)
+ ((?o ??) . ?\xf5)
+ ((?o ?:) . ?\xf6)
+ ((?- ?:) . ?\xf7)
+ ((?o ?/) . ?\xf8)
+ ((?u ?!) . ?\xf9)
+ ((?u ?') . ?\xfa)
+ ((?u ?>) . ?\xfb)
+ ((?u ?:) . ?\xfc)
+ ((?y ?') . ?\xfd)
+ ((?t ?h) . ?\xfe)
+ ((?y ?:) . ?\xff)
+ ((?A ?-) . ?\x0100)
+ ((?a ?-) . ?\x0101)
+ ((?A ?\() . ?\x0102)
+ ((?a ?\() . ?\x0103)
+ ((?A ?\;) . ?\x0104)
+ ((?a ?\;) . ?\x0105)
+ ((?C ?') . ?\x0106)
+ ((?c ?') . ?\x0107)
+ ((?C ?>) . ?\x0108)
+ ((?c ?>) . ?\x0109)
+ ((?C ?.) . ?\x010a)
+ ((?c ?.) . ?\x010b)
+ ((?C ?<) . ?\x010c)
+ ((?c ?<) . ?\x010d)
+ ((?D ?<) . ?\x010e)
+ ((?d ?<) . ?\x010f)
+ ((?D ?/) . ?\x0110)
+ ((?d ?/) . ?\x0111)
+ ((?E ?-) . ?\x0112)
+ ((?e ?-) . ?\x0113)
+ ((?E ?\() . ?\x0114)
+ ((?e ?\() . ?\x0115)
+ ((?E ?.) . ?\x0116)
+ ((?e ?.) . ?\x0117)
+ ((?E ?\;) . ?\x0118)
+ ((?e ?\;) . ?\x0119)
+ ((?E ?<) . ?\x011a)
+ ((?e ?<) . ?\x011b)
+ ((?G ?>) . ?\x011c)
+ ((?g ?>) . ?\x011d)
+ ((?G ?\() . ?\x011e)
+ ((?g ?\() . ?\x011f)
+ ((?G ?.) . ?\x0120)
+ ((?g ?.) . ?\x0121)
+ ((?G ?,) . ?\x0122)
+ ((?g ?,) . ?\x0123)
+ ((?H ?>) . ?\x0124)
+ ((?h ?>) . ?\x0125)
+ ((?H ?/) . ?\x0126)
+ ((?h ?/) . ?\x0127)
+ ((?I ??) . ?\x0128)
+ ((?i ??) . ?\x0129)
+ ((?I ?-) . ?\x012a)
+ ((?i ?-) . ?\x012b)
+ ((?I ?\() . ?\x012c)
+ ((?i ?\() . ?\x012d)
+ ((?I ?\;) . ?\x012e)
+ ((?i ?\;) . ?\x012f)
+ ((?I ?.) . ?\x0130)
+ ((?i ?.) . ?\x0131)
+ ((?I ?J) . ?\x0132)
+ ((?i ?j) . ?\x0133)
+ ((?J ?>) . ?\x0134)
+ ((?j ?>) . ?\x0135)
+ ((?K ?,) . ?\x0136)
+ ((?k ?,) . ?\x0137)
+ ((?k ?k) . ?\x0138)
+ ((?L ?') . ?\x0139)
+ ((?l ?') . ?\x013a)
+ ((?L ?,) . ?\x013b)
+ ((?l ?,) . ?\x013c)
+ ((?L ?<) . ?\x013d)
+ ((?l ?<) . ?\x013e)
+ ((?L ?.) . ?\x013f)
+ ((?l ?.) . ?\x0140)
+ ((?L ?/) . ?\x0141)
+ ((?l ?/) . ?\x0142)
+ ((?N ?') . ?\x0143)
+ ((?n ?') . ?\x0144)
+ ((?N ?,) . ?\x0145)
+ ((?n ?,) . ?\x0146)
+ ((?N ?<) . ?\x0147)
+ ((?n ?<) . ?\x0148)
+ ((?' ?n) . ?\x0149)
+ ((?N ?G) . ?\x014a)
+ ((?n ?g) . ?\x014b)
+ ((?O ?-) . ?\x014c)
+ ((?o ?-) . ?\x014d)
+ ((?O ?\() . ?\x014e)
+ ((?o ?\() . ?\x014f)
+ ((?O ?\") . ?\x0150)
+ ((?o ?\") . ?\x0151)
+ ((?O ?E) . ?\x0152)
+ ((?o ?e) . ?\x0153)
+ ((?R ?') . ?\x0154)
+ ((?r ?') . ?\x0155)
+ ((?R ?,) . ?\x0156)
+ ((?r ?,) . ?\x0157)
+ ((?R ?<) . ?\x0158)
+ ((?r ?<) . ?\x0159)
+ ((?S ?') . ?\x015a)
+ ((?s ?') . ?\x015b)
+ ((?S ?>) . ?\x015c)
+ ((?s ?>) . ?\x015d)
+ ((?S ?,) . ?\x015e)
+ ((?s ?,) . ?\x015f)
+ ((?S ?<) . ?\x0160)
+ ((?s ?<) . ?\x0161)
+ ((?T ?,) . ?\x0162)
+ ((?t ?,) . ?\x0163)
+ ((?T ?<) . ?\x0164)
+ ((?t ?<) . ?\x0165)
+ ((?T ?/) . ?\x0166)
+ ((?t ?/) . ?\x0167)
+ ((?U ??) . ?\x0168)
+ ((?u ??) . ?\x0169)
+ ((?U ?-) . ?\x016a)
+ ((?u ?-) . ?\x016b)
+ ((?U ?\() . ?\x016c)
+ ((?u ?\() . ?\x016d)
+ ((?U ?0) . ?\x016e)
+ ((?u ?0) . ?\x016f)
+ ((?U ?\") . ?\x0170)
+ ((?u ?\") . ?\x0171)
+ ((?U ?\;) . ?\x0172)
+ ((?u ?\;) . ?\x0173)
+ ((?W ?>) . ?\x0174)
+ ((?w ?>) . ?\x0175)
+ ((?Y ?>) . ?\x0176)
+ ((?y ?>) . ?\x0177)
+ ((?Y ?:) . ?\x0178)
+ ((?Z ?') . ?\x0179)
+ ((?z ?') . ?\x017a)
+ ((?Z ?.) . ?\x017b)
+ ((?z ?.) . ?\x017c)
+ ((?Z ?<) . ?\x017d)
+ ((?z ?<) . ?\x017e)
+ ((?O ?9) . ?\x01a0)
+ ((?o ?9) . ?\x01a1)
+ ((?O ?I) . ?\x01a2)
+ ((?o ?i) . ?\x01a3)
+ ((?y ?r) . ?\x01a6)
+ ((?U ?9) . ?\x01af)
+ ((?u ?9) . ?\x01b0)
+ ((?Z ?/) . ?\x01b5)
+ ((?z ?/) . ?\x01b6)
+ ((?E ?D) . ?\x01b7)
+ ((?A ?<) . ?\x01cd)
+ ((?a ?<) . ?\x01ce)
+ ((?I ?<) . ?\x01cf)
+ ((?i ?<) . ?\x01d0)
+ ((?O ?<) . ?\x01d1)
+ ((?o ?<) . ?\x01d2)
+ ((?U ?<) . ?\x01d3)
+ ((?u ?<) . ?\x01d4)
+ ((?A ?1) . ?\x01de)
+ ((?a ?1) . ?\x01df)
+ ((?A ?7) . ?\x01e0)
+ ((?a ?7) . ?\x01e1)
+ ((?A ?3) . ?\x01e2)
+ ((?a ?3) . ?\x01e3)
+ ((?G ?/) . ?\x01e4)
+ ((?g ?/) . ?\x01e5)
+ ((?G ?<) . ?\x01e6)
+ ((?g ?<) . ?\x01e7)
+ ((?K ?<) . ?\x01e8)
+ ((?k ?<) . ?\x01e9)
+ ((?O ?\;) . ?\x01ea)
+ ((?o ?\;) . ?\x01eb)
+ ((?O ?1) . ?\x01ec)
+ ((?o ?1) . ?\x01ed)
+ ((?E ?Z) . ?\x01ee)
+ ((?e ?z) . ?\x01ef)
+ ((?j ?<) . ?\x01f0)
+ ((?G ?') . ?\x01f4)
+ ((?g ?') . ?\x01f5)
+ ((?\; ?S) . ?\x02bf)
+ ((?' ?<) . ?\x02c7)
+ ((?' ?\() . ?\x02d8)
+ ((?' ?.) . ?\x02d9)
+ ((?' ?0) . ?\x02da)
+ ((?' ?\;) . ?\x02db)
+ ((?' ?\") . ?\x02dd)
+ ((?A ?%) . ?\x0386)
+ ((?E ?%) . ?\x0388)
+ ((?Y ?%) . ?\x0389)
+ ((?I ?%) . ?\x038a)
+ ((?O ?%) . ?\x038c)
+ ((?U ?%) . ?\x038e)
+ ((?W ?%) . ?\x038f)
+ ((?i ?3) . ?\x0390)
+ ((?A ?*) . ?\x0391)
+ ((?B ?*) . ?\x0392)
+ ((?G ?*) . ?\x0393)
+ ((?D ?*) . ?\x0394)
+ ((?E ?*) . ?\x0395)
+ ((?Z ?*) . ?\x0396)
+ ((?Y ?*) . ?\x0397)
+ ((?H ?*) . ?\x0398)
+ ((?I ?*) . ?\x0399)
+ ((?K ?*) . ?\x039a)
+ ((?L ?*) . ?\x039b)
+ ((?M ?*) . ?\x039c)
+ ((?N ?*) . ?\x039d)
+ ((?C ?*) . ?\x039e)
+ ((?O ?*) . ?\x039f)
+ ((?P ?*) . ?\x03a0)
+ ((?R ?*) . ?\x03a1)
+ ((?S ?*) . ?\x03a3)
+ ((?T ?*) . ?\x03a4)
+ ((?U ?*) . ?\x03a5)
+ ((?F ?*) . ?\x03a6)
+ ((?X ?*) . ?\x03a7)
+ ((?Q ?*) . ?\x03a8)
+ ((?W ?*) . ?\x03a9)
+ ((?J ?*) . ?\x03aa)
+ ((?V ?*) . ?\x03ab)
+ ((?a ?%) . ?\x03ac)
+ ((?e ?%) . ?\x03ad)
+ ((?y ?%) . ?\x03ae)
+ ((?i ?%) . ?\x03af)
+ ((?u ?3) . ?\x03b0)
+ ((?a ?*) . ?\x03b1)
+ ((?b ?*) . ?\x03b2)
+ ((?g ?*) . ?\x03b3)
+ ((?d ?*) . ?\x03b4)
+ ((?e ?*) . ?\x03b5)
+ ((?z ?*) . ?\x03b6)
+ ((?y ?*) . ?\x03b7)
+ ((?h ?*) . ?\x03b8)
+ ((?i ?*) . ?\x03b9)
+ ((?k ?*) . ?\x03ba)
+ ((?l ?*) . ?\x03bb)
+ ((?m ?*) . ?\x03bc)
+ ((?n ?*) . ?\x03bd)
+ ((?c ?*) . ?\x03be)
+ ((?o ?*) . ?\x03bf)
+ ((?p ?*) . ?\x03c0)
+ ((?r ?*) . ?\x03c1)
+ ((?* ?s) . ?\x03c2)
+ ((?s ?*) . ?\x03c3)
+ ((?t ?*) . ?\x03c4)
+ ((?u ?*) . ?\x03c5)
+ ((?f ?*) . ?\x03c6)
+ ((?x ?*) . ?\x03c7)
+ ((?q ?*) . ?\x03c8)
+ ((?w ?*) . ?\x03c9)
+ ((?j ?*) . ?\x03ca)
+ ((?v ?*) . ?\x03cb)
+ ((?o ?%) . ?\x03cc)
+ ((?u ?%) . ?\x03cd)
+ ((?w ?%) . ?\x03ce)
+ ((?' ?G) . ?\x03d8)
+ ((?, ?G) . ?\x03d9)
+ ((?T ?3) . ?\x03da)
+ ((?t ?3) . ?\x03db)
+ ((?M ?3) . ?\x03dc)
+ ((?m ?3) . ?\x03dd)
+ ((?K ?3) . ?\x03de)
+ ((?k ?3) . ?\x03df)
+ ((?P ?3) . ?\x03e0)
+ ((?p ?3) . ?\x03e1)
+ ((?' ?%) . ?\x03f4)
+ ((?j ?3) . ?\x03f5)
+ ((?I ?O) . ?\x0401)
+ ((?D ?%) . ?\x0402)
+ ((?G ?%) . ?\x0403)
+ ((?I ?E) . ?\x0404)
+ ((?D ?S) . ?\x0405)
+ ((?I ?I) . ?\x0406)
+ ((?Y ?I) . ?\x0407)
+ ((?J ?%) . ?\x0408)
+ ((?L ?J) . ?\x0409)
+ ((?N ?J) . ?\x040a)
+ ((?T ?s) . ?\x040b)
+ ((?K ?J) . ?\x040c)
+ ((?V ?%) . ?\x040e)
+ ((?D ?Z) . ?\x040f)
+ ((?A ?=) . ?\x0410)
+ ((?B ?=) . ?\x0411)
+ ((?V ?=) . ?\x0412)
+ ((?G ?=) . ?\x0413)
+ ((?D ?=) . ?\x0414)
+ ((?E ?=) . ?\x0415)
+ ((?Z ?%) . ?\x0416)
+ ((?Z ?=) . ?\x0417)
+ ((?I ?=) . ?\x0418)
+ ((?J ?=) . ?\x0419)
+ ((?K ?=) . ?\x041a)
+ ((?L ?=) . ?\x041b)
+ ((?M ?=) . ?\x041c)
+ ((?N ?=) . ?\x041d)
+ ((?O ?=) . ?\x041e)
+ ((?P ?=) . ?\x041f)
+ ((?R ?=) . ?\x0420)
+ ((?S ?=) . ?\x0421)
+ ((?T ?=) . ?\x0422)
+ ((?U ?=) . ?\x0423)
+ ((?F ?=) . ?\x0424)
+ ((?H ?=) . ?\x0425)
+ ((?C ?=) . ?\x0426)
+ ((?C ?%) . ?\x0427)
+ ((?S ?%) . ?\x0428)
+ ((?S ?c) . ?\x0429)
+ ((?= ?\") . ?\x042a)
+ ((?Y ?=) . ?\x042b)
+ ((?% ?\") . ?\x042c)
+ ((?J ?E) . ?\x042d)
+ ((?J ?U) . ?\x042e)
+ ((?J ?A) . ?\x042f)
+ ((?a ?=) . ?\x0430)
+ ((?b ?=) . ?\x0431)
+ ((?v ?=) . ?\x0432)
+ ((?g ?=) . ?\x0433)
+ ((?d ?=) . ?\x0434)
+ ((?e ?=) . ?\x0435)
+ ((?z ?%) . ?\x0436)
+ ((?z ?=) . ?\x0437)
+ ((?i ?=) . ?\x0438)
+ ((?j ?=) . ?\x0439)
+ ((?k ?=) . ?\x043a)
+ ((?l ?=) . ?\x043b)
+ ((?m ?=) . ?\x043c)
+ ((?n ?=) . ?\x043d)
+ ((?o ?=) . ?\x043e)
+ ((?p ?=) . ?\x043f)
+ ((?r ?=) . ?\x0440)
+ ((?s ?=) . ?\x0441)
+ ((?t ?=) . ?\x0442)
+ ((?u ?=) . ?\x0443)
+ ((?f ?=) . ?\x0444)
+ ((?h ?=) . ?\x0445)
+ ((?c ?=) . ?\x0446)
+ ((?c ?%) . ?\x0447)
+ ((?s ?%) . ?\x0448)
+ ((?s ?c) . ?\x0449)
+ ((?= ?') . ?\x044a)
+ ((?y ?=) . ?\x044b)
+ ((?% ?') . ?\x044c)
+ ((?j ?e) . ?\x044d)
+ ((?j ?u) . ?\x044e)
+ ((?j ?a) . ?\x044f)
+ ((?i ?o) . ?\x0451)
+ ((?d ?%) . ?\x0452)
+ ((?g ?%) . ?\x0453)
+ ((?i ?e) . ?\x0454)
+ ((?d ?s) . ?\x0455)
+ ((?i ?i) . ?\x0456)
+ ((?y ?i) . ?\x0457)
+ ((?j ?%) . ?\x0458)
+ ((?l ?j) . ?\x0459)
+ ((?n ?j) . ?\x045a)
+ ((?t ?s) . ?\x045b)
+ ((?k ?j) . ?\x045c)
+ ((?v ?%) . ?\x045e)
+ ((?d ?z) . ?\x045f)
+ ((?Y ?3) . ?\x0462)
+ ((?y ?3) . ?\x0463)
+ ((?O ?3) . ?\x046a)
+ ((?o ?3) . ?\x046b)
+ ((?F ?3) . ?\x0472)
+ ((?f ?3) . ?\x0473)
+ ((?V ?3) . ?\x0474)
+ ((?v ?3) . ?\x0475)
+ ((?C ?3) . ?\x0480)
+ ((?c ?3) . ?\x0481)
+ ((?G ?3) . ?\x0490)
+ ((?g ?3) . ?\x0491)
+ ((?A ?+) . ?\x05d0)
+ ((?B ?+) . ?\x05d1)
+ ((?G ?+) . ?\x05d2)
+ ((?D ?+) . ?\x05d3)
+ ((?H ?+) . ?\x05d4)
+ ((?W ?+) . ?\x05d5)
+ ((?Z ?+) . ?\x05d6)
+ ((?X ?+) . ?\x05d7)
+ ((?T ?j) . ?\x05d8)
+ ((?J ?+) . ?\x05d9)
+ ((?K ?%) . ?\x05da)
+ ((?K ?+) . ?\x05db)
+ ((?L ?+) . ?\x05dc)
+ ((?M ?%) . ?\x05dd)
+ ((?M ?+) . ?\x05de)
+ ((?N ?%) . ?\x05df)
+ ((?N ?+) . ?\x05e0)
+ ((?S ?+) . ?\x05e1)
+ ((?E ?+) . ?\x05e2)
+ ((?P ?%) . ?\x05e3)
+ ((?P ?+) . ?\x05e4)
+ ((?Z ?j) . ?\x05e5)
+ ((?Z ?J) . ?\x05e6)
+ ((?Q ?+) . ?\x05e7)
+ ((?R ?+) . ?\x05e8)
+ ((?S ?h) . ?\x05e9)
+ ((?T ?+) . ?\x05ea)
+ ((?, ?+) . ?\x060c)
+ ((?\; ?+) . ?\x061b)
+ ((?? ?+) . ?\x061f)
+ ((?H ?') . ?\x0621)
+ ((?a ?M) . ?\x0622)
+ ((?a ?H) . ?\x0623)
+ ((?w ?H) . ?\x0624)
+ ((?a ?h) . ?\x0625)
+ ((?y ?H) . ?\x0626)
+ ((?a ?+) . ?\x0627)
+ ((?b ?+) . ?\x0628)
+ ((?t ?m) . ?\x0629)
+ ((?t ?+) . ?\x062a)
+ ((?t ?k) . ?\x062b)
+ ((?g ?+) . ?\x062c)
+ ((?h ?k) . ?\x062d)
+ ((?x ?+) . ?\x062e)
+ ((?d ?+) . ?\x062f)
+ ((?d ?k) . ?\x0630)
+ ((?r ?+) . ?\x0631)
+ ((?z ?+) . ?\x0632)
+ ((?s ?+) . ?\x0633)
+ ((?s ?n) . ?\x0634)
+ ((?c ?+) . ?\x0635)
+ ((?d ?d) . ?\x0636)
+ ((?t ?j) . ?\x0637)
+ ((?z ?H) . ?\x0638)
+ ((?e ?+) . ?\x0639)
+ ((?i ?+) . ?\x063a)
+ ((?+ ?+) . ?\x0640)
+ ((?f ?+) . ?\x0641)
+ ((?q ?+) . ?\x0642)
+ ((?k ?+) . ?\x0643)
+ ((?l ?+) . ?\x0644)
+ ((?m ?+) . ?\x0645)
+ ((?n ?+) . ?\x0646)
+ ((?h ?+) . ?\x0647)
+ ((?w ?+) . ?\x0648)
+ ((?j ?+) . ?\x0649)
+ ((?y ?+) . ?\x064a)
+ ((?: ?+) . ?\x064b)
+ ((?\" ?+) . ?\x064c)
+ ((?= ?+) . ?\x064d)
+ ((?/ ?+) . ?\x064e)
+ ((?' ?+) . ?\x064f)
+ ((?1 ?+) . ?\x0650)
+ ((?3 ?+) . ?\x0651)
+ ((?0 ?+) . ?\x0652)
+ ((?a ?S) . ?\x0670)
+ ((?p ?+) . ?\x067e)
+ ((?v ?+) . ?\x06a4)
+ ((?g ?f) . ?\x06af)
+ ((?0 ?a) . ?\x06f0)
+ ((?1 ?a) . ?\x06f1)
+ ((?2 ?a) . ?\x06f2)
+ ((?3 ?a) . ?\x06f3)
+ ((?4 ?a) . ?\x06f4)
+ ((?5 ?a) . ?\x06f5)
+ ((?6 ?a) . ?\x06f6)
+ ((?7 ?a) . ?\x06f7)
+ ((?8 ?a) . ?\x06f8)
+ ((?9 ?a) . ?\x06f9)
+ ((?B ?.) . ?\x1e02)
+ ((?b ?.) . ?\x1e03)
+ ((?B ?_) . ?\x1e06)
+ ((?b ?_) . ?\x1e07)
+ ((?D ?.) . ?\x1e0a)
+ ((?d ?.) . ?\x1e0b)
+ ((?D ?_) . ?\x1e0e)
+ ((?d ?_) . ?\x1e0f)
+ ((?D ?,) . ?\x1e10)
+ ((?d ?,) . ?\x1e11)
+ ((?F ?.) . ?\x1e1e)
+ ((?f ?.) . ?\x1e1f)
+ ((?G ?-) . ?\x1e20)
+ ((?g ?-) . ?\x1e21)
+ ((?H ?.) . ?\x1e22)
+ ((?h ?.) . ?\x1e23)
+ ((?H ?:) . ?\x1e26)
+ ((?h ?:) . ?\x1e27)
+ ((?H ?,) . ?\x1e28)
+ ((?h ?,) . ?\x1e29)
+ ((?K ?') . ?\x1e30)
+ ((?k ?') . ?\x1e31)
+ ((?K ?_) . ?\x1e34)
+ ((?k ?_) . ?\x1e35)
+ ((?L ?_) . ?\x1e3a)
+ ((?l ?_) . ?\x1e3b)
+ ((?M ?') . ?\x1e3e)
+ ((?m ?') . ?\x1e3f)
+ ((?M ?.) . ?\x1e40)
+ ((?m ?.) . ?\x1e41)
+ ((?N ?.) . ?\x1e44)
+ ((?n ?.) . ?\x1e45)
+ ((?N ?_) . ?\x1e48)
+ ((?n ?_) . ?\x1e49)
+ ((?P ?') . ?\x1e54)
+ ((?p ?') . ?\x1e55)
+ ((?P ?.) . ?\x1e56)
+ ((?p ?.) . ?\x1e57)
+ ((?R ?.) . ?\x1e58)
+ ((?r ?.) . ?\x1e59)
+ ((?R ?_) . ?\x1e5e)
+ ((?r ?_) . ?\x1e5f)
+ ((?S ?.) . ?\x1e60)
+ ((?s ?.) . ?\x1e61)
+ ((?T ?.) . ?\x1e6a)
+ ((?t ?.) . ?\x1e6b)
+ ((?T ?_) . ?\x1e6e)
+ ((?t ?_) . ?\x1e6f)
+ ((?V ??) . ?\x1e7c)
+ ((?v ??) . ?\x1e7d)
+ ((?W ?!) . ?\x1e80)
+ ((?W ?`) . ?\x1e80)
+ ((?w ?!) . ?\x1e81)
+ ((?w ?`) . ?\x1e81)
+ ((?W ?') . ?\x1e82)
+ ((?w ?') . ?\x1e83)
+ ((?W ?:) . ?\x1e84)
+ ((?w ?:) . ?\x1e85)
+ ((?W ?.) . ?\x1e86)
+ ((?w ?.) . ?\x1e87)
+ ((?X ?.) . ?\x1e8a)
+ ((?x ?.) . ?\x1e8b)
+ ((?X ?:) . ?\x1e8c)
+ ((?x ?:) . ?\x1e8d)
+ ((?Y ?.) . ?\x1e8e)
+ ((?y ?.) . ?\x1e8f)
+ ((?Z ?>) . ?\x1e90)
+ ((?z ?>) . ?\x1e91)
+ ((?Z ?_) . ?\x1e94)
+ ((?z ?_) . ?\x1e95)
+ ((?h ?_) . ?\x1e96)
+ ((?t ?:) . ?\x1e97)
+ ((?w ?0) . ?\x1e98)
+ ((?y ?0) . ?\x1e99)
+ ((?A ?2) . ?\x1ea2)
+ ((?a ?2) . ?\x1ea3)
+ ((?E ?2) . ?\x1eba)
+ ((?e ?2) . ?\x1ebb)
+ ((?E ??) . ?\x1ebc)
+ ((?e ??) . ?\x1ebd)
+ ((?I ?2) . ?\x1ec8)
+ ((?i ?2) . ?\x1ec9)
+ ((?O ?2) . ?\x1ece)
+ ((?o ?2) . ?\x1ecf)
+ ((?U ?2) . ?\x1ee6)
+ ((?u ?2) . ?\x1ee7)
+ ((?Y ?!) . ?\x1ef2)
+ ((?Y ?`) . ?\x1ef2)
+ ((?y ?!) . ?\x1ef3)
+ ((?y ?`) . ?\x1ef3)
+ ((?Y ?2) . ?\x1ef6)
+ ((?y ?2) . ?\x1ef7)
+ ((?Y ??) . ?\x1ef8)
+ ((?y ??) . ?\x1ef9)
+ ((?\; ?') . ?\x1f00)
+ ((?, ?') . ?\x1f01)
+ ((?\; ?!) . ?\x1f02)
+ ((?, ?!) . ?\x1f03)
+ ((?? ?\;) . ?\x1f04)
+ ((?? ?,) . ?\x1f05)
+ ((?! ?:) . ?\x1f06)
+ ((?? ?:) . ?\x1f07)
+ ((?1 ?N) . ?\x2002)
+ ((?1 ?M) . ?\x2003)
+ ((?3 ?M) . ?\x2004)
+ ((?4 ?M) . ?\x2005)
+ ((?6 ?M) . ?\x2006)
+ ((?1 ?T) . ?\x2009)
+ ((?1 ?H) . ?\x200a)
+ ((?- ?1) . ?\x2010)
+ ((?- ?N) . ?\x2013)
+ ((?- ?M) . ?\x2014)
+ ((?- ?3) . ?\x2015)
+ ((?! ?2) . ?\x2016)
+ ((?= ?2) . ?\x2017)
+ ((?' ?6) . ?\x2018)
+ ((?' ?9) . ?\x2019)
+ ((?. ?9) . ?\x201a)
+ ((?9 ?') . ?\x201b)
+ ((?\" ?6) . ?\x201c)
+ ((?\" ?9) . ?\x201d)
+ ((?: ?9) . ?\x201e)
+ ((?9 ?\") . ?\x201f)
+ ((?/ ?-) . ?\x2020)
+ ((?/ ?=) . ?\x2021)
+ ((?o ?o) . ?\x2022)
+ ((?. ?.) . ?\x2025)
+ ((?, ?.) . ?\x2026)
+ ((?% ?0) . ?\x2030)
+ ((?1 ?') . ?\x2032)
+ ((?2 ?') . ?\x2033)
+ ((?3 ?') . ?\x2034)
+ ((?1 ?\") . ?\x2035)
+ ((?2 ?\") . ?\x2036)
+ ((?3 ?\") . ?\x2037)
+ ((?C ?a) . ?\x2038)
+ ((?< ?1) . ?\x2039)
+ ((?> ?1) . ?\x203a)
+ ((?: ?X) . ?\x203b)
+ ((?' ?-) . ?\x203e)
+ ((?/ ?f) . ?\x2044)
+ ((?0 ?S) . ?\x2070)
+ ((?4 ?S) . ?\x2074)
+ ((?5 ?S) . ?\x2075)
+ ((?6 ?S) . ?\x2076)
+ ((?7 ?S) . ?\x2077)
+ ((?8 ?S) . ?\x2078)
+ ((?9 ?S) . ?\x2079)
+ ((?+ ?S) . ?\x207a)
+ ((?- ?S) . ?\x207b)
+ ((?= ?S) . ?\x207c)
+ ((?\( ?S) . ?\x207d)
+ ((?\) ?S) . ?\x207e)
+ ((?n ?S) . ?\x207f)
+ ((?0 ?s) . ?\x2080)
+ ((?1 ?s) . ?\x2081)
+ ((?2 ?s) . ?\x2082)
+ ((?3 ?s) . ?\x2083)
+ ((?4 ?s) . ?\x2084)
+ ((?5 ?s) . ?\x2085)
+ ((?6 ?s) . ?\x2086)
+ ((?7 ?s) . ?\x2087)
+ ((?8 ?s) . ?\x2088)
+ ((?9 ?s) . ?\x2089)
+ ((?+ ?s) . ?\x208a)
+ ((?- ?s) . ?\x208b)
+ ((?= ?s) . ?\x208c)
+ ((?\( ?s) . ?\x208d)
+ ((?\) ?s) . ?\x208e)
+ ((?L ?i) . ?\x20a4)
+ ((?P ?t) . ?\x20a7)
+ ((?W ?=) . ?\x20a9)
+ ((?= ?e) . ?\x20ac)
+ ((?E ?u) . ?\x20ac)
+ ((?= ?R) . ?\x20bd)
+ ((?= ?P) . ?\x20bd)
+ ((?o ?C) . ?\x2103)
+ ((?c ?o) . ?\x2105)
+ ((?o ?F) . ?\x2109)
+ ((?N ?0) . ?\x2116)
+ ((?P ?O) . ?\x2117)
+ ((?R ?x) . ?\x211e)
+ ((?S ?M) . ?\x2120)
+ ((?T ?M) . ?\x2122)
+ ((?O ?m) . ?\x2126)
+ ((?A ?O) . ?\x212b)
+ ((?1 ?3) . ?\x2153)
+ ((?2 ?3) . ?\x2154)
+ ((?1 ?5) . ?\x2155)
+ ((?2 ?5) . ?\x2156)
+ ((?3 ?5) . ?\x2157)
+ ((?4 ?5) . ?\x2158)
+ ((?1 ?6) . ?\x2159)
+ ((?5 ?6) . ?\x215a)
+ ((?1 ?8) . ?\x215b)
+ ((?3 ?8) . ?\x215c)
+ ((?5 ?8) . ?\x215d)
+ ((?7 ?8) . ?\x215e)
+ ((?1 ?R) . ?\x2160)
+ ((?2 ?R) . ?\x2161)
+ ((?3 ?R) . ?\x2162)
+ ((?4 ?R) . ?\x2163)
+ ((?5 ?R) . ?\x2164)
+ ((?6 ?R) . ?\x2165)
+ ((?7 ?R) . ?\x2166)
+ ((?8 ?R) . ?\x2167)
+ ((?9 ?R) . ?\x2168)
+ ((?a ?R) . ?\x2169)
+ ((?b ?R) . ?\x216a)
+ ((?c ?R) . ?\x216b)
+ ((?1 ?r) . ?\x2170)
+ ((?2 ?r) . ?\x2171)
+ ((?3 ?r) . ?\x2172)
+ ((?4 ?r) . ?\x2173)
+ ((?5 ?r) . ?\x2174)
+ ((?6 ?r) . ?\x2175)
+ ((?7 ?r) . ?\x2176)
+ ((?8 ?r) . ?\x2177)
+ ((?9 ?r) . ?\x2178)
+ ((?a ?r) . ?\x2179)
+ ((?b ?r) . ?\x217a)
+ ((?c ?r) . ?\x217b)
+ ((?< ?-) . ?\x2190)
+ ((?- ?!) . ?\x2191)
+ ((?- ?>) . ?\x2192)
+ ((?- ?v) . ?\x2193)
+ ((?< ?>) . ?\x2194)
+ ((?U ?D) . ?\x2195)
+ ((?< ?=) . ?\x21d0)
+ ((?= ?>) . ?\x21d2)
+ ((?= ?=) . ?\x21d4)
+ ((?F ?A) . ?\x2200)
+ ((?d ?P) . ?\x2202)
+ ((?T ?E) . ?\x2203)
+ ((?/ ?0) . ?\x2205)
+ ((?D ?E) . ?\x2206)
+ ((?N ?B) . ?\x2207)
+ ((?\( ?-) . ?\x2208)
+ ((?- ?\)) . ?\x220b)
+ ((?* ?P) . ?\x220f)
+ ((?+ ?Z) . ?\x2211)
+ ((?- ?2) . ?\x2212)
+ ((?- ?+) . ?\x2213)
+ ((?* ?-) . ?\x2217)
+ ((?O ?b) . ?\x2218)
+ ((?S ?b) . ?\x2219)
+ ((?R ?T) . ?\x221a)
+ ((?0 ?\() . ?\x221d)
+ ((?0 ?0) . ?\x221e)
+ ((?- ?L) . ?\x221f)
+ ((?- ?V) . ?\x2220)
+ ((?P ?P) . ?\x2225)
+ ((?A ?N) . ?\x2227)
+ ((?O ?R) . ?\x2228)
+ ((?\( ?U) . ?\x2229)
+ ((?\) ?U) . ?\x222a)
+ ((?I ?n) . ?\x222b)
+ ((?D ?I) . ?\x222c)
+ ((?I ?o) . ?\x222e)
+ ((?. ?:) . ?\x2234)
+ ((?: ?.) . ?\x2235)
+ ((?: ?R) . ?\x2236)
+ ((?: ?:) . ?\x2237)
+ ((?? ?1) . ?\x223c)
+ ((?C ?G) . ?\x223e)
+ ((?? ?-) . ?\x2243)
+ ((?? ?=) . ?\x2245)
+ ((?? ?2) . ?\x2248)
+ ((?= ??) . ?\x224c)
+ ((?H ?I) . ?\x2253)
+ ((?! ?=) . ?\x2260)
+ ((?= ?3) . ?\x2261)
+ ((?= ?<) . ?\x2264)
+ ((?> ?=) . ?\x2265)
+ ((?< ?*) . ?\x226a)
+ ((?* ?>) . ?\x226b)
+ ((?! ?<) . ?\x226e)
+ ((?! ?>) . ?\x226f)
+ ((?\( ?C) . ?\x2282)
+ ((?\) ?C) . ?\x2283)
+ ((?\( ?_) . ?\x2286)
+ ((?\) ?_) . ?\x2287)
+ ((?0 ?.) . ?\x2299)
+ ((?0 ?2) . ?\x229a)
+ ((?- ?T) . ?\x22a5)
+ ((?. ?P) . ?\x22c5)
+ ((?: ?3) . ?\x22ee)
+ ((?. ?3) . ?\x22ef)
+ ((?E ?h) . ?\x2302)
+ ((?< ?7) . ?\x2308)
+ ((?> ?7) . ?\x2309)
+ ((?7 ?<) . ?\x230a)
+ ((?7 ?>) . ?\x230b)
+ ((?N ?I) . ?\x2310)
+ ((?\( ?A) . ?\x2312)
+ ((?T ?R) . ?\x2315)
+ ((?I ?u) . ?\x2320)
+ ((?I ?l) . ?\x2321)
+ ((?< ?/) . ?\x2329)
+ ((?/ ?>) . ?\x232a)
+ ((?V ?s) . ?\x2423)
+ ((?1 ?h) . ?\x2440)
+ ((?3 ?h) . ?\x2441)
+ ((?2 ?h) . ?\x2442)
+ ((?4 ?h) . ?\x2443)
+ ((?1 ?j) . ?\x2446)
+ ((?2 ?j) . ?\x2447)
+ ((?3 ?j) . ?\x2448)
+ ((?4 ?j) . ?\x2449)
+ ((?1 ?.) . ?\x2488)
+ ((?2 ?.) . ?\x2489)
+ ((?3 ?.) . ?\x248a)
+ ((?4 ?.) . ?\x248b)
+ ((?5 ?.) . ?\x248c)
+ ((?6 ?.) . ?\x248d)
+ ((?7 ?.) . ?\x248e)
+ ((?8 ?.) . ?\x248f)
+ ((?9 ?.) . ?\x2490)
+ ((?h ?h) . ?\x2500)
+ ((?H ?H) . ?\x2501)
+ ((?v ?v) . ?\x2502)
+ ((?V ?V) . ?\x2503)
+ ((?3 ?-) . ?\x2504)
+ ((?3 ?_) . ?\x2505)
+ ((?3 ?!) . ?\x2506)
+ ((?3 ?/) . ?\x2507)
+ ((?4 ?-) . ?\x2508)
+ ((?4 ?_) . ?\x2509)
+ ((?4 ?!) . ?\x250a)
+ ((?4 ?/) . ?\x250b)
+ ((?d ?r) . ?\x250c)
+ ((?d ?R) . ?\x250d)
+ ((?D ?r) . ?\x250e)
+ ((?D ?R) . ?\x250f)
+ ((?d ?l) . ?\x2510)
+ ((?d ?L) . ?\x2511)
+ ((?D ?l) . ?\x2512)
+ ((?L ?D) . ?\x2513)
+ ((?u ?r) . ?\x2514)
+ ((?u ?R) . ?\x2515)
+ ((?U ?r) . ?\x2516)
+ ((?U ?R) . ?\x2517)
+ ((?u ?l) . ?\x2518)
+ ((?u ?L) . ?\x2519)
+ ((?U ?l) . ?\x251a)
+ ((?U ?L) . ?\x251b)
+ ((?v ?r) . ?\x251c)
+ ((?v ?R) . ?\x251d)
+ ((?V ?r) . ?\x2520)
+ ((?V ?R) . ?\x2523)
+ ((?v ?l) . ?\x2524)
+ ((?v ?L) . ?\x2525)
+ ((?V ?l) . ?\x2528)
+ ((?V ?L) . ?\x252b)
+ ((?d ?h) . ?\x252c)
+ ((?d ?H) . ?\x252f)
+ ((?D ?h) . ?\x2530)
+ ((?D ?H) . ?\x2533)
+ ((?u ?h) . ?\x2534)
+ ((?u ?H) . ?\x2537)
+ ((?U ?h) . ?\x2538)
+ ((?U ?H) . ?\x253b)
+ ((?v ?h) . ?\x253c)
+ ((?v ?H) . ?\x253f)
+ ((?V ?h) . ?\x2542)
+ ((?V ?H) . ?\x254b)
+ ((?F ?D) . ?\x2571)
+ ((?B ?D) . ?\x2572)
+ ((?T ?B) . ?\x2580)
+ ((?L ?B) . ?\x2584)
+ ((?F ?B) . ?\x2588)
+ ((?l ?B) . ?\x258c)
+ ((?R ?B) . ?\x2590)
+ ((?. ?S) . ?\x2591)
+ ((?: ?S) . ?\x2592)
+ ((?? ?S) . ?\x2593)
+ ((?f ?S) . ?\x25a0)
+ ((?O ?S) . ?\x25a1)
+ ((?R ?O) . ?\x25a2)
+ ((?R ?r) . ?\x25a3)
+ ((?R ?F) . ?\x25a4)
+ ((?R ?Y) . ?\x25a5)
+ ((?R ?H) . ?\x25a6)
+ ((?R ?Z) . ?\x25a7)
+ ((?R ?K) . ?\x25a8)
+ ((?R ?X) . ?\x25a9)
+ ((?s ?B) . ?\x25aa)
+ ((?S ?R) . ?\x25ac)
+ ((?O ?r) . ?\x25ad)
+ ((?U ?T) . ?\x25b2)
+ ((?u ?T) . ?\x25b3)
+ ((?P ?R) . ?\x25b6)
+ ((?T ?r) . ?\x25b7)
+ ((?D ?t) . ?\x25bc)
+ ((?d ?T) . ?\x25bd)
+ ((?P ?L) . ?\x25c0)
+ ((?T ?l) . ?\x25c1)
+ ((?D ?b) . ?\x25c6)
+ ((?D ?w) . ?\x25c7)
+ ((?L ?Z) . ?\x25ca)
+ ((?0 ?m) . ?\x25cb)
+ ((?0 ?o) . ?\x25ce)
+ ((?0 ?M) . ?\x25cf)
+ ((?0 ?L) . ?\x25d0)
+ ((?0 ?R) . ?\x25d1)
+ ((?S ?n) . ?\x25d8)
+ ((?I ?c) . ?\x25d9)
+ ((?F ?d) . ?\x25e2)
+ ((?B ?d) . ?\x25e3)
+ ((?* ?2) . ?\x2605)
+ ((?* ?1) . ?\x2606)
+ ((?< ?H) . ?\x261c)
+ ((?> ?H) . ?\x261e)
+ ((?0 ?u) . ?\x263a)
+ ((?0 ?U) . ?\x263b)
+ ((?S ?U) . ?\x263c)
+ ((?F ?m) . ?\x2640)
+ ((?M ?l) . ?\x2642)
+ ((?c ?S) . ?\x2660)
+ ((?c ?H) . ?\x2661)
+ ((?c ?D) . ?\x2662)
+ ((?c ?C) . ?\x2663)
+ ((?M ?d) . ?\x2669)
+ ((?M ?8) . ?\x266a)
+ ((?M ?2) . ?\x266b)
+ ((?M ?b) . ?\x266d)
+ ((?M ?x) . ?\x266e)
+ ((?M ?X) . ?\x266f)
+ ((?O ?K) . ?\x2713)
+ ((?X ?X) . ?\x2717)
+ ((?- ?X) . ?\x2720)
+ ((?I ?S) . ?\x3000)
+ ((?, ?_) . ?\x3001)
+ ((?. ?_) . ?\x3002)
+ ((?+ ?\") . ?\x3003)
+ ((?+ ?_) . ?\x3004)
+ ((?* ?_) . ?\x3005)
+ ((?\; ?_) . ?\x3006)
+ ((?0 ?_) . ?\x3007)
+ ((?< ?+) . ?\x300a)
+ ((?> ?+) . ?\x300b)
+ ((?< ?') . ?\x300c)
+ ((?> ?') . ?\x300d)
+ ((?< ?\") . ?\x300e)
+ ((?> ?\") . ?\x300f)
+ ((?\( ?\") . ?\x3010)
+ ((?\) ?\") . ?\x3011)
+ ((?= ?T) . ?\x3012)
+ ((?= ?_) . ?\x3013)
+ ((?\( ?') . ?\x3014)
+ ((?\) ?') . ?\x3015)
+ ((?\( ?I) . ?\x3016)
+ ((?\) ?I) . ?\x3017)
+ ((?- ??) . ?\x301c)
+ ((?A ?5) . ?\x3041)
+ ((?a ?5) . ?\x3042)
+ ((?I ?5) . ?\x3043)
+ ((?i ?5) . ?\x3044)
+ ((?U ?5) . ?\x3045)
+ ((?u ?5) . ?\x3046)
+ ((?E ?5) . ?\x3047)
+ ((?e ?5) . ?\x3048)
+ ((?O ?5) . ?\x3049)
+ ((?o ?5) . ?\x304a)
+ ((?k ?a) . ?\x304b)
+ ((?g ?a) . ?\x304c)
+ ((?k ?i) . ?\x304d)
+ ((?g ?i) . ?\x304e)
+ ((?k ?u) . ?\x304f)
+ ((?g ?u) . ?\x3050)
+ ((?k ?e) . ?\x3051)
+ ((?g ?e) . ?\x3052)
+ ((?k ?o) . ?\x3053)
+ ((?g ?o) . ?\x3054)
+ ((?s ?a) . ?\x3055)
+ ((?z ?a) . ?\x3056)
+ ((?s ?i) . ?\x3057)
+ ((?z ?i) . ?\x3058)
+ ((?s ?u) . ?\x3059)
+ ((?z ?u) . ?\x305a)
+ ((?s ?e) . ?\x305b)
+ ((?z ?e) . ?\x305c)
+ ((?s ?o) . ?\x305d)
+ ((?z ?o) . ?\x305e)
+ ((?t ?a) . ?\x305f)
+ ((?d ?a) . ?\x3060)
+ ((?t ?i) . ?\x3061)
+ ((?d ?i) . ?\x3062)
+ ((?t ?U) . ?\x3063)
+ ((?t ?u) . ?\x3064)
+ ((?d ?u) . ?\x3065)
+ ((?t ?e) . ?\x3066)
+ ((?d ?e) . ?\x3067)
+ ((?t ?o) . ?\x3068)
+ ((?d ?o) . ?\x3069)
+ ((?n ?a) . ?\x306a)
+ ((?n ?i) . ?\x306b)
+ ((?n ?u) . ?\x306c)
+ ((?n ?e) . ?\x306d)
+ ((?n ?o) . ?\x306e)
+ ((?h ?a) . ?\x306f)
+ ((?b ?a) . ?\x3070)
+ ((?p ?a) . ?\x3071)
+ ((?h ?i) . ?\x3072)
+ ((?b ?i) . ?\x3073)
+ ((?p ?i) . ?\x3074)
+ ((?h ?u) . ?\x3075)
+ ((?b ?u) . ?\x3076)
+ ((?p ?u) . ?\x3077)
+ ((?h ?e) . ?\x3078)
+ ((?b ?e) . ?\x3079)
+ ((?p ?e) . ?\x307a)
+ ((?h ?o) . ?\x307b)
+ ((?b ?o) . ?\x307c)
+ ((?p ?o) . ?\x307d)
+ ((?m ?a) . ?\x307e)
+ ((?m ?i) . ?\x307f)
+ ((?m ?u) . ?\x3080)
+ ((?m ?e) . ?\x3081)
+ ((?m ?o) . ?\x3082)
+ ((?y ?A) . ?\x3083)
+ ((?y ?a) . ?\x3084)
+ ((?y ?U) . ?\x3085)
+ ((?y ?u) . ?\x3086)
+ ((?y ?O) . ?\x3087)
+ ((?y ?o) . ?\x3088)
+ ((?r ?a) . ?\x3089)
+ ((?r ?i) . ?\x308a)
+ ((?r ?u) . ?\x308b)
+ ((?r ?e) . ?\x308c)
+ ((?r ?o) . ?\x308d)
+ ((?w ?A) . ?\x308e)
+ ((?w ?a) . ?\x308f)
+ ((?w ?i) . ?\x3090)
+ ((?w ?e) . ?\x3091)
+ ((?w ?o) . ?\x3092)
+ ((?n ?5) . ?\x3093)
+ ((?v ?u) . ?\x3094)
+ ((?\" ?5) . ?\x309b)
+ ((?0 ?5) . ?\x309c)
+ ((?* ?5) . ?\x309d)
+ ((?+ ?5) . ?\x309e)
+ ((?a ?6) . ?\x30a1)
+ ((?A ?6) . ?\x30a2)
+ ((?i ?6) . ?\x30a3)
+ ((?I ?6) . ?\x30a4)
+ ((?u ?6) . ?\x30a5)
+ ((?U ?6) . ?\x30a6)
+ ((?e ?6) . ?\x30a7)
+ ((?E ?6) . ?\x30a8)
+ ((?o ?6) . ?\x30a9)
+ ((?O ?6) . ?\x30aa)
+ ((?K ?a) . ?\x30ab)
+ ((?G ?a) . ?\x30ac)
+ ((?K ?i) . ?\x30ad)
+ ((?G ?i) . ?\x30ae)
+ ((?K ?u) . ?\x30af)
+ ((?G ?u) . ?\x30b0)
+ ((?K ?e) . ?\x30b1)
+ ((?G ?e) . ?\x30b2)
+ ((?K ?o) . ?\x30b3)
+ ((?G ?o) . ?\x30b4)
+ ((?S ?a) . ?\x30b5)
+ ((?Z ?a) . ?\x30b6)
+ ((?S ?i) . ?\x30b7)
+ ((?Z ?i) . ?\x30b8)
+ ((?S ?u) . ?\x30b9)
+ ((?Z ?u) . ?\x30ba)
+ ((?S ?e) . ?\x30bb)
+ ((?Z ?e) . ?\x30bc)
+ ((?S ?o) . ?\x30bd)
+ ((?Z ?o) . ?\x30be)
+ ((?T ?a) . ?\x30bf)
+ ((?D ?a) . ?\x30c0)
+ ((?T ?i) . ?\x30c1)
+ ((?D ?i) . ?\x30c2)
+ ((?T ?U) . ?\x30c3)
+ ((?T ?u) . ?\x30c4)
+ ((?D ?u) . ?\x30c5)
+ ((?T ?e) . ?\x30c6)
+ ((?D ?e) . ?\x30c7)
+ ((?T ?o) . ?\x30c8)
+ ((?D ?o) . ?\x30c9)
+ ((?N ?a) . ?\x30ca)
+ ((?N ?i) . ?\x30cb)
+ ((?N ?u) . ?\x30cc)
+ ((?N ?e) . ?\x30cd)
+ ((?N ?o) . ?\x30ce)
+ ((?H ?a) . ?\x30cf)
+ ((?B ?a) . ?\x30d0)
+ ((?P ?a) . ?\x30d1)
+ ((?H ?i) . ?\x30d2)
+ ((?B ?i) . ?\x30d3)
+ ((?P ?i) . ?\x30d4)
+ ((?H ?u) . ?\x30d5)
+ ((?B ?u) . ?\x30d6)
+ ((?P ?u) . ?\x30d7)
+ ((?H ?e) . ?\x30d8)
+ ((?B ?e) . ?\x30d9)
+ ((?P ?e) . ?\x30da)
+ ((?H ?o) . ?\x30db)
+ ((?B ?o) . ?\x30dc)
+ ((?P ?o) . ?\x30dd)
+ ((?u ?R) . ?\x2515)
+ ((?U ?r) . ?\x2516)
+ ((?U ?R) . ?\x2517)
+ ((?u ?l) . ?\x2518)
+ ((?u ?L) . ?\x2519)
+ ((?U ?l) . ?\x251a)
+ ((?U ?L) . ?\x251b)
+ ((?v ?r) . ?\x251c)
+ ((?v ?R) . ?\x251d)
+ ((?V ?r) . ?\x2520)
+ ((?V ?R) . ?\x2523)
+ ((?v ?l) . ?\x2524)
+ ((?v ?L) . ?\x2525)
+ ((?V ?l) . ?\x2528)
+ ((?V ?L) . ?\x252b)
+ ((?d ?h) . ?\x252c)
+ ((?d ?H) . ?\x252f)
+ ((?D ?h) . ?\x2530)
+ ((?D ?H) . ?\x2533)
+ ((?u ?h) . ?\x2534)
+ ((?u ?H) . ?\x2537)
+ ((?U ?h) . ?\x2538)
+ ((?U ?H) . ?\x253b)
+ ((?v ?h) . ?\x253c)
+ ((?v ?H) . ?\x253f)
+ ((?V ?h) . ?\x2542)
+ ((?V ?H) . ?\x254b)
+ ((?F ?D) . ?\x2571)
+ ((?B ?D) . ?\x2572)
+ ((?T ?B) . ?\x2580)
+ ((?L ?B) . ?\x2584)
+ ((?F ?B) . ?\x2588)
+ ((?l ?B) . ?\x258c)
+ ((?R ?B) . ?\x2590)
+ ((?. ?S) . ?\x2591)
+ ((?: ?S) . ?\x2592)
+ ((?? ?S) . ?\x2593)
+ ((?f ?S) . ?\x25a0)
+ ((?O ?S) . ?\x25a1)
+ ((?R ?O) . ?\x25a2)
+ ((?R ?r) . ?\x25a3)
+ ((?R ?F) . ?\x25a4)
+ ((?R ?Y) . ?\x25a5)
+ ((?R ?H) . ?\x25a6)
+ ((?R ?Z) . ?\x25a7)
+ ((?R ?K) . ?\x25a8)
+ ((?R ?X) . ?\x25a9)
+ ((?s ?B) . ?\x25aa)
+ ((?S ?R) . ?\x25ac)
+ ((?O ?r) . ?\x25ad)
+ ((?U ?T) . ?\x25b2)
+ ((?u ?T) . ?\x25b3)
+ ((?P ?R) . ?\x25b6)
+ ((?T ?r) . ?\x25b7)
+ ((?D ?t) . ?\x25bc)
+ ((?d ?T) . ?\x25bd)
+ ((?P ?L) . ?\x25c0)
+ ((?T ?l) . ?\x25c1)
+ ((?D ?b) . ?\x25c6)
+ ((?D ?w) . ?\x25c7)
+ ((?L ?Z) . ?\x25ca)
+ ((?0 ?m) . ?\x25cb)
+ ((?0 ?o) . ?\x25ce)
+ ((?0 ?M) . ?\x25cf)
+ ((?0 ?L) . ?\x25d0)
+ ((?0 ?R) . ?\x25d1)
+ ((?S ?n) . ?\x25d8)
+ ((?I ?c) . ?\x25d9)
+ ((?F ?d) . ?\x25e2)
+ ((?B ?d) . ?\x25e3)
+ ((?* ?2) . ?\x2605)
+ ((?* ?1) . ?\x2606)
+ ((?< ?H) . ?\x261c)
+ ((?> ?H) . ?\x261e)
+ ((?0 ?u) . ?\x263a)
+ ((?0 ?U) . ?\x263b)
+ ((?S ?U) . ?\x263c)
+ ((?F ?m) . ?\x2640)
+ ((?M ?l) . ?\x2642)
+ ((?c ?S) . ?\x2660)
+ ((?c ?H) . ?\x2661)
+ ((?c ?D) . ?\x2662)
+ ((?c ?C) . ?\x2663)
+ ((?M ?d) . ?\x2669)
+ ((?M ?8) . ?\x266a)
+ ((?M ?2) . ?\x266b)
+ ((?M ?b) . ?\x266d)
+ ((?M ?x) . ?\x266e)
+ ((?M ?X) . ?\x266f)
+ ((?O ?K) . ?\x2713)
+ ((?X ?X) . ?\x2717)
+ ((?- ?X) . ?\x2720)
+ ((?I ?S) . ?\x3000)
+ ((?, ?_) . ?\x3001)
+ ((?. ?_) . ?\x3002)
+ ((?+ ?\") . ?\x3003)
+ ((?+ ?_) . ?\x3004)
+ ((?* ?_) . ?\x3005)
+ ((?\; ?_) . ?\x3006)
+ ((?0 ?_) . ?\x3007)
+ ((?< ?+) . ?\x300a)
+ ((?> ?+) . ?\x300b)
+ ((?< ?') . ?\x300c)
+ ((?> ?') . ?\x300d)
+ ((?< ?\") . ?\x300e)
+ ((?> ?\") . ?\x300f)
+ ((?\( ?\") . ?\x3010)
+ ((?\) ?\") . ?\x3011)
+ ((?= ?T) . ?\x3012)
+ ((?= ?_) . ?\x3013)
+ ((?\( ?') . ?\x3014)
+ ((?\) ?') . ?\x3015)
+ ((?\( ?I) . ?\x3016)
+ ((?\) ?I) . ?\x3017)
+ ((?- ??) . ?\x301c)
+ ((?A ?5) . ?\x3041)
+ ((?a ?5) . ?\x3042)
+ ((?I ?5) . ?\x3043)
+ ((?i ?5) . ?\x3044)
+ ((?U ?5) . ?\x3045)
+ ((?u ?5) . ?\x3046)
+ ((?E ?5) . ?\x3047)
+ ((?e ?5) . ?\x3048)
+ ((?O ?5) . ?\x3049)
+ ((?o ?5) . ?\x304a)
+ ((?k ?a) . ?\x304b)
+ ((?g ?a) . ?\x304c)
+ ((?k ?i) . ?\x304d)
+ ((?g ?i) . ?\x304e)
+ ((?k ?u) . ?\x304f)
+ ((?g ?u) . ?\x3050)
+ ((?k ?e) . ?\x3051)
+ ((?g ?e) . ?\x3052)
+ ((?k ?o) . ?\x3053)
+ ((?g ?o) . ?\x3054)
+ ((?s ?a) . ?\x3055)
+ ((?z ?a) . ?\x3056)
+ ((?s ?i) . ?\x3057)
+ ((?z ?i) . ?\x3058)
+ ((?s ?u) . ?\x3059)
+ ((?z ?u) . ?\x305a)
+ ((?s ?e) . ?\x305b)
+ ((?z ?e) . ?\x305c)
+ ((?s ?o) . ?\x305d)
+ ((?z ?o) . ?\x305e)
+ ((?t ?a) . ?\x305f)
+ ((?d ?a) . ?\x3060)
+ ((?t ?i) . ?\x3061)
+ ((?d ?i) . ?\x3062)
+ ((?t ?U) . ?\x3063)
+ ((?t ?u) . ?\x3064)
+ ((?d ?u) . ?\x3065)
+ ((?t ?e) . ?\x3066)
+ ((?d ?e) . ?\x3067)
+ ((?t ?o) . ?\x3068)
+ ((?d ?o) . ?\x3069)
+ ((?n ?a) . ?\x306a)
+ ((?n ?i) . ?\x306b)
+ ((?n ?u) . ?\x306c)
+ ((?n ?e) . ?\x306d)
+ ((?n ?o) . ?\x306e)
+ ((?h ?a) . ?\x306f)
+ ((?b ?a) . ?\x3070)
+ ((?p ?a) . ?\x3071)
+ ((?h ?i) . ?\x3072)
+ ((?b ?i) . ?\x3073)
+ ((?p ?i) . ?\x3074)
+ ((?h ?u) . ?\x3075)
+ ((?b ?u) . ?\x3076)
+ ((?p ?u) . ?\x3077)
+ ((?h ?e) . ?\x3078)
+ ((?b ?e) . ?\x3079)
+ ((?p ?e) . ?\x307a)
+ ((?h ?o) . ?\x307b)
+ ((?b ?o) . ?\x307c)
+ ((?p ?o) . ?\x307d)
+ ((?m ?a) . ?\x307e)
+ ((?m ?i) . ?\x307f)
+ ((?m ?u) . ?\x3080)
+ ((?m ?e) . ?\x3081)
+ ((?m ?o) . ?\x3082)
+ ((?y ?A) . ?\x3083)
+ ((?y ?a) . ?\x3084)
+ ((?y ?U) . ?\x3085)
+ ((?y ?u) . ?\x3086)
+ ((?y ?O) . ?\x3087)
+ ((?y ?o) . ?\x3088)
+ ((?r ?a) . ?\x3089)
+ ((?r ?i) . ?\x308a)
+ ((?r ?u) . ?\x308b)
+ ((?r ?e) . ?\x308c)
+ ((?r ?o) . ?\x308d)
+ ((?w ?A) . ?\x308e)
+ ((?w ?a) . ?\x308f)
+ ((?w ?i) . ?\x3090)
+ ((?w ?e) . ?\x3091)
+ ((?w ?o) . ?\x3092)
+ ((?n ?5) . ?\x3093)
+ ((?v ?u) . ?\x3094)
+ ((?\" ?5) . ?\x309b)
+ ((?0 ?5) . ?\x309c)
+ ((?* ?5) . ?\x309d)
+ ((?+ ?5) . ?\x309e)
+ ((?a ?6) . ?\x30a1)
+ ((?A ?6) . ?\x30a2)
+ ((?i ?6) . ?\x30a3)
+ ((?I ?6) . ?\x30a4)
+ ((?u ?6) . ?\x30a5)
+ ((?U ?6) . ?\x30a6)
+ ((?e ?6) . ?\x30a7)
+ ((?E ?6) . ?\x30a8)
+ ((?o ?6) . ?\x30a9)
+ ((?O ?6) . ?\x30aa)
+ ((?K ?a) . ?\x30ab)
+ ((?G ?a) . ?\x30ac)
+ ((?K ?i) . ?\x30ad)
+ ((?G ?i) . ?\x30ae)
+ ((?K ?u) . ?\x30af)
+ ((?G ?u) . ?\x30b0)
+ ((?K ?e) . ?\x30b1)
+ ((?G ?e) . ?\x30b2)
+ ((?K ?o) . ?\x30b3)
+ ((?G ?o) . ?\x30b4)
+ ((?S ?a) . ?\x30b5)
+ ((?Z ?a) . ?\x30b6)
+ ((?S ?i) . ?\x30b7)
+ ((?Z ?i) . ?\x30b8)
+ ((?S ?u) . ?\x30b9)
+ ((?Z ?u) . ?\x30ba)
+ ((?S ?e) . ?\x30bb)
+ ((?Z ?e) . ?\x30bc)
+ ((?S ?o) . ?\x30bd)
+ ((?Z ?o) . ?\x30be)
+ ((?T ?a) . ?\x30bf)
+ ((?D ?a) . ?\x30c0)
+ ((?T ?i) . ?\x30c1)
+ ((?D ?i) . ?\x30c2)
+ ((?T ?U) . ?\x30c3)
+ ((?T ?u) . ?\x30c4)
+ ((?D ?u) . ?\x30c5)
+ ((?T ?e) . ?\x30c6)
+ ((?D ?e) . ?\x30c7)
+ ((?T ?o) . ?\x30c8)
+ ((?D ?o) . ?\x30c9)
+ ((?N ?a) . ?\x30ca)
+ ((?N ?i) . ?\x30cb)
+ ((?N ?u) . ?\x30cc)
+ ((?N ?e) . ?\x30cd)
+ ((?N ?o) . ?\x30ce)
+ ((?H ?a) . ?\x30cf)
+ ((?B ?a) . ?\x30d0)
+ ((?P ?a) . ?\x30d1)
+ ((?H ?i) . ?\x30d2)
+ ((?B ?i) . ?\x30d3)
+ ((?P ?i) . ?\x30d4)
+ ((?H ?u) . ?\x30d5)
+ ((?B ?u) . ?\x30d6)
+ ((?P ?u) . ?\x30d7)
+ ((?H ?e) . ?\x30d8)
+ ((?B ?e) . ?\x30d9)
+ ((?P ?e) . ?\x30da)
+ ((?H ?o) . ?\x30db)
+ ((?B ?o) . ?\x30dc)
+ ((?P ?o) . ?\x30dd)
+ ((?M ?a) . ?\x30de)
+ ((?M ?i) . ?\x30df)
+ ((?M ?u) . ?\x30e0)
+ ((?M ?e) . ?\x30e1)
+ ((?M ?o) . ?\x30e2)
+ ((?Y ?A) . ?\x30e3)
+ ((?Y ?a) . ?\x30e4)
+ ((?Y ?U) . ?\x30e5)
+ ((?Y ?u) . ?\x30e6)
+ ((?Y ?O) . ?\x30e7)
+ ((?Y ?o) . ?\x30e8)
+ ((?R ?a) . ?\x30e9)
+ ((?R ?i) . ?\x30ea)
+ ((?R ?u) . ?\x30eb)
+ ((?R ?e) . ?\x30ec)
+ ((?R ?o) . ?\x30ed)
+ ((?W ?A) . ?\x30ee)
+ ((?W ?a) . ?\x30ef)
+ ((?W ?i) . ?\x30f0)
+ ((?W ?e) . ?\x30f1)
+ ((?W ?o) . ?\x30f2)
+ ((?N ?6) . ?\x30f3)
+ ((?V ?u) . ?\x30f4)
+ ((?K ?A) . ?\x30f5)
+ ((?K ?E) . ?\x30f6)
+ ((?V ?a) . ?\x30f7)
+ ((?V ?i) . ?\x30f8)
+ ((?V ?e) . ?\x30f9)
+ ((?V ?o) . ?\x30fa)
+ ((?. ?6) . ?\x30fb)
+ ((?- ?6) . ?\x30fc)
+ ((?* ?6) . ?\x30fd)
+ ((?+ ?6) . ?\x30fe)
+ ((?b ?4) . ?\x3105)
+ ((?p ?4) . ?\x3106)
+ ((?m ?4) . ?\x3107)
+ ((?f ?4) . ?\x3108)
+ ((?d ?4) . ?\x3109)
+ ((?t ?4) . ?\x310a)
+ ((?n ?4) . ?\x310b)
+ ((?l ?4) . ?\x310c)
+ ((?g ?4) . ?\x310d)
+ ((?k ?4) . ?\x310e)
+ ((?h ?4) . ?\x310f)
+ ((?j ?4) . ?\x3110)
+ ((?q ?4) . ?\x3111)
+ ((?x ?4) . ?\x3112)
+ ((?z ?h) . ?\x3113)
+ ((?c ?h) . ?\x3114)
+ ((?s ?h) . ?\x3115)
+ ((?r ?4) . ?\x3116)
+ ((?z ?4) . ?\x3117)
+ ((?c ?4) . ?\x3118)
+ ((?s ?4) . ?\x3119)
+ ((?a ?4) . ?\x311a)
+ ((?o ?4) . ?\x311b)
+ ((?e ?4) . ?\x311c)
+ ((?a ?i) . ?\x311e)
+ ((?e ?i) . ?\x311f)
+ ((?a ?u) . ?\x3120)
+ ((?o ?u) . ?\x3121)
+ ((?a ?n) . ?\x3122)
+ ((?e ?n) . ?\x3123)
+ ((?a ?N) . ?\x3124)
+ ((?e ?N) . ?\x3125)
+ ((?e ?r) . ?\x3126)
+ ((?i ?4) . ?\x3127)
+ ((?u ?4) . ?\x3128)
+ ((?i ?u) . ?\x3129)
+ ((?v ?4) . ?\x312a)
+ ((?n ?G) . ?\x312b)
+ ((?g ?n) . ?\x312c)
+ ((?1 ?c) . ?\x3220)
+ ((?2 ?c) . ?\x3221)
+ ((?3 ?c) . ?\x3222)
+ ((?4 ?c) . ?\x3223)
+ ((?5 ?c) . ?\x3224)
+ ((?6 ?c) . ?\x3225)
+ ((?7 ?c) . ?\x3226)
+ ((?8 ?c) . ?\x3227)
+ ((?9 ?c) . ?\x3228)
+ ((?\s ?\s) . ?\xe000)
+ ((?/ ?c) . ?\xe001)
+ ((?U ?A) . ?\xe002)
+ ((?U ?B) . ?\xe003)
+ ((?\" ?3) . ?\xe004)
+ ((?\" ?1) . ?\xe005)
+ ((?\" ?!) . ?\xe006)
+ ((?\" ?') . ?\xe007)
+ ((?\" ?>) . ?\xe008)
+ ((?\" ??) . ?\xe009)
+ ((?\" ?-) . ?\xe00a)
+ ((?\" ?\() . ?\xe00b)
+ ((?\" ?.) . ?\xe00c)
+ ((?\" ?:) . ?\xe00d)
+ ((?\" ?0) . ?\xe00e)
+ ((?\" ?\") . ?\xe00f)
+ ((?\" ?<) . ?\xe010)
+ ((?\" ?,) . ?\xe011)
+ ((?\" ?\;) . ?\xe012)
+ ((?\" ?_) . ?\xe013)
+ ((?\" ?=) . ?\xe014)
+ ((?\" ?/) . ?\xe015)
+ ((?\" ?i) . ?\xe016)
+ ((?\" ?d) . ?\xe017)
+ ((?\" ?p) . ?\xe018)
+ ((?\; ?\;) . ?\xe019)
+ ((?, ?,) . ?\xe01a)
+ ((?b ?3) . ?\xe01b)
+ ((?C ?i) . ?\xe01c)
+ ((?f ?\() . ?\xe01d)
+ ((?e ?d) . ?\xe01e)
+ ((?a ?m) . ?\xe01f)
+ ((?p ?m) . ?\xe020)
+ ((?F ?l) . ?\xe023)
+ ((?G ?F) . ?\xe024)
+ ((?> ?V) . ?\xe025)
+ ((?! ?*) . ?\xe026)
+ ((?? ?*) . ?\xe027)
+ ((?J ?<) . ?\xe028)
+ ((?f ?f) . ?\xfb00)
+ ((?f ?i) . ?\xfb01)
+ ((?f ?l) . ?\xfb02)
+ ((?f ?t) . ?\xfb05)
+ ((?s ?t) . ?\xfb06)
+ ((?~ ?!) . ?\x00a1)
+ ((?c ?|) . ?\x00a2)
+ ((?$ ?$) . ?\x00a3)
+ ((?o ?x) . ?\x00a4)
+ ((?Y ?-) . ?\x00a5)
+ ((?| ?|) . ?\x00a6)
+ ((?c ?O) . ?\x00a9)
+ ((?- ?,) . ?\x00ac)
+ ((?- ?=) . ?\x00af)
+ ((?~ ?o) . ?\x00b0)
+ ((?2 ?2) . ?\x00b2)
+ ((?3 ?3) . ?\x00b3)
+ ((?p ?p) . ?\x00b6)
+ ((?~ ?.) . ?\x00b7)
+ ((?1 ?1) . ?\x00b9)
+ ((?~ ??) . ?\x00bf)
+ ((?A ?`) . ?\x00c0)
+ ((?A ?^) . ?\x00c2)
+ ((?A ?~) . ?\x00c3)
+ ((?A ?\") . ?\x00c4)
+ ((?A ?@) . ?\x00c5)
+ ((?E ?`) . ?\x00c8)
+ ((?E ?^) . ?\x00ca)
+ ((?E ?\") . ?\x00cb)
+ ((?I ?`) . ?\x00cc)
+ ((?I ?^) . ?\x00ce)
+ ((?I ?\") . ?\x00cf)
+ ((?N ?~) . ?\x00d1)
+ ((?O ?`) . ?\x00d2)
+ ((?O ?^) . ?\x00d4)
+ ((?O ?~) . ?\x00d5)
+ ((?/ ?\\) . ?\x00d7)
+ ((?U ?`) . ?\x00d9)
+ ((?U ?^) . ?\x00db)
+ ((?I ?p) . ?\x00de)
+ ((?a ?`) . ?\x00e0)
+ ((?a ?^) . ?\x00e2)
+ ((?a ?~) . ?\x00e3)
+ ((?a ?\") . ?\x00e4)
+ ((?a ?@) . ?\x00e5)
+ ((?e ?`) . ?\x00e8)
+ ((?e ?^) . ?\x00ea)
+ ((?e ?\") . ?\x00eb)
+ ((?i ?`) . ?\x00ec)
+ ((?i ?^) . ?\x00ee)
+ ((?n ?~) . ?\x00f1)
+ ((?o ?`) . ?\x00f2)
+ ((?o ?^) . ?\x00f4)
+ ((?o ?~) . ?\x00f5)
+ ((?u ?`) . ?\x00f9)
+ ((?u ?^) . ?\x00fb)
+ ((?y ?\") . ?\x00ff))
+ "Table of default digraphs.
+This includes all digraphs defined in RFC 1345,
+as well as miscellaneous digraphs for multi-byte characters.
+See also `evil-digraphs-table-user'.")
+
+;;;###autoload
+(defun evil-digraph (digraph)
+ "Convert DIGRAPH to character or list representation.
+If DIGRAPH is a list (CHAR1 CHAR2), return the corresponding character;
+if DIGRAPH is a character, return the corresponding list.
+Searches in `evil-digraphs-table-user' and `evil-digraphs-table'."
+ (if (listp digraph)
+ (or (cdr (assoc digraph evil-digraphs-table-user))
+ (cdr (assoc digraph evil-digraphs-table))
+ (cl-destructuring-bind (char1 char2) digraph
+ (unless (eq char1 char2)
+ (or (cdr (assoc (list char2 char1) evil-digraphs-table-user))
+ (cdr (assoc (list char2 char1) evil-digraphs-table))))))
+ (or (car (rassoc digraph evil-digraphs-table-user))
+ (car (rassoc digraph evil-digraphs-table)))))
+
+(provide 'evil-digraphs)
+
+;;; evil-digraphs.el ends here
diff --git a/.config/emacs/lisp/evil/evil-ex.el b/.config/emacs/lisp/evil/evil-ex.el
new file mode 100644
index 0000000..94edd6e
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-ex.el
@@ -0,0 +1,940 @@
+;;; evil-ex.el --- Ex mode -*- lexical-binding: t; -*-
+
+;; Author: Frank Fischer <frank fischer at mathematik.tu-chemnitz.de>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Ex is implemented as an extensible minilanguage, whose grammar
+;; is stored in `evil-ex-grammar'. Ex commands are defined with
+;; `evil-ex-define-cmd', which creates a binding from a string
+;; to an interactive function. It is also possible to define key
+;; sequences which execute a command immediately when entered:
+;; such shortcuts go in `evil-ex-shortcut-map'.
+
+;; To provide buffer and filename completion, as well as interactive
+;; feedback, Ex defines the concept of an argument handler, specified
+;; with `evil-ex-define-argument-type'. In the case of the
+;; substitution command (":s/foo/bar"), the handler incrementally
+;; highlights matches in the buffer as the substitution is typed.
+
+;;; Code:
+
+(require 'evil-common)
+(require 'evil-states)
+
+(declare-function evil-goto-line "evil-commands")
+
+(eval-when-compile
+ (defconst evil-ex-grammar
+ '((expression
+ (count command argument #'evil-ex-call-command)
+ ((\? range) command argument #'evil-ex-call-command)
+ (line #'evil-goto-line)
+ (sexp #'eval-expression))
+ (count
+ number)
+ (command #'evil-ex-parse-command)
+ (binding
+ "[~&*@<>=:#]+\\|[[:alpha:]_]+\\|!")
+ (emacs-binding
+ "[[:alpha:]-][[:alnum:][:punct:]]*")
+ (argument
+ ((\? "\\(?:.\\|\n\\)+") #'$1))
+ (range
+ ("%" #'(evil-ex-full-range))
+ ("*" #'(evil-ex-last-visual-range))
+ ((\? line) "[,;]" (\? line)
+ #'(let ((l1 $1))
+ (save-excursion
+ (and l1 (string= $2 ";") (goto-line l1))
+ (evil-ex-range l1 $3))))
+ (line #'evil-ex-range)
+ ("`" marker-name ",`" marker-name
+ #'(evil-ex-char-marker-range $2 $4)))
+ (line
+ ((\? base) (\? offset) search (\? offset)
+ #'(save-excursion
+ (goto-line (evil-ex-line $1 $2))
+ (evil-ex-line $3 $4)))
+ (base (\? offset) #'evil-ex-line)
+ (nil offset #'evil-ex-line))
+ (base
+ number
+ ("'" marker-name #'(evil-ex-marker $2))
+ search
+ ("\\^" #'(evil-ex-first-line))
+ ("\\$" #'(evil-ex-last-line))
+ ("\\." #'(evil-ex-current-line)))
+ (offset
+ (+ signed-number #'+))
+ ;; TODO - handle offset & ;next-pattern search elements
+ (search
+ forward
+ backward
+ next
+ prev
+ subst)
+ (forward
+ ("/" "\\(?:\\\\.\\|[^/]\\)+" "/\\|$" #'(evil-ex-re-fwd $2)))
+ (backward
+ ("?" "\\(?:\\\\.\\|[^?]\\)+" "?\\|$" #'(evil-ex-re-bwd $2)))
+ (marker-name
+ "[]\\[-a-zA-Z_<>'}{)(]")
+ (next
+ "\\\\/" #'(evil-ex-prev-search))
+ (prev
+ "\\\\\\?" #'(evil-ex-prev-search))
+ (subst
+ "\\\\&" #'(evil-ex-prev-search))
+ (signed-number
+ (sign (\? number) #'evil-ex-signed-number))
+ (sign
+ "[+-]" #'intern)
+ (number
+ "[0-9]+" #'string-to-number)
+ (sexp
+ "(.*)?" #'(car (read-from-string $0))))
+ "Grammar for Ex.
+An association list of syntactic symbols and their definitions.
+The first entry is the start symbol. A symbol's definition may
+reference other symbols, but the grammar cannot contain
+left recursion. See `evil-parser' for a detailed explanation
+of the syntax.")
+
+ (defun evil-parser--dexp (obj)
+ "Parse a numerical dollar-sign symbol.
+Given e.g. $4, return 4."
+ (when (symbolp obj)
+ (let ((str (symbol-name obj)))
+ (when (string-match "\\`\\$\\([0-9]+\\)\\'" str)
+ (string-to-number (match-string 1 str))))))
+
+ (defmacro evil-parser (grammar &rest entrypoints)
+ "Construct a parser for GRAMMAR with ENTRYPOINTS.
+The result is a function taking the arguments SYMBOL and SYNTAX, that
+parses the text after point. SYMBOL should be one of ENTRYPOINTS.
+
+If parsing succeeds, point is moved to the end of the parsed text and
+a 1-tuple (RESULT) is returned. Otherwise, the return value is nil.
+
+GRAMMAR is an association list of symbols and their definitions.
+A definition is a list of production rules, which are tried in
+succession. A production rule can be one of the following:
+
+ nil matches the empty string.
+ A regular expression matches a substring.
+ A symbol matches a production for that symbol.
+ (X Y) matches X followed by Y.
+ (\\? X) matches zero or one of X.
+ (* X) matches zero or more of X.
+ (+ X) matches one or more of X.
+ (& X) matches X, but does not consume.
+ (! X) matches anything but X, but does not consume.
+
+Thus, a simple grammar may look like:
+
+ ((plus \"\\\\+\") ; plus <- \"+\"
+ (minus \"-\") ; minus <- \"-\"
+ (operator plus minus)) ; operator <- plus / minus
+
+All input-consuming rules have a value. A regular expression evaluates
+to the text matched, while a list evaluates to a list of values.
+The value of a list may be overridden with a semantic action, which is
+specified with a #\\='-quoted expression at the end:
+
+ (X Y #\\='foo)
+
+The value of this rule is the result of calling foo with the values
+of X and Y as arguments. Alternatively, the function call may be
+specified explicitly:
+
+ (X Y #\\='(foo $1 $2))
+
+Here, $1 refers to X and $2 refers to Y. $0 refers to the whole list.
+Dollar expressions can also be used directly:
+
+ (X Y #\\='$1)
+
+This matches X followed by Y, but ignores the value of Y;
+the value of the list is the same as the value of X.
+
+If the SYNTAX argument is non-nil, then all semantic actions
+are ignored, and a syntax tree is constructed instead. The
+syntax tree obeys the property that all the leaf nodes are
+parts of the input string. Thus, by traversing the syntax tree,
+one can determine how each character was parsed.
+
+The following symbols have reserved meanings within a grammar:
+`\\?', `*', `+', `&', `!', `function', `alt', `seq' and nil."
+ (cl-labels
+ ;; Return code for parsing PRODUCTION.
+ ((compile
+ (production)
+ (pcase production
+ ('nil '(list (when syntax (point)))) ; Epsilon
+ ((and (pred stringp) regexp) ; Token
+ `(when (progn
+ (skip-chars-forward " \t\n\r") ; Ignore leading whitespace
+ (looking-at ,regexp))
+ (goto-char (match-end 0))
+ (list (if syntax (point) (match-string 0)))))
+ ((and (pred symbolp) symbol) ; Symbol
+ `(let ((result (,symbol syntax)))
+ (and syntax result (push ',symbol (car result)))
+ result))
+ (`(function ,fun) ; Function
+ `(let ((result (funcall #',fun)))
+ (and syntax result (setcar result (point)))
+ result))
+ ;; Positive lookahead
+ (`(& . ,rule) `(when ,(compile rule) ,(compile nil)))
+ ;; Negative lookahead
+ (`(! . ,rule) `(unless ,(compile rule) ,(compile nil)))
+ ;; Zero or one
+ (`(\? . ,(or `(,rule) rule)) (compile `(alt ,rule nil)))
+ ;; Zero or more
+ (`(* . ,rules) (compile `(alt (+ ,@rules) nil)))
+ ;; Lists
+ ((or `(,(and (or '+ 'alt 'seq) symbol) . ,rules)
+ (and (pred listp) rules (let symbol 'seq)))
+ (let ((func (unless (eq symbol 'alt) #'list)))
+ (pcase (when (> (length rules) 1) (car (last rules)))
+ (`(function ,x) (setq func x
+ rules (butlast rules))))
+ `(let ((cell
+ ,(pcase symbol
+ ('+ ; One or more
+ (when (cdr rules) (error "Too many `+' rules"))
+ `(cl-loop for x = ,(compile (car rules))
+ while x collect (car x) into result until (eobp)
+ finally return (when result (list result))))
+ ('alt `(or ,@(mapcar #'compile rules)))
+ ('seq
+ (cl-loop
+ for rule in rules collect
+ (macroexp-let2 nil x (compile rule)
+ (if (memq (car-safe rule) '(& !)) x
+ `(when ,x (push (car ,x) result))))
+ into items finally return
+ `(let ((pos (point)) result)
+ (if (and ,@items) (list (nreverse result))
+ (goto-char pos)
+ nil)))))))
+ ;; Semantic action
+ (when (and ',func cell (not syntax))
+ (setcar
+ cell
+ (let ((result (car cell)))
+ (ignore result) ; Suppress unused var warning
+ ,(pcase func
+ ;; Dollar expression
+ ((or (pred evil-parser--dexp) (pred listp))
+ (dval func))
+ ((pred symbolp)
+ `(,(if (eq symbol 'alt) #'list #'cons) #',func result))
+ (_ (error "Invalid semantic action `%S'" func))))))
+ cell)))))
+ ;; Substitute all dollar-sign symbols in X.
+ ;; Each dollar-sign symbol is replaced with the corresponding
+ ;; element in RESULT, so that $1 becomes the first element, etc.
+ ;; The special value $0 is substituted with the whole list RESULT.
+ (dval
+ (x)
+ (if (listp x) (cons #'list (mapcar #'dval x))
+ (let ((num (evil-parser--dexp x)))
+ (cond ((null num) `',x)
+ ((eq num 0) 'result)
+ (t `(nth (1- ,num) result)))))))
+ `(lambda (symbol &optional syntax)
+ (cl-labels
+ (,@(cl-loop for (symbol . def) in (eval grammar t) collect
+ `(,symbol (syntax) ,(compile `(alt . ,def))))
+ (evil-ex-parse-command
+ ()
+ (let* ((result (binding nil))
+ (command (car result)))
+ (cond
+ ((not result) nil)
+ ;; Check whether the parsed command is followed by a slash,
+ ;; dash or number and either the part before is NOT known to be
+ ;; a binding, or the complete string IS known to be a binding.
+ ((and (let ((ch (char-after)))
+ (and ch (or (memq ch '(?- ?/)) (<= ?0 ch ?9))))
+ (or (evil-ex-binding
+ (concat command (buffer-substring (point) (point-max))) t)
+ (not (evil-ex-binding command t))))
+ (backward-char (length command))
+ (emacs-binding nil))
+ ;; Parse a following "!" as bang only if the command
+ ;; has the property :ex-bang t.
+ ((when (eq (char-after) ?!)
+ (let ((binding (evil-ex-completed-binding command t)))
+ (and binding (evil-get-command-property binding :ex-bang))))
+ (forward-char)
+ (setcar result (concat command "!"))
+ result)
+ (t result)))))
+ (pcase symbol
+ ,@(cl-loop for sym in entrypoints collect `(',sym ,(compile sym)))
+ (_ (error "Unknown entrypoint `%s'" symbol))))))))
+
+(defvar evil-ex-argument-types nil
+ "Association list of argument handlers.")
+
+(defvar evil-ex-commands nil
+ "Association list of command bindings and functions.")
+
+(defvar evil-ex-reverse-range nil
+ "Whether the current Ex range was entered reversed.")
+
+(defvar evil--ex-cmd nil
+ "The current Ex command string.")
+
+(defvar evil--ex-argument-handler nil
+ "The argument handler for the current Ex command.")
+
+(defvar evil--ex-shortcut-command nil
+ "Interactive command to use instead of an Ex command.")
+
+(define-error 'evil-ex-error "Ex syntax error")
+
+(defun evil-ex-p ()
+ "Return non-nil if currently in Ex state."
+ (when evil-ex-original-buffer t))
+
+(evil-define-command evil-ex (&optional initial-input)
+ "Enter an Ex command.
+The Ex command line is initialized with the value of INITIAL-INPUT. If
+the command is called interactively the initial input depends on the
+current state. In Normal state if a prefix count is given then the
+initial input is \".,.+count\", otherwise it is empty. In Visual state
+the initial input is the visual region '<,'> or `<,`>. The variable
+`evil-ex-initial-input', if non-nil, is appended to the line."
+ :keep-visual t
+ :repeat abort
+ (interactive
+ (let ((s (concat
+ (cond
+ ((and (evil-visual-state-p)
+ evil-ex-visual-char-range
+ (memq (evil-visual-type) '(inclusive exclusive)))
+ "`<,`>")
+ ((evil-visual-state-p) "'<,'>")
+ (current-prefix-arg
+ (let ((arg (prefix-numeric-value current-prefix-arg)))
+ (cond ((< arg 0) (setq arg (1+ arg)))
+ ((> arg 0) (setq arg (1- arg))))
+ (if (= arg 0) "." (format ".,.%+d" arg)))))
+ evil-ex-initial-input)))
+ (list (unless (string= s "") s))))
+ (let ((buffer (current-buffer))
+ (previous-command (when evil-want-empty-ex-last-command
+ (car evil-ex-history)))
+ s evil--ex-cmd evil--ex-argument-handler evil--ex-shortcut-command)
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (setq-local evil-ex-original-buffer buffer)
+ (evil-ex-setup)
+ (if initial-input (evil--ex-update)
+ (when previous-command
+ (add-hook 'pre-command-hook #'evil-ex-remove-default nil t))))
+ (setq s (read-from-minibuffer
+ ":"
+ (or initial-input
+ (and previous-command (propertize previous-command 'face 'shadow)))
+ evil-ex-completion-map nil 'evil-ex-history)))
+ (if evil--ex-shortcut-command
+ (call-interactively evil--ex-shortcut-command)
+ (when (string= s "") (setq s previous-command))
+ (unless (string= s "") (evil-ex-execute s)))))
+
+(defun evil-ex-execute (string)
+ "Execute STRING as an Ex command."
+ (eval (or (evil-ex-parse string) (signal 'evil-ex-error string)) t))
+
+(defun evil-ex-parse (&optional string syntax entrypoint)
+ "Parse STRING as an Ex expression and return its evaluation tree.
+If STRING is nil, parse the text after point instead. If SYNTAX is
+non-nil, return a syntax tree instead. ENTRYPOINT is the start
+symbol, which defaults to `expression'."
+ (if string
+ (with-temp-buffer
+ (insert string)
+ (goto-char (point-min))
+ (evil-ex-parse nil syntax entrypoint))
+ (let ((result (funcall (evil-parser evil-ex-grammar expression range)
+ (or entrypoint 'expression) syntax)))
+ (and result
+ ;; Disallow incomplete matches (ignore trailing WS)
+ (not (search-forward "[^ \t\n\r]" nil t))
+ (car result)))))
+
+(defun evil-ex-delete-backward-char ()
+ "Close the minibuffer if it is empty, otherwise call `delete-backward-char'."
+ (interactive)
+ (call-interactively
+ (if (< (minibuffer-prompt-end) (point-max))
+ #'delete-backward-char
+ #'abort-recursive-edit)))
+
+(cl-defstruct (evil-ex-argument-handler (:type list) (:constructor nil)
+ (:copier nil) (:predicate nil))
+ (runner nil :read-only t) (completer nil :read-only t))
+
+(defun evil-ex-setup ()
+ "Initialize Ex minibuffer.
+This function registers hooks that are used for the interactive
+actions during Ex state."
+ (add-hook 'after-change-functions #'evil--ex-update nil t)
+ (add-hook 'minibuffer-exit-hook #'evil-ex-teardown nil t)
+ (add-hook 'completion-at-point-functions #'evil-ex-completion-at-point nil t))
+
+(defsubst evil--ex-bang-p (command)
+ "Return non-nil if the string COMMAND has a \"!\" suffix."
+ (and (> (length command) 1) (eq (aref command (1- (length command))) ?!)))
+
+(defun evil--ex-update (&optional beg _end _old-len)
+ "Update Ex variables when the minibuffer changes.
+This function is usually called from `after-change-functions'
+hook. If BEG is non-nil (which is the case when called from
+`after-change-functions'), then an error description is shown
+in case of incomplete or unknown commands."
+ (when (and beg (eq this-command #'self-insert-command))
+ (let ((cmd (lookup-key evil-ex-shortcut-map (minibuffer-contents-no-properties))))
+ (when (commandp cmd)
+ (setq evil--ex-shortcut-command cmd)
+ (exit-minibuffer))))
+
+ (setq evil--ex-cmd nil)
+ (let ((expr (save-excursion (goto-char (minibuffer-prompt-end))
+ (evil-ex-parse)))
+ func handler current-prefix-arg evil-ex-range evil-ex-bang evil-ex-argument)
+ (when (eq (car expr) #'evil-ex-call-command)
+ (with-current-buffer evil-ex-original-buffer
+ (let* ((range (eval (nth 1 expr) t))
+ (count (when (integerp range) range)))
+ (setq current-prefix-arg count
+ evil-ex-range (if count (evil-ex-range count count) range)
+ evil--ex-cmd (eval (nth 2 expr) t)
+ evil-ex-bang (evil--ex-bang-p evil--ex-cmd)
+ evil-ex-argument (eval (nth 3 expr) t))))
+ (cond
+ ((not beg))
+ ;; Test the current command when called from `after-change-functions'
+ ((setq func (evil-ex-completed-binding evil--ex-cmd t))
+ ;; Update argument handler
+ (let ((type (evil-get-command-property func :ex-arg)))
+ (when type (setq handler (cdr (assq type evil-ex-argument-types)))))
+ (if (eq handler evil--ex-argument-handler)
+ (let ((runner (evil-ex-argument-handler-runner handler)))
+ (when runner (funcall runner 'update evil-ex-argument)))
+ (let ((runner (evil-ex-argument-handler-runner evil--ex-argument-handler)))
+ (when runner (funcall runner 'stop)))
+ (setq evil--ex-argument-handler handler)
+ (let ((runner (evil-ex-argument-handler-runner handler)))
+ (when runner (funcall runner 'start evil-ex-argument)))))
+ (t (let* ((evil-ex-complete-emacs-commands 'in-turn)
+ (prefix (try-completion evil--ex-cmd (evil-ex-completion-table))))
+ (cond ((stringp prefix) (evil-ex-echo "Incomplete command"))
+ ((null prefix) (evil-ex-echo "Unknown command")))))))))
+
+(defun evil-ex-teardown ()
+ "Deinitialize Ex minibuffer.
+Clean up everything set up by `evil-ex-setup'."
+ (let ((runner (evil-ex-argument-handler-runner evil--ex-argument-handler)))
+ (when runner (funcall runner 'stop))))
+
+(defvar-local evil--ex-echo-overlay nil
+ "Overlay for displaying info messages during Ex.")
+
+(defun evil-ex-echo (string &rest args)
+ "Display a message after the current Ex command."
+ ;; Differs from minibuffer-message, which see, in that it does not
+ ;; use sit-for, since it may be called in the middle of a command.
+ (unless (or evil-no-display (zerop (length string)))
+ (let ((string (concat " [" (apply #'format string args) "]")))
+ (put-text-property 0 1 'cursor t string) ; Place cursor before message
+ (put-text-property 1 (length string) 'face 'evil-ex-info string)
+ (with-selected-window (minibuffer-window)
+ (if evil--ex-echo-overlay
+ (move-overlay evil--ex-echo-overlay (point-max) (point-max))
+ (setq evil--ex-echo-overlay (make-overlay (point-max) (point-max) nil t t)))
+ (add-hook 'pre-command-hook #'evil--ex-remove-echo-overlay nil t)
+ (overlay-put evil--ex-echo-overlay 'after-string string)))))
+
+(defun evil--ex-remove-echo-overlay ()
+ "Remove echo overlay from Ex minibuffer."
+ (delete-overlay evil--ex-echo-overlay)
+ (setq evil--ex-echo-overlay nil)
+ (remove-hook 'pre-command-hook #'evil--ex-remove-echo-overlay t))
+
+(cl-defun evil-ex-completion-at-point ()
+ "Function used for `completion-at-point-functions' in Ex state."
+ (cl-flet ((fix-beg (b) (min (save-excursion
+ (+ (goto-char b) (skip-chars-forward " \t\n\r")))
+ (point))))
+ (pcase (nreverse (evil--ex-syntactic-context))
+ ((or (and 'nil (let beg (minibuffer-prompt-end)))
+ `((expression) (command . ,beg) . ,_)
+ (and `((expression) (line) . ,_)
+ (guard (looking-at-p "[ \t\n\r]*\\'"))
+ (let beg (point))))
+ (list (fix-beg beg) (point) (evil-ex-completion-table)))
+ (`((expression) (argument . ,beg))
+ (setq beg (fix-beg beg))
+ ;; If it's an autoload, load the function; this allows external
+ ;; packages to register autoloaded Ex commands which will be
+ ;; loaded when ex argument completion is triggered.
+ (let ((binding (evil-ex-binding evil--ex-cmd t))) (autoload-do-load binding))
+
+ (let* ((binding (evil-ex-completed-binding evil--ex-cmd))
+ (arg-type (evil-get-command-property binding :ex-arg))
+ (arg-handler (cdr (assq arg-type evil-ex-argument-types))))
+ (pcase (evil-ex-argument-handler-completer arg-handler)
+ (`(collection . ,table) (list beg (point-max) table))
+ (`(completion-at-point . ,completer)
+ (save-restriction (narrow-to-region beg (point-max))
+ (funcall completer))))))
+ (`((expression) (sexp . ,_))
+ (when (fboundp 'elisp-completion-at-point) (elisp-completion-at-point))))))
+
+(defun evil-ex-completion-table ()
+ (let ((ex-cmds
+ (cl-loop
+ for (cmd . fun) in evil-ex-commands unless (stringp fun)
+ collect cmd
+ ;; Append ! to all commands that may take a bang argument
+ when (evil-get-command-property fun :ex-bang)
+ collect (concat cmd "!")))
+ (emacs-cmds (lambda (str pred action)
+ (completion-table-with-predicate
+ obarray #'commandp t str pred action))))
+ (cond
+ ((null evil-ex-complete-emacs-commands) ex-cmds)
+ ((eq evil-ex-complete-emacs-commands 'in-turn)
+ (completion-table-in-turn ex-cmds emacs-cmds))
+ (t (cl-loop for s in-ref ex-cmds do
+ (setf s (propertize s 'face 'evil-ex-commands)))
+ (evil-completion-table-concat ex-cmds emacs-cmds)))))
+
+(defun evil-completion-table-concat (table1 table2)
+ (lambda (string pred action)
+ (cond
+ ((null action)
+ (let (matches)
+ (dolist (table (list table1 table2) (try-completion string matches))
+ (let ((x (try-completion string table pred)))
+ (when x (push (if (eq x 't) string x) matches))))))
+ ((eq action t)
+ (delete-dups
+ (append (all-completions string table1 pred)
+ (all-completions string table2 pred))))
+ ((eq action 'lambda)
+ (when (or (test-completion string table1 pred)
+ (test-completion string table2 pred))
+ t))
+ ((eq (car-safe action) 'boundaries)
+ (or (completion-boundaries string table1 pred (cdr action))
+ (completion-boundaries string table2 pred (cdr action))))
+ ((eq action 'metadata)
+ '(metadata (display-sort-function . evil-ex-sort-completions))))))
+
+(defun evil-ex-sort-completions (completions)
+ (sort completions
+ (lambda (str1 str2)
+ (let ((p1 (eq (get-text-property 0 'face str1) 'evil-ex-commands))
+ (p2 (eq (get-text-property 0 'face str2) 'evil-ex-commands)))
+ (if (eq p1 p2) (string< str1 str2) p1)))))
+
+(define-obsolete-function-alias 'evil-ex-completion #'completion-at-point "1.15.0")
+
+(define-obsolete-function-alias
+ 'evil-ex-command-completion-at-point #'evil-ex-completion-at-point "1.15.0")
+
+(defalias 'evil-ex-argument-completion-at-point #'ignore)
+(make-obsolete
+ 'evil-ex-argument-completion-at-point #'evil-ex-completion-at-point "1.15.0")
+
+(define-obsolete-function-alias
+ 'evil-ex-elisp-completion-at-point #'elisp-completion-at-point "1.15.0")
+
+(defun evil-ex-define-cmd (cmd function)
+ "Bind the function FUNCTION to the command CMD."
+ (if (not (string-match-p "\\[" cmd))
+ (evil--add-to-alist evil-ex-commands cmd function)
+ (string-match "\\(.*\\)\\[\\(.*\\)\\]" cmd)
+ (let ((mandatory (match-string 1 cmd))
+ (optional (match-string 2 cmd)))
+ (dotimes (n (1+ (length optional)))
+ (evil--add-to-alist evil-ex-commands
+ (concat mandatory (substring optional 0 n))
+ function)))))
+
+(defmacro evil-ex-define-argument-type (arg-type doc &rest body)
+ "Define a new handler for argument-type ARG-TYPE.
+DOC is the documentation string. It is followed by a list of keywords
+and function:
+
+:collection COLLECTION
+
+ A collection for completion as required by `all-completions'.
+
+:completion-at-point FUNC
+
+ Function to be called to initialize a potential completion. FUNC
+ must match the requirements as described for the variable
+ `completion-at-point-functions'. When FUNC is called the minibuffer
+ content is narrowed to exactly match the argument.
+
+:runner FUNC
+
+ Function to be called when the type of the current argument changes
+ or when the content of this argument changes. This function should
+ take one obligatory argument FLAG followed by an optional argument
+ ARG. FLAG is one of three symbol `start', `stop' or `update'. When
+ the argument type is recognized for the first time and this handler
+ is started the FLAG is `start'. If the argument type changes to
+ something else or ex state finished the handler FLAG is `stop'. If
+ the content of the argument has changed FLAG is `update'. If FLAG is
+ either `start' or `update' then ARG is the current value of this
+ argument. If FLAG is `stop' then arg is nil."
+ (declare (indent defun)
+ (doc-string 2)
+ (debug (&define name
+ [&optional stringp]
+ [&rest [keywordp function-form]])))
+ (unless (stringp doc) (push doc body))
+ (let (runner completer)
+ (while (keywordp (car body))
+ (let ((key (pop body))
+ (func (pop body)))
+ (cond
+ ((eq key :runner)
+ (setq runner `#',func))
+ ((eq key :collection)
+ (setq completer `(cons 'collection #',func)))
+ ((eq key :completion-at-point)
+ (setq completer `(cons 'completion-at-point #',func))))))
+ `(evil--add-to-alist evil-ex-argument-types
+ ',arg-type (list ,runner ,completer))))
+
+(evil-ex-define-argument-type file
+ "Handle a file argument."
+ :collection read-file-name-internal)
+
+(evil-ex-define-argument-type buffer
+ "Called to complete a buffer name argument."
+ :collection internal-complete-buffer)
+
+(declare-function comint-completion-at-point "comint")
+(declare-function shell-completion-vars "shell" ())
+
+(defvar-local evil--ex-shell-argument-initialized nil
+ "This variable is set to t if shell command completion has been initialized.
+See `evil-ex-init-shell-argument-completion'.")
+
+(defun evil-ex-init-shell-argument-completion (flag &optional _arg)
+ "Prepare the current minibuffer for completion of shell commands.
+This function must be called from the :runner function of some
+argument handler that requires shell completion."
+ (when (and (eq flag 'start)
+ (not evil--ex-shell-argument-initialized))
+ (setq evil--ex-shell-argument-initialized t)
+ (require 'shell)
+ ;; Set up Comint for Shell mode, except
+ ;; `comint-completion-at-point' will be called manually.
+ (shell-completion-vars)
+ (remove-hook 'completion-at-point-functions #'comint-completion-at-point t)))
+
+(evil-ex-define-argument-type shell
+ "Shell argument type, supports completion."
+ :completion-at-point comint-completion-at-point
+ :runner evil-ex-init-shell-argument-completion)
+
+(defun evil-ex-file-or-shell-command-completion-at-point ()
+ (if (eq (char-after (point-min)) ?!)
+ (save-restriction
+ (narrow-to-region (1+ (point-min)) (point-max))
+ (comint-completion-at-point))
+ (list (point-min) (point-max) #'read-file-name-internal)))
+
+(evil-ex-define-argument-type file-or-shell
+ "File or shell argument type.
+If the current argument starts with a ! the rest of the argument
+is considered a shell command, otherwise a file-name. Completion
+works accordingly."
+ :completion-at-point evil-ex-file-or-shell-command-completion-at-point
+ :runner evil-ex-init-shell-argument-completion)
+
+(defun evil-ex-binding (command &optional noerror)
+ "Return the final binding of COMMAND."
+ (let ((binding (if (evil--ex-bang-p command) (substring command 0 -1)
+ command)))
+ (while (stringp
+ (setq binding (cdr (assoc binding evil-ex-commands)))))
+ (unless binding (setq binding (intern-soft command)))
+ (if (commandp binding)
+ (or (command-remapping binding) binding)
+ (unless noerror (user-error "Unknown command: `%s'" command)))))
+
+(defun evil-ex-completed-binding (command &optional noerror)
+ "Return the final binding of the completion of COMMAND."
+ (let ((completion (try-completion command evil-ex-commands)))
+ (evil-ex-binding (if (eq completion t) command
+ (or completion command))
+ noerror)))
+
+;; TODO: extensions like :p :~ <cfile> ...
+(defun evil-ex-replace-special-filenames (file-name)
+ "Replace special symbols in FILE-NAME.
+Replaces % by the current file-name,
+Replaces # by the alternate file-name in FILE-NAME."
+ (let ((remote (file-remote-p file-name))
+ (current-fname (buffer-file-name))
+ (alternate-fname (and (other-buffer)
+ (buffer-file-name (other-buffer)))))
+ (setq file-name (or (file-remote-p file-name 'localname) file-name))
+ (when current-fname
+ (setq current-fname (or (file-remote-p current-fname 'localname)
+ current-fname))
+ (setq file-name
+ (replace-regexp-in-string "\\(^\\|[^\\\\]\\)\\(%\\)"
+ current-fname file-name
+ t t 2)))
+ (when alternate-fname
+ (setq alternate-fname (or (file-remote-p alternate-fname 'localname)
+ alternate-fname))
+ (setq file-name
+ (replace-regexp-in-string "\\(^\\|[^\\\\]\\)\\(#\\)"
+ alternate-fname file-name
+ t t 2)))
+ (setq file-name
+ (replace-regexp-in-string "\\\\\\([#%]\\)"
+ "\\1" file-name t))
+ (setq file-name (concat remote file-name)))
+ file-name)
+
+(defun evil-ex-file-arg ()
+ "Return the current Ex argument as a file name.
+This function interprets special file names like # and %."
+ (unless (zerop (length evil-ex-argument))
+ (evil-ex-replace-special-filenames evil-ex-argument)))
+
+(define-error 'evil-ex-no-previous-cmd "No previous command line")
+
+(defun evil-ex-repeat (&optional count)
+ "Repeat the last Ex command."
+ (interactive "P")
+ (when count
+ (goto-char (point-min))
+ (forward-line (1- count)))
+ (cl-loop
+ with evil-ex-original-buffer = (current-buffer)
+ for last-cmd in evil-ex-history do
+ (condition-case nil
+ (cl-return (let (evil-ex-history) (evil-ex-execute last-cmd)))
+ (evil-ex-no-previous-cmd))
+ finally (signal 'evil-ex-no-previous-cmd nil)))
+
+(defun evil-ex-call-command (range command argument)
+ "Execute the given command COMMAND."
+ (when evil-ex-reverse-range
+ (setq evil-ex-reverse-range nil)
+ (unless (y-or-n-p "Backward range given, OK to swap? ")
+ (user-error "")))
+ (let* ((count (when (integerp range) range))
+ (current-prefix-arg count)
+ (evil-ex-range (if count (evil-ex-range count count) range))
+ (cmd (evil-ex-completed-binding command))
+ (evil-ex-bang (evil--ex-bang-p command))
+ (evil-ex-argument argument)
+ (evil-this-type (evil-type evil-ex-range))
+ (evil-ex-point (point))
+ (restore-point
+ (and evil-ex-range
+ (evil-get-command-property cmd :restore-point)
+ (if (evil-visual-state-p) evil-visual-beginning evil-ex-point)))
+ (evil-called-from-ex-p t))
+ (evil-exit-visual-state)
+ (deactivate-mark)
+ (when evil-ex-range
+ ;; Set region if an explicit range has been specified
+ (cl-destructuring-bind (beg end &rest) (evil-expand-range evil-ex-range t)
+ (goto-char beg)
+ (set-marker (mark-marker) end)))
+ (setq this-command cmd)
+ (let ((mark-active evil-ex-range))
+ (run-hooks 'pre-command-hook)
+ (call-interactively cmd))
+ (run-hooks 'post-command-hook)
+ (when restore-point (goto-char restore-point))))
+
+(defun evil-ex-line (base &optional offset)
+ "Return the line number of BASE plus OFFSET."
+ (+ (or base (line-number-at-pos))
+ (or offset 0)))
+
+(defun evil-ex-first-line ()
+ "Return the line number of the first line."
+ (line-number-at-pos (point-min)))
+
+(defun evil-ex-current-line ()
+ "Return the line number of the current line."
+ (line-number-at-pos))
+
+(defun evil-ex-last-line ()
+ "Return the line number of the last line."
+ (save-excursion
+ (goto-char (point-max))
+ (when (bolp)
+ (forward-line -1))
+ (line-number-at-pos)))
+
+(defun evil-ex-range (beg-line &optional end-line)
+ "Return the first and last position of the current range."
+ (let* ((beg (if beg-line (evil-line-position beg-line)
+ (line-beginning-position)))
+ (end (if end-line (evil-line-position (1+ end-line))
+ (save-excursion (goto-char beg) (line-beginning-position 2)))))
+ (when (< end beg)
+ (setq evil-ex-reverse-range t)
+ (evil-swap beg end))
+ (evil-range beg end 'line :expanded t)))
+
+(defun evil-ex-full-range ()
+ "Return a range encompassing the whole buffer."
+ (evil-range (point-min) (point-max) 'line :expanded t))
+
+(defun evil-ex-last-visual-range ()
+ "Return a linewise range of the last visual selection."
+ (evil-range evil-visual-mark evil-visual-point 'line))
+
+(defun evil-ex-marker (marker)
+ "Return MARKER's line number in the current buffer.
+Signal an error if MARKER is in a different buffer."
+ (setq marker (evil-get-marker
+ (if (stringp marker) (aref marker 0) marker)))
+ (if (numberp marker)
+ (line-number-at-pos marker)
+ (user-error "Ex does not support markers in other files")))
+
+(defun evil-ex-char-marker-range (beg end)
+ (setq beg (evil-get-marker (if (stringp beg) (aref beg 0) beg))
+ end (evil-get-marker (if (stringp end) (aref end 0) end)))
+ (unless (and (numberp beg) (numberp end))
+ (user-error "Ex does not support markers in other files"))
+ (evil-expand-range
+ (evil-range beg end
+ (if (evil-visual-state-p)
+ (evil-visual-type)
+ 'inclusive))))
+
+(declare-function evil-ex-make-search-pattern "evil-search")
+
+(defun evil-ex-re-fwd (pattern)
+ "Search forward for PATTERN.
+Return the line number of the match."
+ (when evil-ex-search-vim-style-regexp
+ (setq pattern (evil-transform-vim-style-regexp pattern)))
+ (set-text-properties 0 (length pattern) nil pattern)
+ (setq evil-ex-search-pattern (evil-ex-make-search-pattern pattern)
+ evil-ex-search-direction 'forward)
+ (condition-case err
+ (save-excursion
+ (evil-move-beginning-of-line 2)
+ (when (or (re-search-forward pattern nil t)
+ (progn
+ (goto-char (point-min))
+ (re-search-forward pattern nil t)))
+ (line-number-at-pos (match-beginning 0))))
+ (invalid-regexp
+ (evil-ex-echo (cadr err))
+ nil)))
+
+(defun evil-ex-re-bwd (pattern)
+ "Search backward for PATTERN.
+Return the line number of the match."
+ (when evil-ex-search-vim-style-regexp
+ (setq pattern (evil-transform-vim-style-regexp pattern)))
+ (set-text-properties 0 (length pattern) nil pattern)
+ (setq evil-ex-search-pattern (evil-ex-make-search-pattern pattern)
+ evil-ex-search-direction 'backward)
+ (condition-case err
+ (save-excursion
+ (evil-move-beginning-of-line)
+ (when (or (re-search-backward pattern nil t)
+ (progn
+ (goto-char (point-max))
+ (re-search-backward pattern nil t)))
+ (line-number-at-pos (match-beginning 0))))
+ (invalid-regexp
+ (evil-ex-echo (cadr err))
+ nil)))
+
+(defun evil-ex-prev-search ()
+ (error "Previous search not yet implemented"))
+
+(defun evil-ex-signed-number (sign &optional number)
+ "Return a signed number like -3 and +1.
+NUMBER defaults to 1."
+ (funcall sign (or number 1)))
+
+(defun evil-ex-command-force-p (command)
+ "Whether COMMAND accepts the bang argument."
+ (declare (obsolete evil-get-command-property "1.15.0"))
+ (let ((binding (evil-ex-completed-binding command t)))
+ (when binding
+ (evil-get-command-property binding :ex-bang))))
+
+(cl-defun evil--ex-syntactic-context
+ (&optional (pos (point))
+ (tree (save-excursion (goto-char (minibuffer-prompt-end))
+ (evil-ex-parse nil t)))
+ &aux i result)
+ "Return the syntactical context in TREE of the character at POS.
+POS defaults to the current position of point."
+ ;; Iterate over syntax tree leaves (i.e. the strings), and return
+ ;; the path to the leaf containing the cursor. Or, if not found,
+ ;; e.g. because of trailing whitespace, the leaf at most one char
+ ;; past the rightmost non-empty string.
+ (cl-labels
+ ((traverse
+ (node path)
+ (while (and (consp node) (symbolp (car node)))
+ (push (cons (pop node) i) path))
+ (if (listp node)
+ (dolist (child node) (traverse child path))
+ ;; NODE is the end position of a parsed string
+ (when (>= node pos) (cl-return-from evil--ex-syntactic-context path))
+ (when (or (null result) (> node i))
+ (setq i node
+ result path)))))
+ (traverse tree ()))
+ result)
+
+(provide 'evil-ex)
+
+;;; evil-ex.el ends here
diff --git a/.config/emacs/lisp/evil/evil-integration.el b/.config/emacs/lisp/evil/evil-integration.el
new file mode 100644
index 0000000..710d69d
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-integration.el
@@ -0,0 +1,468 @@
+;;; evil-integration.el --- Integrate Evil with other modules -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This provides evil integration for various emacs modes.
+;; Additional keybindings (or default state) should go into evil-keybindings.el.
+
+;;; Code:
+
+(require 'evil-maps)
+(require 'evil-core)
+(require 'evil-macros)
+(require 'evil-types)
+(require 'evil-repeat)
+
+;;; Evilize some commands
+
+;; unbound keys should be ignored
+(evil-declare-ignore-repeat 'undefined)
+
+(mapc #'(lambda (cmd)
+ (evil-set-command-property cmd :keep-visual t)
+ (evil-declare-not-repeat cmd))
+ '(digit-argument
+ negative-argument
+ universal-argument
+ universal-argument-minus
+ universal-argument-more
+ universal-argument-other-key))
+(mapc #'evil-declare-not-repeat
+ '(what-cursor-position))
+(mapc #'evil-declare-change-repeat
+ '(dabbrev-expand
+ hippie-expand
+ quoted-insert))
+(mapc #'evil-declare-abort-repeat
+ '(balance-windows
+ eval-expression
+ execute-extended-command
+ exit-minibuffer
+ compile
+ delete-window
+ delete-other-windows
+ find-file-at-point
+ ffap-other-window
+ recompile
+ redo
+ save-buffer
+ split-window
+ split-window-horizontally
+ split-window-vertically
+ undo
+ undo-tree-redo
+ undo-tree-undo))
+
+(evil-set-type #'previous-line 'line)
+(evil-set-type #'next-line 'line)
+
+(dolist (cmd '(keyboard-quit keyboard-escape-quit))
+ (evil-set-command-property cmd :suppress-operator t))
+
+;;; Mouse
+(evil-declare-insert-at-point-repeat 'mouse-yank-primary)
+(evil-declare-insert-at-point-repeat 'mouse-yank-secondary)
+
+;;; key-binding
+
+;; Calling `keyboard-quit' should cancel repeat
+(advice-add 'keyboard-quit :before #'evil-repeat-abort)
+
+(add-hook 'wdired-mode-hook #'evil-change-to-initial-state)
+(advice-add 'wdired-change-to-dired-mode :after
+ #'evil--change-to-initial-state-with-msg)
+(defun evil--change-to-initial-state-with-msg (&rest _)
+ (evil-change-to-initial-state nil t))
+
+;;; Parentheses
+
+(evil--advice-add 'show-paren-function :around #'evil--match-paren-in-normal-state)
+(defun evil--match-paren-in-normal-state (orig-fun &rest args)
+ "Match parentheses in Normal state."
+ (if (eq (not (memq 'not evil-highlight-closing-paren-at-point-states))
+ (not (memq evil-state evil-highlight-closing-paren-at-point-states)))
+ (apply orig-fun args)
+ (let* ((orig-spdf show-paren-data-function)
+ (show-paren-data-function
+ (lambda ()
+ (let ((pos (point)) narrow)
+ (setq
+ pos (cl-dotimes (i (1+ (* 2 evil-show-paren-range)))
+ (setq pos (+ pos (if (cl-evenp i) i (- i))))
+ (pcase (syntax-class (syntax-after pos))
+ (4 (setq narrow pos) (cl-return pos))
+ (5 (cl-return (1+ pos))))))
+ (when pos
+ (save-excursion
+ (goto-char pos)
+ (save-restriction
+ (when narrow (narrow-to-region narrow (point-max)))
+ (funcall orig-spdf))))))))
+ (apply orig-fun args))))
+
+;;; Undo tree
+(eval-after-load 'undo-tree
+ '(with-no-warnings
+ (evil-ex-define-cmd "undol[ist]" 'undo-tree-visualize)
+ (evil-ex-define-cmd "ul" 'undo-tree-visualize)
+
+ (define-key undo-tree-visualizer-mode-map
+ [remap evil-backward-char] 'undo-tree-visualize-switch-branch-left)
+ (define-key undo-tree-visualizer-mode-map
+ [remap evil-forward-char] 'undo-tree-visualize-switch-branch-right)
+ (define-key undo-tree-visualizer-mode-map
+ [remap evil-next-line] 'undo-tree-visualize-redo)
+ (define-key undo-tree-visualizer-mode-map
+ [remap evil-previous-line] 'undo-tree-visualize-undo)
+ (define-key undo-tree-visualizer-mode-map
+ [remap evil-ret] 'undo-tree-visualizer-set)
+
+ (define-key undo-tree-visualizer-selection-mode-map
+ [remap evil-backward-char] 'undo-tree-visualizer-select-left)
+ (define-key undo-tree-visualizer-selection-mode-map
+ [remap evil-forward-char] 'undo-tree-visualizer-select-right)
+ (define-key undo-tree-visualizer-selection-mode-map
+ [remap evil-next-line] 'undo-tree-visualizer-select-next)
+ (define-key undo-tree-visualizer-selection-mode-map
+ [remap evil-previous-line] 'undo-tree-visualizer-select-previous)
+ (define-key undo-tree-visualizer-selection-mode-map
+ [remap evil-ret] 'undo-tree-visualizer-set)))
+
+;;; Auto-complete
+(eval-after-load 'auto-complete
+ '(progn
+ (evil-add-command-properties 'auto-complete :repeat 'evil-ac-repeat)
+ (evil-add-command-properties 'ac-complete :repeat 'evil-ac-repeat)
+ (evil-add-command-properties 'ac-expand :repeat 'evil-ac-repeat)
+ (evil-add-command-properties 'ac-next :repeat 'ignore)
+ (evil-add-command-properties 'ac-previous :repeat 'ignore)
+
+ (defvar evil-ac-prefix-len nil
+ "The length of the prefix of the current item to be completed.")
+
+ (defvar ac-prefix)
+ (defun evil-ac-repeat (flag)
+ "Record the changes for auto-completion."
+ (cond
+ ((eq flag 'pre)
+ (setq evil-ac-prefix-len (length ac-prefix))
+ (evil-repeat-start-record-changes))
+ ((eq flag 'post)
+ ;; Add change to remove the prefix
+ (evil-repeat-record-change (- evil-ac-prefix-len)
+ ""
+ evil-ac-prefix-len)
+ ;; Add change to insert the full completed text
+ (evil-repeat-record-change
+ (- evil-ac-prefix-len)
+ (buffer-substring-no-properties (- evil-repeat-pos
+ evil-ac-prefix-len)
+ (point))
+ 0)
+ ;; Finish repeation
+ (evil-repeat-finish-record-changes))))))
+
+;;; Company
+(eval-after-load 'company
+ '(progn
+ (mapc #'evil-declare-change-repeat
+ '(company-complete-mouse
+ company-complete-number
+ company-complete-selection
+ company-complete-common))
+
+ (mapc #'evil-declare-ignore-repeat
+ '(company-abort
+ company-select-next
+ company-select-previous
+ company-select-next-or-abort
+ company-select-previous-or-abort
+ company-select-mouse
+ company-show-doc-buffer
+ company-show-location
+ company-search-candidates
+ company-filter-candidates))))
+
+;;; Eval last sexp
+(defun evil--preceding-sexp (command &rest args)
+ "In Normal- or Motion-state, allow last sexp to end at point."
+ (save-excursion
+ (or evil-move-beyond-eol
+ (eolp)
+ (not (or (evil-normal-state-p) (evil-motion-state-p)))
+ (forward-char))
+ (apply command args)))
+(advice-add 'elisp--preceding-sexp :around #'evil--preceding-sexp)
+(advice-add 'pp-last-sexp :around #'evil--preceding-sexp)
+(advice-add 'lisp-eval-last-sexp :around #'evil--preceding-sexp)
+
+;;; Show key
+(advice-add 'quail-show-key :around #'evil--in-emacs-state)
+(advice-add 'describe-char :around #'evil--in-emacs-state)
+(defun evil--in-emacs-state (orig-fun &rest args)
+ "Temporarily enter Emacs-state and apply ORIG-FUN to ARGS."
+ (evil-with-state emacs (apply orig-fun args)))
+
+;;; ace-jump-mode
+(declare-function ace-jump-char-mode "ext:ace-jump-mode")
+(declare-function ace-jump-word-mode "ext:ace-jump-mode")
+(declare-function ace-jump-line-mode "ext:ace-jump-mode")
+(defvar ace-jump-mode-scope)
+
+(defvar evil-ace-jump-active nil)
+
+(defmacro evil-enclose-ace-jump-for-motion (&rest body)
+ "Enclose ace-jump to make it suitable for motions.
+This includes restricting `ace-jump-mode' to the current window
+in visual and operator state, deactivating visual updates, saving
+the mark and entering `recursive-edit'."
+ (declare (indent defun)
+ (debug t))
+ `(let ((old-mark (mark))
+ (ace-jump-mode-scope
+ (if (and (not (memq evil-state '(visual operator)))
+ (boundp 'ace-jump-mode-scope))
+ ace-jump-mode-scope
+ 'window)))
+ (remove-hook 'pre-command-hook #'evil-visual-pre-command t)
+ (remove-hook 'post-command-hook #'evil-visual-post-command t)
+ (unwind-protect
+ (let ((evil-ace-jump-active 'prepare))
+ (add-hook 'ace-jump-mode-end-hook
+ #'evil-ace-jump-exit-recursive-edit)
+ ,@body
+ (when evil-ace-jump-active
+ (setq evil-ace-jump-active t)
+ (recursive-edit)))
+ (remove-hook 'post-command-hook
+ #'evil-ace-jump-exit-recursive-edit)
+ (remove-hook 'ace-jump-mode-end-hook
+ #'evil-ace-jump-exit-recursive-edit)
+ (if (evil-visual-state-p)
+ (progn
+ (add-hook 'pre-command-hook #'evil-visual-pre-command nil t)
+ (add-hook 'post-command-hook #'evil-visual-post-command nil t)
+ (set-mark old-mark))
+ (push-mark old-mark)))))
+
+(advice-add 'ace-jump-done :after #'evil--after-ace-jump-done)
+(defun evil--after-ace-jump-done (&rest _)
+ (when evil-ace-jump-active
+ (add-hook 'post-command-hook #'evil-ace-jump-exit-recursive-edit)))
+
+(defun evil-ace-jump-exit-recursive-edit ()
+ "Exit a recursive edit caused by an evil jump."
+ (cond
+ ((eq evil-ace-jump-active 'prepare)
+ (setq evil-ace-jump-active nil))
+ (evil-ace-jump-active
+ (remove-hook 'post-command-hook #'evil-ace-jump-exit-recursive-edit)
+ (exit-recursive-edit))))
+
+(evil-define-motion evil-ace-jump-char-mode (_count)
+ "Jump visually directly to a char using ace-jump."
+ :type inclusive
+ (evil-without-repeat
+ (let ((pnt (point))
+ (buf (current-buffer)))
+ (evil-enclose-ace-jump-for-motion
+ (call-interactively 'ace-jump-char-mode))
+ ;; if we jump backwards, motion type is exclusive, analogously
+ ;; to `evil-find-char-backward'
+ (when (and (equal buf (current-buffer))
+ (< (point) pnt))
+ (setq evil-this-type
+ (cond
+ ((eq evil-this-type 'exclusive) 'inclusive)
+ ((eq evil-this-type 'inclusive) 'exclusive)))))))
+
+(evil-define-motion evil-ace-jump-char-to-mode (_count)
+ "Jump visually to the char in front of a char using ace-jump."
+ :type inclusive
+ (evil-without-repeat
+ (let ((pnt (point))
+ (buf (current-buffer)))
+ (evil-enclose-ace-jump-for-motion
+ (call-interactively 'ace-jump-char-mode))
+ (if (and (equal buf (current-buffer))
+ (< (point) pnt))
+ (progn
+ (or (eobp) (forward-char))
+ (setq evil-this-type
+ (cond
+ ((eq evil-this-type 'exclusive) 'inclusive)
+ ((eq evil-this-type 'inclusive) 'exclusive))))
+ (backward-char)))))
+
+(evil-define-motion evil-ace-jump-line-mode (_count)
+ "Jump visually to the beginning of a line using ace-jump."
+ :type line
+ :repeat abort
+ (evil-without-repeat
+ (evil-enclose-ace-jump-for-motion
+ (call-interactively 'ace-jump-line-mode))))
+
+(evil-define-motion evil-ace-jump-word-mode (_count)
+ "Jump visually to the beginning of a word using ace-jump."
+ :type exclusive
+ :repeat abort
+ (evil-without-repeat
+ (evil-enclose-ace-jump-for-motion
+ (call-interactively 'ace-jump-word-mode))))
+
+(define-key evil-motion-state-map [remap ace-jump-char-mode] #'evil-ace-jump-char-mode)
+(define-key evil-motion-state-map [remap ace-jump-line-mode] #'evil-ace-jump-line-mode)
+(define-key evil-motion-state-map [remap ace-jump-word-mode] #'evil-ace-jump-word-mode)
+
+;;; avy
+(declare-function avy-goto-word-or-subword-1 "ext:avy")
+(declare-function avy-goto-line "ext:avy")
+(declare-function avy-goto-char "ext:avy")
+(declare-function avy-goto-char-2 "ext:avy")
+(declare-function avy-goto-char-2-above "ext:avy")
+(declare-function avy-goto-char-2-below "ext:avy")
+(declare-function avy-goto-char-in-line "ext:avy")
+(declare-function avy-goto-word-0 "ext:avy")
+(declare-function avy-goto-word-1 "ext:avy")
+(declare-function avy-goto-word-1-above "ext:avy")
+(declare-function avy-goto-word-1-below "ext:avy")
+(declare-function avy-goto-subword-0 "ext:avy")
+(declare-function avy-goto-subword-1 "ext:avy")
+(declare-function avy-goto-char-timer "ext:avy")
+(defvar avy-all-windows)
+
+(defmacro evil-enclose-avy-for-motion (&rest body)
+ "Enclose avy to make it suitable for motions.
+Based on `evil-enclose-ace-jump-for-motion'."
+ (declare (indent defun)
+ (debug t))
+ `(let ((avy-all-windows
+ (if (and (not (memq evil-state '(visual operator)))
+ (boundp 'avy-all-windows))
+ avy-all-windows
+ nil)))
+ ,@body))
+
+(defmacro evil-define-avy-motion (command type)
+ (declare (indent defun)
+ (debug t))
+ (let ((name (intern (format "evil-%s" command))))
+ `(evil-define-motion ,name (_count)
+ ,(format "Evil motion for `%s'." command)
+ :type ,type
+ :jump t
+ :repeat abort
+ (evil-without-repeat
+ (evil-enclose-avy-for-motion
+ (call-interactively ',command))))))
+
+;; define evil-avy-* motion commands for avy-* commands
+(evil-define-avy-motion avy-goto-char inclusive)
+(evil-define-avy-motion avy-goto-char-2 inclusive)
+(evil-define-avy-motion avy-goto-char-2-above inclusive)
+(evil-define-avy-motion avy-goto-char-2-below inclusive)
+(evil-define-avy-motion avy-goto-char-in-line inclusive)
+(evil-define-avy-motion avy-goto-char-timer inclusive)
+(evil-define-avy-motion avy-goto-line line)
+(evil-define-avy-motion avy-goto-line-above line)
+(evil-define-avy-motion avy-goto-line-below line)
+(evil-define-avy-motion avy-goto-subword-0 exclusive)
+(evil-define-avy-motion avy-goto-subword-1 exclusive)
+(evil-define-avy-motion avy-goto-symbol-1 exclusive)
+(evil-define-avy-motion avy-goto-symbol-1-above exclusive)
+(evil-define-avy-motion avy-goto-symbol-1-below exclusive)
+(evil-define-avy-motion avy-goto-word-0 exclusive)
+(evil-define-avy-motion avy-goto-word-1 exclusive)
+(evil-define-avy-motion avy-goto-word-1-above exclusive)
+(evil-define-avy-motion avy-goto-word-1-below exclusive)
+(evil-define-avy-motion avy-goto-word-or-subword-1 exclusive)
+
+;; remap avy-* commands to evil-avy-* commands
+(dolist (command '(avy-goto-char
+ avy-goto-char-2
+ avy-goto-char-2-above
+ avy-goto-char-2-below
+ avy-goto-char-in-line
+ avy-goto-char-timer
+ avy-goto-line
+ avy-goto-line-above
+ avy-goto-line-below
+ avy-goto-subword-0
+ avy-goto-subword-1
+ avy-goto-symbol-1
+ avy-goto-symbol-1-above
+ avy-goto-symbol-1-below
+ avy-goto-word-0
+ avy-goto-word-1
+ avy-goto-word-1-above
+ avy-goto-word-1-below
+ avy-goto-word-or-subword-1))
+ (define-key evil-motion-state-map
+ (vector 'remap command) (intern-soft (format "evil-%s" command))))
+
+;;; nXhtml/mumamo
+;; ensure that mumamo does not toggle evil through its globalized mode
+(eval-after-load 'mumamo
+ '(with-no-warnings
+ (push 'evil-mode-cmhh mumamo-change-major-mode-no-nos)))
+
+;; visual-line-mode integration
+(when evil-respect-visual-line-mode
+ (evil-define-minor-mode-key 'motion 'visual-line-mode
+ "j" 'evil-next-visual-line
+ "gj" 'evil-next-line
+ "k" 'evil-previous-visual-line
+ "gk" 'evil-previous-line
+ "0" 'evil-beginning-of-visual-line
+ "g0" 'evil-beginning-of-line
+ "$" 'evil-end-of-visual-line
+ "g$" 'evil-end-of-line
+ "V" 'evil-visual-screen-line))
+
+;;; abbrev.el
+(defun evil-maybe-expand-abbrev ()
+ (when (and abbrev-mode evil-want-abbrev-expand-on-insert-exit)
+ (expand-abbrev)))
+
+(eval-after-load 'abbrev
+ '(add-hook 'evil-insert-state-exit-hook #'evil-maybe-expand-abbrev))
+
+;;; ElDoc
+(eval-after-load 'eldoc
+ '(when (fboundp 'eldoc-add-command-completions)
+ (eldoc-add-command-completions "evil-window-")))
+
+;;; XRef
+(eval-after-load 'xref
+ '(progn
+ (evil-set-command-property 'xref-find-definitions :jump t)
+ (evil-set-command-property 'xref-find-references :jump t)))
+
+(provide 'evil-integration)
+
+;;; evil-integration.el ends here
diff --git a/.config/emacs/lisp/evil/evil-jumps.el b/.config/emacs/lisp/evil/evil-jumps.el
new file mode 100644
index 0000000..a5ad8ba
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-jumps.el
@@ -0,0 +1,358 @@
+;;; evil-jumps.el --- Jump list implementation -*- lexical-binding: t -*-
+
+;; Author: Bailey Ling <bling at live.ca>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+(require 'cl-lib)
+(require 'evil-core)
+(require 'evil-states)
+
+;;; Code:
+
+(defgroup evil-jumps nil
+ "Evil jump list configuration options."
+ :prefix "evil-jumps"
+ :group 'evil)
+
+(defcustom evil-jumps-cross-buffers t
+ "When non-nil, the jump commands can cross borders between buffers.
+Otherwise the jump commands act only within the current buffer."
+ :type 'boolean)
+
+(defcustom evil-jumps-max-length 100
+ "The maximum number of jumps to keep track of."
+ :type 'integer)
+
+(defcustom evil-jumps-pre-jump-hook nil
+ "Hooks to run just before jumping to a location in the jump list."
+ :type 'hook)
+
+(defcustom evil-jumps-post-jump-hook nil
+ "Hooks to run just after jumping to a location in the jump list."
+ :type 'hook)
+
+(defcustom evil-jumps-ignored-file-patterns '("COMMIT_EDITMSG$" "TAGS$")
+ "List of regexps to exclude file path from inclusion in the jump list."
+ :type '(repeat string))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar savehist-additional-variables)
+
+(defvar evil--jumps-jumping nil)
+
+(defvar evil--jumps-jump-command nil
+ "Set by `evil--jump-backward', used and cleared in the
+`post-command-hook' by `evil--jump-handle-buffer-crossing'")
+
+(eval-when-compile (defvar evil--jumps-debug nil))
+
+(defvar evil--jumps-buffer-targets "\\*\\(new\\|scratch\\)\\*"
+ "Regexp to determine if buffer with `buffer-name' is a valid jump target.")
+
+(defvar evil--jumps-window-jumps (make-hash-table)
+ "Hashtable which stores all jumps on a per window basis.")
+
+(defvar evil-jumps-history nil
+ "History of `evil-mode' jumps that are persisted with `savehist'.")
+
+(cl-defstruct evil-jumps-struct
+ ring
+ (idx -1)
+ previous-pos)
+
+;; Is inlining this really worth it?
+(defsubst evil--jumps-message (format &rest args)
+ (when (eval-when-compile evil--jumps-debug)
+ (with-current-buffer (get-buffer-create "*evil-jumps*")
+ (goto-char (point-max))
+ (insert (apply #'format format args) "\n"))))
+
+(defun evil--jumps-get-current (&optional window)
+ (unless window (setq window (selected-window)))
+ (let ((jump-struct (gethash window evil--jumps-window-jumps)))
+ (unless jump-struct
+ (setq jump-struct (make-evil-jumps-struct))
+ (puthash window jump-struct evil--jumps-window-jumps))
+ jump-struct))
+
+(defun evil--jumps-get-jumps (struct)
+ (let ((ring (evil-jumps-struct-ring struct)))
+ (unless ring
+ (setq ring (make-ring evil-jumps-max-length))
+ (setf (evil-jumps-struct-ring struct) ring))
+ ring))
+
+(defun evil--jumps-get-window-jump-list ()
+ (let ((struct (evil--jumps-get-current)))
+ (evil--jumps-get-jumps struct)))
+
+(defun evil--jumps-savehist-load ()
+ (add-to-list 'savehist-additional-variables 'evil-jumps-history)
+ (let ((ring (make-ring evil-jumps-max-length)))
+ (cl-loop for jump in (reverse evil-jumps-history)
+ do (ring-insert ring jump))
+ (setf (evil-jumps-struct-ring (evil--jumps-get-current)) ring))
+ (add-hook 'savehist-save-hook #'evil--jumps-savehist-sync)
+ (remove-hook 'savehist-mode-hook #'evil--jumps-savehist-load))
+
+(defun evil--jumps-savehist-sync ()
+ "Update the printable value of window jumps for `savehist'."
+ (setq evil-jumps-history
+ (delq nil (mapcar #'(lambda (jump)
+ (let* ((mark (car jump))
+ (pos (if (markerp mark)
+ (marker-position mark)
+ mark))
+ (file-name (cadr jump)))
+ (when (and (not (file-remote-p file-name))
+ (file-exists-p file-name)
+ pos)
+ (list pos file-name))))
+ (ring-elements (evil--jumps-get-window-jump-list))))))
+
+(defun evil--jumps-current-file-name ()
+ "Get the current buffer file name for `evil--jumps-push'."
+ (or buffer-file-name
+ (when (derived-mode-p 'dired-mode) default-directory)))
+
+(defun evil--jumps-jump (idx shift)
+ (let ((target-list (evil--jumps-get-window-jump-list)))
+ (evil--jumps-message "jumping from %s by %s" idx shift)
+ (evil--jumps-message "target list = %s" target-list)
+ (setq idx (+ idx shift))
+ (let ((current-file-name (or (evil--jumps-current-file-name) (buffer-name)))
+ (size (ring-length target-list)))
+ (unless evil-jumps-cross-buffers
+ ;; skip jump marks pointing to other buffers
+ (while (and (< idx size) (>= idx 0)
+ (not (string= current-file-name (cadr (ring-ref target-list idx)))))
+ (setq idx (+ idx shift))))
+ (when (and (< idx size) (>= idx 0))
+ ;; actual jump
+ (run-hooks 'evil-jumps-pre-jump-hook)
+ (let* ((place (ring-ref target-list idx))
+ (pos (car place))
+ (file-name (cadr place)))
+ (setq evil--jumps-jumping t)
+ (unless (string= current-file-name file-name)
+ (if (string-match-p evil--jumps-buffer-targets file-name)
+ (switch-to-buffer file-name)
+ (find-file file-name)))
+ (setq evil--jumps-jumping nil)
+ (goto-char pos)
+ (setf (evil-jumps-struct-idx (evil--jumps-get-current)) idx)
+ (run-hooks 'evil-jumps-post-jump-hook))))))
+
+(defun evil--jumps-push ()
+ "Push the current cursor/file position to the jump list."
+ (let ((target-list (evil--jumps-get-window-jump-list))
+ (file-name (evil--jumps-current-file-name))
+ (buffer-name (buffer-name))
+ (current-pos (point-marker))
+ (first-pos nil)
+ (first-file-name nil)
+ (excluded nil))
+ (when (and (not file-name)
+ (string-match-p evil--jumps-buffer-targets buffer-name))
+ (setq file-name buffer-name))
+ (when file-name
+ (dolist (pattern evil-jumps-ignored-file-patterns)
+ (when (string-match-p pattern file-name)
+ (setq excluded t)))
+ (unless excluded
+ (unless (ring-empty-p target-list)
+ (setq first-pos (car (ring-ref target-list 0)))
+ (setq first-file-name (car (cdr (ring-ref target-list 0)))))
+ (unless (and (equal first-pos current-pos)
+ (equal first-file-name file-name))
+ (evil--jumps-message "pushing %s on %s" current-pos file-name)
+ (ring-insert target-list `(,current-pos ,file-name)))))
+ (evil--jumps-message "%s %s"
+ (selected-window)
+ (and (not (ring-empty-p target-list))
+ (ring-ref target-list 0)))))
+
+(evil-define-command evil-show-jumps ()
+ "Display the contents of the jump list."
+ :repeat nil
+ (evil-with-view-list
+ :name "evil-jumps"
+ :mode "Evil Jump List"
+ :format [("Jump" 5 nil)
+ ("Marker" 8 nil)
+ ("File/text" 1000 t)]
+ :entries (let* ((jumps (evil--jumps-savehist-sync))
+ (count 0))
+ (cl-loop for jump in jumps
+ collect `(nil [,(number-to-string (cl-incf count))
+ ,(number-to-string (car jump))
+ (,(cadr jump))])))
+ :select-action #'evil--show-jumps-select-action))
+
+(defun evil--show-jumps-select-action (jump)
+ (let ((position (string-to-number (elt jump 1)))
+ (file (car (elt jump 2))))
+ (kill-buffer)
+ (switch-to-buffer (find-file file))
+ (goto-char position)))
+
+(defun evil-set-jump (&optional pos)
+ "Set jump point at POS.
+POS defaults to point."
+ (save-excursion
+ (when (markerp pos)
+ (set-buffer (marker-buffer pos)))
+
+ (unless (or (region-active-p) (evil-visual-state-p))
+ (push-mark pos t))
+
+ (unless evil--jumps-jumping
+ ;; clear out intermediary jumps when a new one is set
+ (let* ((struct (evil--jumps-get-current))
+ (target-list (evil--jumps-get-jumps struct))
+ (idx (evil-jumps-struct-idx struct)))
+ (cl-loop repeat idx
+ do (ring-remove target-list))
+ (setf (evil-jumps-struct-idx struct) -1))
+ (when pos
+ (goto-char pos))
+ (evil--jumps-push))))
+(put 'evil-set-jump 'permanent-local-hook t)
+
+(defun evil--jump-backward (count)
+ (setq evil--jumps-jump-command t)
+ (let ((count (or count 1)))
+ (evil-motion-loop (nil count)
+ (let* ((struct (evil--jumps-get-current))
+ (idx (evil-jumps-struct-idx struct)))
+ (evil--jumps-message "jumping back %s" idx)
+ (when (= idx -1)
+ (setq idx 0)
+ (setf (evil-jumps-struct-idx struct) 0)
+ (evil--jumps-push))
+ (evil--jumps-jump idx 1)))))
+
+(defun evil--jump-forward (count)
+ (setq evil--jumps-jump-command t)
+ (let ((count (or count 1)))
+ (evil-motion-loop (nil count)
+ (let* ((struct (evil--jumps-get-current))
+ (idx (evil-jumps-struct-idx struct)))
+ (when (= idx -1)
+ (setq idx 0)
+ (setf (evil-jumps-struct-idx struct) 0)
+ (evil--jumps-push))
+ (evil--jumps-jump idx -1)))))
+
+(defun evil--jumps-window-configuration-hook (&rest _args)
+ (let* ((window-list (window-list-1 nil nil t))
+ (existing-window (selected-window))
+ (new-window (previous-window)))
+ (when (and (not (eq existing-window new-window))
+ (> (length window-list) 1))
+ (let* ((target-jump-struct (evil--jumps-get-current new-window)))
+ (if (not (ring-empty-p (evil--jumps-get-jumps target-jump-struct)))
+ (evil--jumps-message "target window %s already has %s jumps" new-window
+ (ring-length (evil--jumps-get-jumps target-jump-struct)))
+ (evil--jumps-message "new target window detected; copying %s to %s" existing-window new-window)
+ (let* ((source-jump-struct (evil--jumps-get-current existing-window))
+ (source-list (evil--jumps-get-jumps source-jump-struct)))
+ (when (= (ring-length (evil--jumps-get-jumps target-jump-struct)) 0)
+ (setf (evil-jumps-struct-previous-pos target-jump-struct) (evil-jumps-struct-previous-pos source-jump-struct))
+ (setf (evil-jumps-struct-idx target-jump-struct) (evil-jumps-struct-idx source-jump-struct))
+ (setf (evil-jumps-struct-ring target-jump-struct) (ring-copy source-list)))))))
+ ;; delete obsolete windows
+ (maphash (lambda (key _val)
+ (unless (member key window-list)
+ (evil--jumps-message "removing %s" key)
+ (remhash key evil--jumps-window-jumps)))
+ evil--jumps-window-jumps)))
+(put 'evil--jumps-window-configuration-hook 'permanent-local-hook t)
+
+(defun evil--jump-hook (&optional command)
+ "`pre-command-hook' for evil-jumps.
+Set jump point if COMMAND has a non-nil `:jump' property. Otherwise,
+save the current position in case the command being executed will
+change the current buffer."
+ (setq command (or command this-command))
+ (if (evil-get-command-property command :jump)
+ (evil-set-jump)
+ (setf (evil-jumps-struct-previous-pos (evil--jumps-get-current))
+ (point-marker))))
+(put 'evil--jump-hook 'permanent-local-hook t)
+
+(defun evil--jump-handle-buffer-crossing ()
+ (let ((jump-command evil--jumps-jump-command))
+ (setq evil--jumps-jump-command nil)
+ (dolist (frame (frame-list))
+ (dolist (window (window-list frame))
+ (let* ((struct (evil--jumps-get-current window))
+ (previous-pos (evil-jumps-struct-previous-pos struct)))
+ (when previous-pos
+ (setf (evil-jumps-struct-previous-pos struct) nil)
+ (if (and
+ ;; `evil-jump-backward' and 'evil-jump-forward' need
+ ;; to be handled specially. When jumping backward
+ ;; multiple times, calling `evil-set-jump' is always
+ ;; wrong: If you jump back twice and we call
+ ;; `evil-set-jump' after the second time, we clear
+ ;; the forward jump list and `evil--jump-forward'
+ ;; won't work.
+
+ ;; The first time you jump backward, setting a jump
+ ;; point is sometimes correct. But we don't do it
+ ;; here because this function is called after
+ ;; `evil--jump-backward' has updated our position in
+ ;; the jump list so, again, `evil-set-jump' would
+ ;; break `evil--jump-forward'.
+ (not jump-command)
+ (let ((previous-buffer (marker-buffer previous-pos)))
+ (and previous-buffer
+ (not (eq previous-buffer (window-buffer window))))))
+ (evil-set-jump previous-pos)
+ (set-marker previous-pos nil))))))))
+(put 'evil--jump-handle-buffer-crossing 'permanent-local-hook t)
+
+(if (bound-and-true-p savehist-loaded)
+ (evil--jumps-savehist-load)
+ (add-hook 'savehist-mode-hook #'evil--jumps-savehist-load))
+
+(defun evil--jumps-install-or-uninstall ()
+ (if evil-local-mode
+ (progn
+ (add-hook 'pre-command-hook #'evil--jump-hook nil t)
+ (add-hook 'post-command-hook #'evil--jump-handle-buffer-crossing nil t)
+ (add-hook 'next-error-hook #'evil-set-jump nil t)
+ (add-hook 'window-configuration-change-hook #'evil--jumps-window-configuration-hook nil t))
+ (remove-hook 'pre-command-hook #'evil--jump-hook t)
+ (remove-hook 'post-command-hook #'evil--jump-handle-buffer-crossing t)
+ (remove-hook 'next-error-hook #'evil-set-jump t)
+ (remove-hook 'window-configuration-change-hook #'evil--jumps-window-configuration-hook t)))
+
+(add-hook 'evil-local-mode-hook #'evil--jumps-install-or-uninstall)
+
+(provide 'evil-jumps)
+
+;;; evil-jumps.el ends here
diff --git a/.config/emacs/lisp/evil/evil-keybindings.el b/.config/emacs/lisp/evil/evil-keybindings.el
new file mode 100644
index 0000000..81a8b00
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-keybindings.el
@@ -0,0 +1,124 @@
+;;; evil-keybindings.el --- Add some Evil keybindings to other modules -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This provides a set of keybindings for other emacs modes. This also includes
+;; setting up the initial evil state of those other modes.
+
+;;; Code:
+
+(require 'evil-maps)
+(require 'evil-core)
+(require 'evil-macros)
+(require 'evil-types)
+(require 'evil-repeat)
+
+;; etags-select
+;; FIXME: probably etags-select should be recomended in docs
+(eval-after-load 'etags-select
+ '(progn
+ (define-key evil-motion-state-map "g]" 'etags-select-find-tag-at-point)))
+
+;;; Buffer-menu
+
+(evil-add-hjkl-bindings Buffer-menu-mode-map 'motion)
+
+;; dictionary.el
+
+(evil-add-hjkl-bindings dictionary-mode-map 'motion
+ "?" 'dictionary-help ; "h"
+ "C-o" 'dictionary-previous) ; "l"
+
+;;; Dired
+
+(eval-after-load 'dired
+ '(progn
+ ;; use the standard Dired bindings as a base
+ (defvar dired-mode-map)
+ (evil-make-overriding-map dired-mode-map 'normal)
+ (evil-add-hjkl-bindings dired-mode-map 'normal
+ "J" 'dired-goto-file ; "j"
+ "K" 'dired-do-kill-lines ; "k"
+ "r" 'dired-do-redisplay ; "l"
+ ;; ":d", ":v", ":s", ":e"
+ ";" (lookup-key dired-mode-map ":"))))
+
+;;; ERT
+
+(evil-add-hjkl-bindings ert-results-mode-map 'motion)
+
+;;; Info
+
+(evil-add-hjkl-bindings Info-mode-map 'motion
+ "0" 'evil-beginning-of-line
+ (kbd "\M-h") 'Info-help ; "h"
+ "\C-t" 'Info-history-back ; "l"
+ "\C-o" 'Info-history-back
+ " " 'Info-scroll-up
+ "\C-]" 'Info-follow-nearest-node
+ (kbd "DEL") 'Info-scroll-down)
+
+;;; Speedbar
+
+(evil-add-hjkl-bindings speedbar-mode-map 'motion
+ "h" 'backward-char
+ "j" 'speedbar-next
+ "k" 'speedbar-prev
+ "l" 'forward-char
+ "i" 'speedbar-item-info
+ "r" 'speedbar-refresh
+ "u" 'speedbar-up-directory
+ "o" 'speedbar-toggle-line-expansion
+ (kbd "RET") 'speedbar-edit-line)
+
+;; Ibuffer
+(eval-after-load 'ibuffer
+ '(progn
+ (defvar ibuffer-mode-map)
+ (evil-make-overriding-map ibuffer-mode-map 'normal)
+ (evil-define-key 'normal ibuffer-mode-map
+ "j" 'evil-next-line
+ "k" 'evil-previous-line
+ (kbd "RET") 'ibuffer-visit-buffer)))
+
+;;; ag.el
+(eval-after-load 'ag
+ '(progn
+ (defvar ag-mode-map)
+ (add-to-list 'evil-motion-state-modes 'ag-mode)
+ (evil-add-hjkl-bindings ag-mode-map 'motion)))
+
+;;; ELP
+
+(advice-add 'elp-results :after #'evil--set-motion-state)
+(defun evil--set-motion-state (&rest _)
+ (evil-motion-state))
+
+(provide 'evil-keybindings)
+
+;;; evil-keybindings.el ends here
diff --git a/.config/emacs/lisp/evil/evil-macros.el b/.config/emacs/lisp/evil/evil-macros.el
new file mode 100644
index 0000000..0f7fd59
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-macros.el
@@ -0,0 +1,772 @@
+;;; evil-macros.el --- Macros -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'evil-common)
+(require 'evil-states)
+(require 'evil-repeat)
+
+(declare-function evil-ex-p "evil-ex")
+(declare-function evil-line-or-visual-line "evil-commands")
+
+;; set some error codes
+(put 'beginning-of-line 'error-conditions '(beginning-of-line error))
+(put 'beginning-of-line 'error-message "Beginning of line")
+(put 'end-of-line 'error-conditions '(end-of-line error))
+(put 'end-of-line 'error-message "End of line")
+;; we don't want line boundaries to trigger the debugger
+;; when `debug-on-error' is t
+(cl-pushnew 'beginning-of-line debug-ignored-errors)
+(cl-pushnew 'end-of-line debug-ignored-errors)
+
+(defun evil-motion-range (motion &optional count type)
+ "Execute a motion and return the buffer positions.
+The return value is a list (BEG END TYPE)."
+ (let ((opoint (point))
+ (omark (mark t))
+ (obuffer (current-buffer))
+ (evil-motion-marker (move-marker (make-marker) (point)))
+ range)
+ (evil-with-transient-mark-mode
+ (evil-narrow-to-field
+ (unwind-protect
+ (let ((current-prefix-arg count)
+ ;; Store type in global variable `evil-this-type'.
+ ;; If necessary, motions can change their type
+ ;; during execution by setting this variable.
+ (evil-this-type
+ (or type (evil-get-command-property motion :type 'exclusive))))
+ (condition-case err
+ (let ((repeat-type (evil--repeat-type motion)))
+ (when (functionp repeat-type) (funcall repeat-type 'pre))
+ (unless (with-local-quit
+ (setq range (call-interactively motion))
+ t)
+ (evil-repeat-abort)
+ (setq quit-flag t))
+ (when (functionp repeat-type) (funcall repeat-type 'post)))
+ (error
+ (evil-repeat-abort)
+ ;; some operators depend on succeeding motions, in
+ ;; particular for `evil-forward-char' (e.g., used by
+ ;; `evil-substitute'), therefore we let end-of-line
+ ;; and end-of-buffer pass
+ (if (memq (car err) '(end-of-line end-of-buffer))
+ (message (error-message-string err))
+ (signal (car err) (cdr err)))))
+ (cond
+ ;; the motion returned a range
+ ((evil-range-p range))
+ ;; the motion made a Visual selection
+ ((evil-visual-state-p)
+ (setq range (evil-visual-range)))
+ ;; the motion made an active region
+ ((region-active-p)
+ (setq range (evil-range (region-beginning) (region-end)
+ evil-this-type)))
+ ;; default: range from previous position to current
+ (t (setq range (evil-expand-range
+ (evil-normalize evil-motion-marker
+ (point)
+ evil-this-type)))))
+ (unless (or (null type) (eq (evil-type range) type))
+ (evil-set-type range type)
+ (evil-expand-range range))
+ (evil-set-range-properties range nil)
+ range)
+ ;; restore point and mark like `save-excursion',
+ ;; but only if the motion hasn't disabled the operator
+ (unless evil-inhibit-operator
+ (set-buffer obuffer)
+ (evil-move-mark omark)
+ (goto-char opoint))
+ ;; delete marker so it doesn't slow down editing
+ (move-marker evil-motion-marker nil))))))
+
+(defmacro evil-define-motion (motion args &rest body)
+ "Define a motion command MOTION.
+ARGS is a list of arguments. Motions can have any number of
+arguments, but the first (if any) has the predefined meaning of
+count. BODY must execute the motion by moving point.
+
+Optional keyword arguments are:
+- `:type' - determines how the motion works after an operator (one of
+ `inclusive', `line', `block' and `exclusive', or a self-defined
+ motion type)
+- `:jump' - if non-nil, the previous position is stored in the jump
+ list, so that it can be restored with \
+\\<evil-motion-state-map>\\[evil-jump-backward]
+
+\(fn MOTION (COUNT ARGS...) DOC [[KEY VALUE]...] BODY...)"
+ (declare (indent defun)
+ (doc-string 3)
+ (debug (&define name lambda-list
+ [&optional stringp]
+ [&rest keywordp sexp]
+ [&optional ("interactive" [&rest form])]
+ def-body)))
+ (let (arg doc interactive key keys)
+ (when args
+ (setq args `(&optional ,@(delq '&optional args))
+ ;; the count is either numerical or nil
+ interactive '("<c>")))
+ ;; collect docstring
+ (when (and (> (length body) 1)
+ (or (eq (car-safe (car body)) #'format)
+ (stringp (car body))))
+ (setq doc (pop body)))
+ ;; collect keywords
+ (setq keys (plist-put keys :repeat 'motion))
+ (while (keywordp (car body))
+ (setq key (pop body)
+ arg (pop body)
+ keys (plist-put keys key arg)))
+ ;; collect `interactive' specification
+ (when (eq (car-safe (car body)) 'interactive)
+ (setq interactive (cdr (pop body))))
+ ;; macro expansion
+ `(progn
+ ;; refresh echo area in Eldoc mode
+ (when ',motion
+ (eval-after-load 'eldoc
+ '(and (fboundp 'eldoc-add-command)
+ (eldoc-add-command ',motion))))
+ (evil-define-command ,motion (,@args)
+ ,@(when doc `(,doc)) ; avoid nil before `interactive'
+ ,@keys
+ :keep-visual t
+ (interactive ,@interactive)
+ ,@body))))
+
+(defmacro evil-narrow-to-line (&rest body)
+ "Narrow BODY to the current line.
+BODY will signal `beginning-of-line' or `end-of-line' upon reaching
+the beginning or end of the current line."
+ (declare (indent defun) (debug t))
+ `(cl-destructuring-bind (beg end &rest) (evil-line-expand (point) (point))
+ (when (save-excursion (goto-char end) (bolp))
+ (setq end (max beg (1- end))))
+ ;; Do not include the newline in Normal state
+ (or evil-move-beyond-eol
+ (evil-visual-state-p) (evil-operator-state-p)
+ (setq end (max beg (1- end))))
+ (evil-with-restriction beg end
+ (condition-case err
+ (progn ,@body)
+ (beginning-of-buffer
+ (signal (if (= (point-min) beg) 'beginning-of-line (car err))
+ (cdr err)))
+ (end-of-buffer
+ (signal (if (= (point-max) end) 'end-of-line (car err))
+ (cdr err)))))))
+
+(defun evil-eobp (&optional pos)
+ "Whether point is at end-of-buffer with regard to end-of-line."
+ (save-excursion
+ (when pos (goto-char pos))
+ (cond
+ ((eobp))
+ ;; the rest only pertains to Normal state
+ ((not (evil-normal-state-p)) nil)
+ ;; at the end of the last line
+ ((eolp)
+ (forward-char)
+ (eobp))
+ ;; at the last character of the last line
+ (t
+ (forward-char)
+ (cond
+ ((eobp))
+ ((eolp)
+ (forward-char)
+ (eobp)))))))
+
+(defun evil-move-beginning (count forward &optional backward)
+ "Move to the beginning of the COUNT next object.
+If COUNT is negative, move to the COUNT previous object.
+FORWARD is a function which moves to the end of the object, and
+BACKWARD is a function which moves to the beginning.
+If one is unspecified, the other is used with a negative argument."
+ (let* ((count (or count 1))
+ (backward (or backward
+ #'(lambda (count)
+ (funcall forward (- count)))))
+ (forward (or forward
+ #'(lambda (count)
+ (funcall backward (- count)))))
+ (opoint (point)))
+ (cond
+ ((< count 0)
+ (when (bobp)
+ (signal 'beginning-of-buffer nil))
+ (unwind-protect
+ (evil-motion-loop (nil count count)
+ (funcall backward 1))
+ (unless (zerop count)
+ (goto-char (point-min)))))
+ ((> count 0)
+ (when (evil-eobp)
+ (signal 'end-of-buffer nil))
+ ;; Do we need to move past the current object?
+ (when (<= (save-excursion
+ (funcall forward 1)
+ (funcall backward 1)
+ (point))
+ opoint)
+ (setq count (1+ count)))
+ (unwind-protect
+ (evil-motion-loop (nil count count)
+ (funcall forward 1))
+ (if (zerop count)
+ ;; go back to beginning of object
+ (funcall backward 1)
+ (goto-char (point-max)))))
+ (t count))))
+
+(defun evil-move-end (count forward &optional backward inclusive)
+ "Move to the end of the COUNT next object.
+If COUNT is negative, move to the COUNT previous object.
+FORWARD is a function which moves to the end of the object, and
+BACKWARD is a function which moves to the beginning.
+If one is unspecified, the other is used with a negative argument.
+If INCLUSIVE is non-nil, then point is placed at the last character
+of the object; otherwise it is placed at the end of the object."
+ (let* ((count (or count 1))
+ (backward (or backward
+ #'(lambda (count)
+ (funcall forward (- count)))))
+ (forward (or forward
+ #'(lambda (count)
+ (funcall backward (- count)))))
+ (opoint (point)))
+ (cond
+ ((< count 0)
+ (when (bobp)
+ (signal 'beginning-of-buffer nil))
+ ;; Do we need to move past the current object?
+ (when (>= (save-excursion
+ (funcall backward 1)
+ (funcall forward 1)
+ (point))
+ (if inclusive
+ (1+ opoint)
+ opoint))
+ (setq count (1- count)))
+ (unwind-protect
+ (evil-motion-loop (nil count count)
+ (funcall backward 1))
+ (if (not (zerop count))
+ (goto-char (point-min))
+ ;; go to end of object
+ (funcall forward 1)
+ (when inclusive
+ (unless (bobp) (backward-char)))
+ (when (or (evil-normal-state-p)
+ (evil-motion-state-p))
+ (evil-adjust-cursor)))))
+ ((> count 0)
+ (when (evil-eobp)
+ (signal 'end-of-buffer nil))
+ (when inclusive
+ (forward-char))
+ (unwind-protect
+ (evil-motion-loop (nil count count)
+ (funcall forward 1))
+ (if (not (zerop count))
+ (goto-char (point-max))
+ (when inclusive
+ (unless (bobp) (backward-char)))
+ (when (or (evil-normal-state-p)
+ (evil-motion-state-p))
+ (evil-adjust-cursor)))))
+ (t count))))
+
+(defun evil-text-object-make-linewise (range)
+ "Turn the text object selection RANGE to linewise.
+The selection is adjusted in a sensible way so that the selected
+lines match the user intent. In particular, whitespace-only parts
+at the first and last lines are omitted. This function returns
+the new range."
+ ;; Bug #607
+ ;; If new type is linewise and the selection of the
+ ;; first line consists of whitespace only, the
+ ;; beginning is moved to the start of the next line. If
+ ;; the selections of the last line consists of
+ ;; whitespace only, the end is moved to the end of the
+ ;; previous line.
+ (if (eq (evil-type range) 'line)
+ range
+ (let ((expanded (plist-get (evil-range-properties range) :expanded))
+ (newrange (evil-expand-range range t)))
+ (save-excursion
+ ;; skip whitespace at the beginning
+ (goto-char (evil-range-beginning newrange))
+ (skip-chars-forward " \t")
+ (when (and (not (bolp)) (eolp))
+ (evil-set-range-beginning newrange (1+ (point))))
+ ;; skip whitepsace at the end
+ (goto-char (evil-range-end newrange))
+ (skip-chars-backward " \t")
+ (when (and (not (eolp)) (bolp))
+ (evil-set-range-end newrange (1- (point))))
+ ;; only modify range if result is not empty
+ (if (> (evil-range-beginning newrange)
+ (evil-range-end newrange))
+ range
+ (unless expanded
+ (evil-contract-range newrange))
+ newrange)))))
+
+(defmacro evil-define-text-object (object args &rest body)
+ "Define a text object command OBJECT.
+BODY should return a range (BEG END) to the right of point
+if COUNT is positive, and to the left of it if negative.
+
+Optional keyword arguments:
+- `:type' - determines how the range applies after an operator
+ (`inclusive', `line', `block', and `exclusive', or a self-defined
+ motion type).
+- `:extend-selection' - if non-nil (default), the text object always
+ enlarges the current selection. Otherwise, it replaces the current
+ selection.
+
+\(fn OBJECT (COUNT) DOC [[KEY VALUE]...] BODY...)"
+ (declare (indent defun)
+ (doc-string 3)
+ (debug (&define name lambda-list
+ [&optional stringp]
+ [&rest keywordp sexp]
+ def-body)))
+ (let* ((args (delq '&optional args))
+ (count (or (pop args) 'count))
+ (args (when args `(&optional ,@args)))
+ (interactive '(interactive "<c><v>"))
+ doc keys)
+ ;; collect docstring
+ (when (stringp (car body))
+ (setq doc (pop body)))
+ ;; collect keywords
+ (setq keys (plist-put keys :extend-selection t))
+ (while (keywordp (car body))
+ (setq keys (plist-put keys (pop body) (pop body))))
+ ;; interactive
+ (when (eq (car-safe (car body)) 'interactive)
+ (setq interactive (pop body)))
+ ;; macro expansion
+ `(evil-define-motion ,object (,count ,@args)
+ ,@(when doc `(,doc))
+ ,@keys
+ ,interactive
+ (setq ,count (or ,count 1))
+ (when (/= ,count 0)
+ ;; FIXME: These let-bindings shadow variables in args
+ (let ((type (evil-type ',object evil-visual-char))
+ (extend (and (evil-visual-state-p)
+ (evil-get-command-property
+ ',object :extend-selection
+ ',(plist-get keys :extend-selection))))
+ (dir evil-visual-direction)
+ mark point range selection)
+ (cond
+ ;; Visual state: extend the current selection
+ ((and (evil-visual-state-p)
+ (called-interactively-p 'any))
+ ;; if we are at the beginning of the Visual selection,
+ ;; go to the left (negative COUNT); if at the end,
+ ;; go to the right (positive COUNT)
+ (setq dir evil-visual-direction
+ ,count (* ,count dir))
+ (setq range (progn ,@body))
+ (when (evil-range-p range)
+ (setq range (evil-expand-range range))
+ (evil-set-type range (evil-type range type))
+ (setq range (evil-contract-range range))
+ ;; the beginning is mark and the end is point
+ ;; unless the selection goes the other way
+ (setq mark (evil-range-beginning range)
+ point (evil-range-end range)
+ type (evil-type
+ (if evil-text-object-change-visual-type
+ range
+ (evil-visual-range))))
+ (when (and (eq type 'line)
+ (not (eq type (evil-type range))))
+ (let ((newrange (evil-text-object-make-linewise range)))
+ (setq mark (evil-range-beginning newrange)
+ point (evil-range-end newrange))))
+ (when (< dir 0)
+ (evil-swap mark point))
+ ;; select the union
+ (evil-visual-make-selection mark point type)))
+ ;; not Visual state: return a pair of buffer positions
+ (t
+ (setq range (progn ,@body))
+ (unless (evil-range-p range)
+ (setq ,count (- ,count)
+ range (progn ,@body)))
+ (when (evil-range-p range)
+ (setq selection (evil-range (point) (point) type))
+ (if extend
+ (setq range (evil-range-union range selection))
+ (evil-set-type range (evil-type range type)))
+ ;; possibly convert to linewise
+ (when (eq evil-this-type-modified 'line)
+ (setq range (evil-text-object-make-linewise range)))
+ (evil-set-range-properties range nil)
+ range))))))))
+
+(defmacro evil-define-operator (operator args &rest body)
+ "Define an operator command OPERATOR.
+The operator acts on the range of characters BEG through
+END. BODY must execute the operator by potentially manipulating
+the buffer contents, or otherwise causing side effects to happen.
+
+Optional keyword arguments are:
+- `:type' - force the input range to be of a given type (`inclusive',
+ `line', `block', and `exclusive', or a self-defined motion type).
+- `:motion' - use a predetermined motion instead of waiting for one
+ from the keyboard. This does not affect the behavior in visual
+ state, where selection boundaries are always used.
+- `:repeat' - if non-nil (default), then \
+ \\<evil-normal-state-map>\\[evil-repeat] will repeat the
+ operator.
+- `:move-point' - if non-nil (default), the cursor will be moved to
+ the beginning of the range before the body executes
+- `:keep-visual' - if non-nil, the selection is not disabled when the
+ operator is executed in visual state. By default, visual state is
+ exited automatically.
+- `:restore-point' - if non-nil, point is restored when the
+ operator is executed from ex.
+
+\(fn OPERATOR (BEG END ARGS...) DOC [[KEY VALUE]...] BODY...)"
+ (declare (indent defun)
+ (doc-string 3)
+ (debug (&define name lambda-list
+ [&optional stringp]
+ [&rest keywordp sexp]
+ [&optional ("interactive" [&rest form])]
+ def-body)))
+ (let* ((args (delq '&optional args))
+ (interactive (if (> (length args) 2) '("<R>") '("<r>")))
+ (args (if (> (length args) 2)
+ `(,(nth 0 args) ,(nth 1 args)
+ &optional ,@(nthcdr 2 args))
+ args))
+ (end-marker (make-symbol "end-marker"))
+ arg doc key keys visual)
+ ;; collect docstring
+ (when (and (> (length body) 1)
+ (or (eq (car-safe (car-safe body)) 'format)
+ (stringp (car-safe body))))
+ (setq doc (pop body)))
+ ;; collect keywords
+ (setq keys (plist-put keys :move-point t))
+ (while (keywordp (car-safe body))
+ (setq key (pop body)
+ arg (pop body))
+ (cond
+ ((eq key :keep-visual)
+ (setq visual arg))
+ (t
+ (setq keys (plist-put keys key arg)))))
+ ;; collect `interactive' specification
+ (when (eq (car-safe (car-safe body)) 'interactive)
+ (setq interactive (cdr-safe (pop body))))
+ ;; transform extended interactive specs
+ (setq interactive (apply #'evil-interactive-form interactive))
+ (setq keys (evil-concat-plists keys (cdr-safe interactive))
+ interactive (car-safe interactive))
+ ;; macro expansion
+ `(evil-define-command ,operator ,args
+ ,@(when doc `(,doc))
+ ,@keys
+ :keep-visual t
+ :suppress-operator t
+ (interactive
+ (let* ((props (evil-command-properties ',operator))
+ (evil-operator-range-motion
+ (let ((p (plist-member props :motion)))
+ ;; :motion nil is equivalent to :motion undefined
+ (when p (or (cadr p) #'undefined))))
+ (evil-operator-range-type (plist-get props :type))
+ evil-operator-range-beginning evil-operator-range-end
+ evil-inhibit-operator)
+ (setq evil-inhibit-operator-value nil
+ evil-this-operator this-command
+ evil-operator-start-col (current-column))
+ (prog1 ,interactive
+ (setq evil-inhibit-operator-value evil-inhibit-operator)
+ (if ,visual
+ (when (evil-visual-state-p) (evil-visual-expand-region))
+ (setq deactivate-mark t))
+ (cond
+ ((evil-visual-state-p)
+ (evil-visual-rotate 'upper-left))
+ ((plist-get props :move-point)
+ (when evil-operator-range-beginning
+ (goto-char evil-operator-range-beginning)))))))
+ (unwind-protect
+ (let ((evil-inhibit-operator evil-inhibit-operator-value)
+ (,end-marker (make-marker)))
+ (set-marker ,end-marker ,(cadr args))
+ (unless (and evil-inhibit-operator
+ (called-interactively-p 'any))
+ ,@body)
+ (evil-set-marker ?\[ (or ,(car args) (point-max)))
+ (evil-set-marker ?\] (max (or ,(car args) (point-max))
+ (1- (or (marker-position ,end-marker) (point-max)))))
+ (set-marker ,end-marker nil))
+ (setq evil-inhibit-operator-value nil)))))
+
+;; this is used in the `interactive' specification of an operator command
+(defun evil-operator-range (&optional return-type)
+ "Read a motion from the keyboard and return its buffer positions.
+The return value is a list (BEG END), or (BEG END TYPE) if
+RETURN-TYPE is non-nil."
+ (let ((motion (or evil-operator-range-motion
+ (when evil-called-from-ex-p 'evil-line)))
+ (type evil-operator-range-type)
+ range count)
+ (setq evil-this-type-modified nil)
+ (cond
+ ;; Ex command
+ ((and evil-called-from-ex-p evil-ex-range)
+ (setq range evil-ex-range))
+ ;; Visual selection
+ ((and (not evil-called-from-ex-p) (evil-visual-state-p))
+ (setq range (evil-visual-range)))
+ ;; active region
+ ((and (not evil-called-from-ex-p) (region-active-p))
+ (setq range (evil-range (region-beginning) (region-end)
+ (or evil-this-type 'exclusive))))
+ ;; motion
+ (t
+ (evil-save-echo-area
+ (evil-save-state
+ (unless motion
+ ;; Make linewise operator shortcuts. E.g., "d" yields the
+ ;; shortcut "dd", and "g?" yields shortcuts "g??" and "g?g?".
+ (let ((keys (nth 2 (evil-extract-count (this-command-keys)))))
+ (evil-change-state 'operator)
+ (cl-loop for keys on (listify-key-sequence keys) do
+ (define-key evil-operator-shortcut-map
+ (vconcat keys) #'evil-line-or-visual-line)))
+ ;; read motion from keyboard
+ (let ((command (evil-read-motion motion)))
+ (setq motion (car command)
+ count (cadr command)
+ type (or type (nth 2 command)))))
+ (cond
+ ((eq motion #'undefined)
+ (setq range (list nil nil)
+ motion nil))
+ ((or (null motion) ; keyboard-quit
+ (evil-get-command-property motion :suppress-operator))
+ (evil-repeat-abort)
+ (setq quit-flag t
+ range (evil-range (point) (point)) ; zero-len range
+ motion nil))
+ (evil-repeat-count
+ (setq count evil-repeat-count
+ ;; only the first operator's count is overwritten
+ evil-repeat-count nil))
+ ((or count current-prefix-arg)
+ ;; multiply operator count and motion count together
+ (setq count
+ (* (prefix-numeric-value count)
+ (prefix-numeric-value current-prefix-arg)))))
+ (when motion
+ (let ((evil-state 'operator)
+ mark-active)
+ ;; calculate motion range
+ (setq range (evil-motion-range motion count type))))
+ ;; update global variables
+ (setq evil-this-motion motion
+ evil-this-motion-count count
+ type (evil-type range type)
+ evil-this-type type)))))
+ (unless (or (null type) (eq (evil-type range) type))
+ (evil-contract-range range)
+ (evil-set-range-type range type)
+ (evil-expand-range range))
+ (setq evil-operator-range-beginning (evil-range-beginning range)
+ evil-operator-range-end (evil-range-end range)
+ evil-operator-range-type (evil-type range))
+ (setcdr (cdr range)
+ (when return-type (list (evil-type range))))
+ range))
+
+(defmacro evil-define-type (type doc &rest body)
+ "Define type TYPE.
+DOC is a general description and shows up in all docstrings.
+
+Optional keyword arguments:
+- `:expand' - expansion function. This function should accept two
+ positions in the current buffer, BEG and END,and return a pair of
+ expanded buffer positions.
+- `:contract' - the opposite of `:expand'. Optional.
+- `:one-to-one' - non-nil if expansion is one-to-one. This means that
+ `:expand' followed by `:contract' always return the original range.
+- `:normalize' - normalization function. This function should accept
+ two unexpanded positions and adjust them before expansion. May be
+ used to deal with buffer boundaries.
+- `:string' - description function. Takes two buffer positions and
+ returns a human-readable string. For example \"2 lines\"
+
+If further keywords and functions are specified, they are assumed to
+be transformations on buffer positions, like `:expand' and `:contract'.
+
+\(fn TYPE DOC [[KEY FUNC]...])"
+ (declare (indent defun)
+ (doc-string 2)
+ (debug (&define name
+ [&optional stringp]
+ [&rest [keywordp function-form]])))
+ (let ((plist (list :one-to-one t)) ; standard values
+ args defun-forms func key name string sym val)
+ ;; keywords
+ (while (keywordp (car-safe body))
+ (setq key (pop body)
+ val (pop body))
+ (if (plist-member plist key) ; not a function
+ (setq plist (plist-put plist key val))
+ (setq func val
+ sym (intern (replace-regexp-in-string
+ "^:" "" (symbol-name key)))
+ name (intern (format "evil-%s-%s" type sym))
+ args (car (cdr-safe func))
+ string (cadr (cdr-safe func))
+ string (if (stringp string)
+ (format "%s\n\n" string) "")
+ plist (plist-put plist key `',name))
+ (push
+ (cond
+ ((eq key :string)
+ `(defun ,name (beg end &rest properties)
+ ,(format "Return size of %s from BEG to END \
+with PROPERTIES.\n\n%s%s" type string doc)
+ (let ((type ',type)
+ plist range)
+ (when (and beg end)
+ (evil-sort beg end)
+ (save-excursion
+ (unless (plist-get properties :expanded)
+ (setq range (apply #'evil-expand
+ beg end type properties)
+ beg (evil-range-beginning range)
+ end (evil-range-end range)
+ type (evil-type range type)
+ plist (evil-range-properties range))
+ (setq properties
+ (evil-concat-plists properties plist)))
+ (or (apply #',func beg end
+ (when ,(> (length args) 2)
+ properties))
+ ""))))))
+ (t
+ `(defun ,name (beg end &rest properties)
+ ,(format "Perform %s transformation on %s from BEG to END \
+with PROPERTIES.\n\n%s%s" sym type string doc)
+ (let ((type ',type)
+ plist range)
+ (when (and beg end)
+ (evil-sort beg end)
+ (save-excursion
+ (when (memq ,key '(:expand :contract))
+ (setq properties
+ (plist-put properties
+ :expanded ,(eq key :expand))))
+ (setq range (or (apply #',func beg end
+ (when ,(> (length args) 2)
+ properties))
+ (apply #'evil-range
+ beg end type properties))
+ beg (evil-range-beginning range)
+ end (evil-range-end range)
+ type (evil-type range type)
+ plist (evil-range-properties range))
+ (setq properties
+ (evil-concat-plists properties plist))
+ (apply #'evil-range beg end type properties)))))))
+ defun-forms)))
+ ;; :one-to-one requires both or neither of :expand and :contract
+ (when (plist-get plist :expand)
+ (setq plist (plist-put plist :one-to-one
+ (and (plist-get plist :contract)
+ (plist-get plist :one-to-one)))))
+ `(progn
+ (evil--add-to-alist evil-type-properties ',type (list ,@plist))
+ ,@defun-forms
+ ',type)))
+
+(defmacro evil-define-interactive-code (code &rest body)
+ "Define an interactive code.
+PROMPT, if given, is the remainder of the interactive string
+up to the next newline. Command properties may be specified
+via KEY-VALUE pairs. BODY should evaluate to a list of values.
+
+\(fn CODE (PROMPT) [[KEY VALUE]...] BODY...)"
+ (declare (indent defun))
+ (let* ((args (and (> (length body) 1) (listp (car body))
+ (pop body)))
+ (doc (when (stringp (car body)) (pop body)))
+ (properties
+ (cl-loop while (keywordp (car body))
+ collect (pop body) collect (pop body)))
+ (func (if args
+ `(lambda ,args
+ ,@(when doc `(,doc))
+ ,@body)
+ `',(macroexp-progn body))))
+ `(eval-and-compile
+ (evil--add-to-alist
+ evil-interactive-alist ,code (cons ,func ',properties))
+ ,code)))
+
+;;; Highlighting
+
+(when (fboundp 'font-lock-add-keywords)
+ (font-lock-add-keywords
+ 'emacs-lisp-mode
+ ;; Match all `evil-define-' forms except `evil-define-key'.
+ ;; (In the interests of speed, this expression is incomplete
+ ;; and does not match all three-letter words.)
+ '(("(\\(evil-\\(?:ex-\\)?define-\
+\\(?:[^ k][^ e][^ y]\\|[-[:word:]]\\{4,\\}\\)\\)\
+\\>[ \f\t\n\r\v]*\\(\\(?:\\sw\\|\\s_\\)+\\)?"
+ (1 'font-lock-keyword-face)
+ (2 'font-lock-function-name-face nil t))
+ ("(\\(evil-\\(?:delay\\|narrow\\|signal\\|save\\|with\\(?:out\\)?\\)\
+\\(?:-[-[:word:]]+\\)?\\)\\>\[ \f\t\n\r\v]+"
+ 1 'font-lock-keyword-face)
+ ("(\\(evil-\\(?:[-[:word:]]\\)*loop\\)\\>[ \f\t\n\r\v]+"
+ 1 'font-lock-keyword-face))))
+
+(provide 'evil-macros)
+
+;;; evil-macros.el ends here
diff --git a/.config/emacs/lisp/evil/evil-maps.el b/.config/emacs/lisp/evil/evil-maps.el
new file mode 100644
index 0000000..6778023
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-maps.el
@@ -0,0 +1,686 @@
+;;; evil-maps.el --- Default keymaps -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'evil-states)
+(require 'evil-ex)
+(require 'evil-commands)
+(require 'evil-command-window)
+(require 'evil-common)
+
+;;; Normal state
+
+(define-key evil-normal-state-map "a" 'evil-append)
+(define-key evil-normal-state-map "A" 'evil-append-line)
+(define-key evil-normal-state-map "c" 'evil-change)
+(define-key evil-normal-state-map "C" 'evil-change-line)
+(define-key evil-normal-state-map "d" 'evil-delete)
+(define-key evil-normal-state-map "D" 'evil-delete-line)
+(define-key evil-normal-state-map "i" 'evil-insert)
+(define-key evil-normal-state-map (kbd "<insert>") 'evil-insert)
+(define-key evil-normal-state-map (kbd "<insertchar>") 'evil-insert)
+(define-key evil-normal-state-map "I" 'evil-insert-line)
+(define-key evil-normal-state-map "J" 'evil-join)
+(define-key evil-normal-state-map "m" 'evil-set-marker)
+(define-key evil-normal-state-map "o" 'evil-open-below)
+(define-key evil-normal-state-map "O" 'evil-open-above)
+(define-key evil-normal-state-map "p" 'evil-paste-after)
+(define-key evil-normal-state-map "P" 'evil-paste-before)
+(define-key evil-normal-state-map "q" 'evil-record-macro)
+(define-key evil-normal-state-map "Q" 'evil-execute-last-recorded-macro)
+(define-key evil-normal-state-map "r" 'evil-replace)
+(define-key evil-normal-state-map "R" 'evil-enter-replace-state)
+(define-key evil-normal-state-map "s" 'evil-substitute)
+(define-key evil-normal-state-map "S" 'evil-change-whole-line)
+(define-key evil-normal-state-map "x" 'evil-delete-char)
+(define-key evil-normal-state-map "X" 'evil-delete-backward-char)
+(define-key evil-normal-state-map [deletechar] 'evil-delete-char)
+(define-key evil-normal-state-map "y" 'evil-yank)
+(define-key evil-normal-state-map "Y" 'evil-yank-line)
+(define-key evil-normal-state-map "&" 'evil-ex-repeat-substitute)
+(define-key evil-normal-state-map "g&" 'evil-ex-repeat-global-substitute)
+(define-key evil-normal-state-map "g8" 'what-cursor-position)
+(define-key evil-normal-state-map "ga" 'what-cursor-position)
+(define-key evil-normal-state-map "gi" 'evil-insert-resume)
+(define-key evil-normal-state-map "gI" 'evil-insert-0-line)
+(define-key evil-normal-state-map "gJ" 'evil-join-whitespace)
+(define-key evil-normal-state-map "gp" 'evil-paste-after-cursor-after)
+(define-key evil-normal-state-map "gP" 'evil-paste-before-cursor-after)
+(define-key evil-normal-state-map "gq" 'evil-fill-and-move)
+(define-key evil-normal-state-map "gw" 'evil-fill)
+(define-key evil-normal-state-map "gu" 'evil-downcase)
+(define-key evil-normal-state-map "gU" 'evil-upcase)
+(define-key evil-normal-state-map "gf" 'find-file-at-point)
+(define-key evil-normal-state-map "]f" 'find-file-at-point)
+(define-key evil-normal-state-map "[f" 'find-file-at-point)
+(define-key evil-normal-state-map "gF" 'evil-find-file-at-point-with-line)
+(define-key evil-normal-state-map "]F" 'evil-find-file-at-point-with-line)
+(define-key evil-normal-state-map "[F" 'evil-find-file-at-point-with-line)
+(define-key evil-normal-state-map "gx" 'browse-url-at-point)
+(define-key evil-normal-state-map "g?" 'evil-rot13)
+(define-key evil-normal-state-map "g~" 'evil-invert-case)
+(define-key evil-normal-state-map "zo" 'evil-open-fold)
+(define-key evil-normal-state-map "zO" 'evil-open-fold-rec)
+(define-key evil-normal-state-map "zc" 'evil-close-fold)
+(define-key evil-normal-state-map "za" 'evil-toggle-fold)
+(define-key evil-normal-state-map "zr" 'evil-open-folds)
+(define-key evil-normal-state-map "zm" 'evil-close-folds)
+(define-key evil-normal-state-map "z=" 'ispell-word)
+(define-key evil-normal-state-map "\C-n" 'evil-paste-pop-next)
+(define-key evil-normal-state-map "\C-p" 'evil-paste-pop)
+(define-key evil-normal-state-map "\C-t" 'pop-tag-mark)
+(define-key evil-normal-state-map (kbd "C-.") 'evil-repeat-pop)
+(define-key evil-normal-state-map (kbd "M-.") 'evil-repeat-pop-next)
+(define-key evil-normal-state-map "." 'evil-repeat)
+(define-key evil-normal-state-map "@" 'evil-execute-macro)
+(define-key evil-normal-state-map "\"" 'evil-use-register)
+(define-key evil-normal-state-map "~" 'evil-invert-char)
+(define-key evil-normal-state-map "=" 'evil-indent)
+(define-key evil-normal-state-map "<" 'evil-shift-left)
+(define-key evil-normal-state-map ">" 'evil-shift-right)
+(define-key evil-normal-state-map "ZZ" 'evil-save-modified-and-close)
+(define-key evil-normal-state-map "ZQ" 'evil-quit)
+(define-key evil-normal-state-map (kbd "DEL") 'evil-backward-char)
+(define-key evil-normal-state-map [escape] 'evil-force-normal-state)
+(define-key evil-normal-state-map [remap cua-paste-pop] 'evil-paste-pop)
+(define-key evil-normal-state-map [remap yank-pop] 'evil-paste-pop)
+
+;; go to last change
+(define-key evil-normal-state-map "g;" 'evil-goto-last-change)
+(define-key evil-normal-state-map "g," 'evil-goto-last-change-reverse)
+
+;; undo
+(define-key evil-normal-state-map "u" 'evil-undo)
+(define-key evil-normal-state-map "\C-r" 'evil-redo)
+
+;; window commands
+(define-prefix-command 'evil-window-map)
+(define-key evil-window-map "b" 'evil-window-bottom-right)
+(define-key evil-window-map "c" 'evil-window-delete)
+(define-key evil-window-map "f" 'ffap-other-window)
+(define-key evil-window-map "h" 'evil-window-left)
+(define-key evil-window-map "H" 'evil-window-move-far-left)
+(define-key evil-window-map "j" 'evil-window-down)
+(define-key evil-window-map "J" 'evil-window-move-very-bottom)
+(define-key evil-window-map "k" 'evil-window-up)
+(define-key evil-window-map "K" 'evil-window-move-very-top)
+(define-key evil-window-map "l" 'evil-window-right)
+(define-key evil-window-map "L" 'evil-window-move-far-right)
+(define-key evil-window-map "n" 'evil-window-new)
+(define-key evil-window-map "o" 'delete-other-windows)
+(define-key evil-window-map "p" 'evil-window-mru)
+(define-key evil-window-map "q" 'evil-quit)
+(define-key evil-window-map "r" 'evil-window-rotate-downwards)
+(define-key evil-window-map "R" 'evil-window-rotate-upwards)
+(define-key evil-window-map "s" 'evil-window-split)
+(define-key evil-window-map "S" 'evil-window-split)
+(define-key evil-window-map "t" 'evil-window-top-left)
+(when (featurep 'tab-bar)
+ (define-key evil-window-map "T" 'tab-window-detach))
+(define-key evil-window-map "v" 'evil-window-vsplit)
+(define-key evil-window-map "w" 'evil-window-next)
+(define-key evil-window-map "W" 'evil-window-prev)
+(define-key evil-window-map "x" 'evil-window-exchange)
+(define-key evil-window-map "+" 'evil-window-increase-height)
+(define-key evil-window-map "-" 'evil-window-decrease-height)
+(define-key evil-window-map ":" 'evil-ex)
+(define-key evil-window-map "_" 'evil-window-set-height)
+(define-key evil-window-map "<" 'evil-window-decrease-width)
+(define-key evil-window-map ">" 'evil-window-increase-width)
+(define-key evil-window-map "=" 'balance-windows)
+(define-key evil-window-map (kbd "C-=") 'balance-windows)
+(define-key evil-window-map "|" 'evil-window-set-width)
+(define-key evil-window-map [down] 'evil-window-down)
+(define-key evil-window-map [up] 'evil-window-up)
+(define-key evil-window-map [left] 'evil-window-left)
+(define-key evil-window-map [right] 'evil-window-right)
+(define-key evil-window-map "\C-b" 'evil-window-bottom-right)
+(define-key evil-window-map "\C-c" 'evil-window-delete)
+(define-key evil-window-map "\C-f" 'ffap-other-window)
+(define-key evil-window-map "\C-h" 'evil-window-left)
+(define-key evil-window-map (kbd "C-S-h") 'evil-window-move-far-left)
+(define-key evil-window-map "\C-j" 'evil-window-down)
+(define-key evil-window-map (kbd "C-S-j") 'evil-window-move-very-bottom)
+(define-key evil-window-map "\C-k" 'evil-window-up)
+(define-key evil-window-map (kbd "C-S-k") 'evil-window-move-very-top)
+(define-key evil-window-map "\C-l" 'evil-window-right)
+(define-key evil-window-map (kbd "C-S-l") 'evil-window-move-far-right)
+(define-key evil-window-map "\C-n" 'evil-window-new)
+(define-key evil-window-map "\C-o" 'delete-other-windows)
+(define-key evil-window-map "\C-p" 'evil-window-mru)
+(define-key evil-window-map "\C-q" 'evil-quit)
+(define-key evil-window-map "\C-r" 'evil-window-rotate-downwards)
+(define-key evil-window-map (kbd "C-S-r") 'evil-window-rotate-upwards)
+(define-key evil-window-map "\C-s" 'evil-window-split)
+(define-key evil-window-map (kbd "C-S-s") 'evil-window-split)
+(define-key evil-window-map "\C-t" 'evil-window-top-left)
+(define-key evil-window-map "\C-v" 'evil-window-vsplit)
+(define-key evil-window-map "\C-w" 'evil-window-next)
+(define-key evil-window-map (kbd "C-S-W") 'evil-window-prev)
+(define-key evil-window-map "\C-x" 'evil-window-exchange)
+(define-key evil-window-map "\C-_" 'evil-window-set-height)
+(define-key evil-window-map [C-down] 'evil-window-down)
+(define-key evil-window-map [C-up] 'evil-window-up)
+(define-key evil-window-map [C-left] 'evil-window-left)
+(define-key evil-window-map [C-right] 'evil-window-right)
+(define-key evil-window-map "0" 'evil-window-digit-argument)
+(define-key evil-window-map "1" 'evil-window-digit-argument)
+(define-key evil-window-map "2" 'evil-window-digit-argument)
+(define-key evil-window-map "3" 'evil-window-digit-argument)
+(define-key evil-window-map "4" 'evil-window-digit-argument)
+(define-key evil-window-map "5" 'evil-window-digit-argument)
+(define-key evil-window-map "6" 'evil-window-digit-argument)
+(define-key evil-window-map "7" 'evil-window-digit-argument)
+(define-key evil-window-map "8" 'evil-window-digit-argument)
+(define-key evil-window-map "9" 'evil-window-digit-argument)
+
+(when (featurep 'tab-bar)
+ (define-key evil-motion-state-map "gt" 'evil-tab-next)
+ (define-key evil-window-map "gt" 'evil-tab-next)
+ (define-key evil-motion-state-map "gT" 'tab-bar-switch-to-prev-tab)
+ (define-key evil-window-map "gT" 'tab-bar-switch-to-prev-tab))
+
+;;; Motion state
+
+;; "0" is a special command when called first
+(define-key evil-motion-state-map "0" 'evil-beginning-of-line)
+(define-key evil-motion-state-map "1" 'digit-argument)
+(define-key evil-motion-state-map "2" 'digit-argument)
+(define-key evil-motion-state-map "3" 'digit-argument)
+(define-key evil-motion-state-map "4" 'digit-argument)
+(define-key evil-motion-state-map "5" 'digit-argument)
+(define-key evil-motion-state-map "6" 'digit-argument)
+(define-key evil-motion-state-map "7" 'digit-argument)
+(define-key evil-motion-state-map "8" 'digit-argument)
+(define-key evil-motion-state-map "9" 'digit-argument)
+(define-key evil-motion-state-map "b" 'evil-backward-word-begin)
+(define-key evil-motion-state-map "B" 'evil-backward-WORD-begin)
+(define-key evil-motion-state-map "e" 'evil-forward-word-end)
+(define-key evil-motion-state-map "E" 'evil-forward-WORD-end)
+(define-key evil-motion-state-map "f" 'evil-find-char)
+(define-key evil-motion-state-map "F" 'evil-find-char-backward)
+(define-key evil-motion-state-map "G" 'evil-goto-line)
+(define-key evil-motion-state-map "h" 'evil-backward-char)
+(define-key evil-motion-state-map "H" 'evil-window-top)
+(define-key evil-motion-state-map "j" 'evil-next-line)
+(define-key evil-motion-state-map "k" 'evil-previous-line)
+(define-key evil-motion-state-map "l" 'evil-forward-char)
+(define-key evil-motion-state-map " " 'evil-forward-char)
+(define-key evil-motion-state-map "K" 'evil-lookup)
+(define-key evil-motion-state-map "L" 'evil-window-bottom)
+(define-key evil-motion-state-map "M" 'evil-window-middle)
+(define-key evil-motion-state-map "n" 'evil-search-next)
+(define-key evil-motion-state-map "N" 'evil-search-previous)
+(define-key evil-motion-state-map "t" 'evil-find-char-to)
+(define-key evil-motion-state-map "T" 'evil-find-char-to-backward)
+(define-key evil-motion-state-map "w" 'evil-forward-word-begin)
+(define-key evil-motion-state-map "W" 'evil-forward-WORD-begin)
+(define-key evil-motion-state-map "y" 'evil-yank)
+(define-key evil-motion-state-map "Y" 'evil-yank-line)
+(define-key evil-motion-state-map "gd" 'evil-goto-definition)
+(define-key evil-motion-state-map "ge" 'evil-backward-word-end)
+(define-key evil-motion-state-map "gE" 'evil-backward-WORD-end)
+(define-key evil-motion-state-map "gg" 'evil-goto-first-line)
+(define-key evil-motion-state-map "gj" 'evil-next-visual-line)
+(define-key evil-motion-state-map (vconcat "g" [down]) 'evil-next-visual-line)
+(define-key evil-motion-state-map "gk" 'evil-previous-visual-line)
+(define-key evil-motion-state-map (vconcat "g" [up]) 'evil-previous-visual-line)
+(define-key evil-motion-state-map "g0" 'evil-beginning-of-visual-line)
+(define-key evil-motion-state-map "g_" 'evil-last-non-blank)
+(define-key evil-motion-state-map "g^" 'evil-first-non-blank-of-visual-line)
+(define-key evil-motion-state-map (vconcat "g" [home]) 'evil-first-non-blank-of-visual-line)
+(define-key evil-motion-state-map "gm" 'evil-middle-of-visual-line)
+(define-key evil-motion-state-map "gM" 'evil-percentage-of-line)
+(define-key evil-motion-state-map "go" 'evil-goto-char)
+(define-key evil-motion-state-map "g$" 'evil-end-of-visual-line)
+(define-key evil-motion-state-map (vconcat "g" [end]) 'evil-end-of-visual-line)
+(define-key evil-motion-state-map "g\C-]" 'evil-jump-to-tag)
+(define-key evil-motion-state-map "{" 'evil-backward-paragraph)
+(define-key evil-motion-state-map "}" 'evil-forward-paragraph)
+(define-key evil-motion-state-map "#" 'evil-search-word-backward)
+(define-key evil-motion-state-map "g#" 'evil-search-unbounded-word-backward)
+(define-key evil-motion-state-map "$" 'evil-end-of-line)
+(define-key evil-motion-state-map [end] 'evil-end-of-line)
+(define-key evil-motion-state-map [home] 'evil-beginning-of-line)
+(define-key evil-motion-state-map "%" 'evil-jump-item)
+(define-key evil-motion-state-map "`" 'evil-goto-mark)
+(define-key evil-motion-state-map "'" 'evil-goto-mark-line)
+(define-key evil-motion-state-map "(" 'evil-backward-sentence-begin)
+(define-key evil-motion-state-map ")" 'evil-forward-sentence-begin)
+(define-key evil-motion-state-map "]]" 'evil-forward-section-begin)
+(define-key evil-motion-state-map "][" 'evil-forward-section-end)
+(define-key evil-motion-state-map "[[" 'evil-backward-section-begin)
+(define-key evil-motion-state-map "[]" 'evil-backward-section-end)
+(define-key evil-motion-state-map "[(" 'evil-previous-open-paren)
+(define-key evil-motion-state-map "])" 'evil-next-close-paren)
+(define-key evil-motion-state-map "[{" 'evil-previous-open-brace)
+(define-key evil-motion-state-map "]}" 'evil-next-close-brace)
+(define-key evil-motion-state-map "]'" 'evil-next-mark-line)
+(define-key evil-motion-state-map "]`" 'evil-next-mark)
+(define-key evil-motion-state-map "['" 'evil-previous-mark-line)
+(define-key evil-motion-state-map "[`" 'evil-previous-mark)
+(define-key evil-motion-state-map "]s" 'evil-next-flyspell-error)
+(define-key evil-motion-state-map "[s" 'evil-prev-flyspell-error)
+(define-key evil-motion-state-map "*" 'evil-search-word-forward)
+(define-key evil-motion-state-map "g*" 'evil-search-unbounded-word-forward)
+(define-key evil-motion-state-map "," 'evil-repeat-find-char-reverse)
+(define-key evil-motion-state-map "/" 'evil-search-forward)
+(define-key evil-motion-state-map ";" 'evil-repeat-find-char)
+(define-key evil-motion-state-map "?" 'evil-search-backward)
+(define-key evil-motion-state-map "|" 'evil-goto-column)
+(define-key evil-motion-state-map "^" 'evil-first-non-blank)
+(define-key evil-motion-state-map "+" 'evil-next-line-first-non-blank)
+(define-key evil-motion-state-map "_" 'evil-next-line-1-first-non-blank)
+(define-key evil-motion-state-map "-" 'evil-previous-line-first-non-blank)
+(define-key evil-motion-state-map "\C-w" 'evil-window-map)
+(define-key evil-motion-state-map (kbd "C-6") 'evil-switch-to-windows-last-buffer)
+(define-key evil-motion-state-map "\C-]" 'evil-jump-to-tag)
+(define-key evil-motion-state-map (kbd "C-b") 'evil-scroll-page-up)
+(define-key evil-motion-state-map (kbd "C-e") 'evil-scroll-line-down)
+(define-key evil-motion-state-map (kbd "C-f") 'evil-scroll-page-down)
+(define-key evil-motion-state-map (kbd "C-o") 'evil-jump-backward)
+(define-key evil-motion-state-map (kbd "C-y") 'evil-scroll-line-up)
+(define-key evil-motion-state-map (kbd "RET") 'evil-ret)
+(define-key evil-motion-state-map "\\" 'evil-execute-in-emacs-state)
+(define-key evil-motion-state-map "z^" 'evil-scroll-top-line-to-bottom)
+(define-key evil-motion-state-map "z+" 'evil-scroll-bottom-line-to-top)
+(define-key evil-motion-state-map "zt" 'evil-scroll-line-to-top)
+;; TODO: z RET has an advanced form taking an count before the RET
+;; but this requires again a special state with a single command
+;; bound to RET
+(define-key evil-motion-state-map (vconcat "z" [return]) 'evil-scroll-line-to-top-first-non-blank)
+(define-key evil-motion-state-map (kbd "z RET") 'evil-scroll-line-to-top-first-non-blank)
+(define-key evil-motion-state-map "zz" 'evil-scroll-line-to-center)
+(define-key evil-motion-state-map "z." 'evil-scroll-line-to-center-first-non-blank)
+(define-key evil-motion-state-map "zb" 'evil-scroll-line-to-bottom)
+(define-key evil-motion-state-map "z-" 'evil-scroll-line-to-bottom-first-non-blank)
+(define-key evil-motion-state-map "v" 'evil-visual-char)
+(define-key evil-motion-state-map "V" 'evil-visual-line)
+(define-key evil-motion-state-map "\C-v" 'evil-visual-block)
+(define-key evil-motion-state-map "gv" 'evil-visual-restore)
+(define-key evil-motion-state-map (kbd "C-^") 'evil-buffer)
+(define-key evil-motion-state-map [left] 'evil-backward-char)
+(define-key evil-motion-state-map [right] 'evil-forward-char)
+(define-key evil-motion-state-map [up] 'evil-previous-line)
+(define-key evil-motion-state-map [down] 'evil-next-line)
+(define-key evil-motion-state-map "zl" 'evil-scroll-column-right)
+(define-key evil-motion-state-map [?z right] 'evil-scroll-column-right)
+(define-key evil-motion-state-map "zh" 'evil-scroll-column-left)
+(define-key evil-motion-state-map [?z left] 'evil-scroll-column-left)
+(define-key evil-motion-state-map "ze" 'evil-scroll-end-column)
+(define-key evil-motion-state-map "zs" 'evil-scroll-start-column)
+(define-key evil-motion-state-map "zH" 'evil-scroll-left)
+(define-key evil-motion-state-map [?z S-left] 'evil-scroll-left)
+(define-key evil-motion-state-map "zL" 'evil-scroll-right)
+(define-key evil-motion-state-map [?z S-right] 'evil-scroll-right)
+(define-key evil-motion-state-map
+ (read-kbd-macro evil-toggle-key) 'evil-emacs-state)
+
+;; text objects
+(define-key evil-outer-text-objects-map "w" 'evil-a-word)
+(define-key evil-outer-text-objects-map "W" 'evil-a-WORD)
+(define-key evil-outer-text-objects-map "s" 'evil-a-sentence)
+(define-key evil-outer-text-objects-map "p" 'evil-a-paragraph)
+(define-key evil-outer-text-objects-map "b" 'evil-a-paren)
+(define-key evil-outer-text-objects-map "(" 'evil-a-paren)
+(define-key evil-outer-text-objects-map ")" 'evil-a-paren)
+(define-key evil-outer-text-objects-map "[" 'evil-a-bracket)
+(define-key evil-outer-text-objects-map "]" 'evil-a-bracket)
+(define-key evil-outer-text-objects-map "B" 'evil-a-curly)
+(define-key evil-outer-text-objects-map "{" 'evil-a-curly)
+(define-key evil-outer-text-objects-map "}" 'evil-a-curly)
+(define-key evil-outer-text-objects-map "<" 'evil-an-angle)
+(define-key evil-outer-text-objects-map ">" 'evil-an-angle)
+(define-key evil-outer-text-objects-map "'" 'evil-a-single-quote)
+(define-key evil-outer-text-objects-map "\"" 'evil-a-double-quote)
+(define-key evil-outer-text-objects-map "`" 'evil-a-back-quote)
+(define-key evil-outer-text-objects-map "t" 'evil-a-tag)
+(define-key evil-outer-text-objects-map "o" 'evil-a-symbol)
+(define-key evil-inner-text-objects-map "w" 'evil-inner-word)
+(define-key evil-inner-text-objects-map "W" 'evil-inner-WORD)
+(define-key evil-inner-text-objects-map "s" 'evil-inner-sentence)
+(define-key evil-inner-text-objects-map "p" 'evil-inner-paragraph)
+(define-key evil-inner-text-objects-map "b" 'evil-inner-paren)
+(define-key evil-inner-text-objects-map "(" 'evil-inner-paren)
+(define-key evil-inner-text-objects-map ")" 'evil-inner-paren)
+(define-key evil-inner-text-objects-map "[" 'evil-inner-bracket)
+(define-key evil-inner-text-objects-map "]" 'evil-inner-bracket)
+(define-key evil-inner-text-objects-map "B" 'evil-inner-curly)
+(define-key evil-inner-text-objects-map "{" 'evil-inner-curly)
+(define-key evil-inner-text-objects-map "}" 'evil-inner-curly)
+(define-key evil-inner-text-objects-map "<" 'evil-inner-angle)
+(define-key evil-inner-text-objects-map ">" 'evil-inner-angle)
+(define-key evil-inner-text-objects-map "'" 'evil-inner-single-quote)
+(define-key evil-inner-text-objects-map "\"" 'evil-inner-double-quote)
+(define-key evil-inner-text-objects-map "`" 'evil-inner-back-quote)
+(define-key evil-inner-text-objects-map "t" 'evil-inner-tag)
+(define-key evil-inner-text-objects-map "o" 'evil-inner-symbol)
+(define-key evil-motion-state-map "gn" 'evil-next-match)
+(define-key evil-motion-state-map "gN" 'evil-previous-match)
+
+(when evil-want-C-i-jump
+ (define-key evil-motion-state-map (kbd "C-i") 'evil-jump-forward))
+
+(when evil-want-C-u-scroll
+ (define-key evil-motion-state-map (kbd "C-u") 'evil-scroll-up))
+
+(when evil-want-C-d-scroll
+ (define-key evil-motion-state-map (kbd "C-d") 'evil-scroll-down))
+
+(when evil-want-C-g-bindings
+ (define-key evil-motion-state-map "g\C-g" 'count-words))
+
+;;; Visual state
+
+(define-key evil-visual-state-map "A" 'evil-append)
+(define-key evil-visual-state-map "I" 'evil-insert)
+(define-key evil-visual-state-map "o" 'exchange-point-and-mark)
+(define-key evil-visual-state-map "O" 'evil-visual-exchange-corners)
+(define-key evil-visual-state-map "R" 'evil-change-whole-line)
+(define-key evil-visual-state-map "u" 'evil-downcase)
+(define-key evil-visual-state-map "U" 'evil-upcase)
+(define-key evil-visual-state-map "X" 'evil-delete-line)
+(define-key evil-visual-state-map "a" evil-outer-text-objects-map)
+(define-key evil-visual-state-map "i" evil-inner-text-objects-map)
+(define-key evil-visual-state-map (kbd "<insert>") 'undefined)
+(define-key evil-visual-state-map (kbd "<insertchar>") 'undefined)
+(define-key evil-visual-state-map [remap evil-repeat] 'undefined)
+(define-key evil-visual-state-map [escape] 'evil-exit-visual-state)
+(define-key evil-visual-state-map "gf" 'evil-find-file-at-point-visual)
+
+;;; Operator-Pending state
+
+(define-key evil-operator-state-map "a" evil-outer-text-objects-map)
+(define-key evil-operator-state-map "i" evil-inner-text-objects-map)
+;; (define-key evil-operator-state-map [escape] 'keyboard-quit)
+
+;;; Insert state
+
+(defvar evil-insert-state-bindings
+ `(([insert] . evil-enter-replace-state)
+ ("\C-q" . evil-quoted-insert)
+ ("\C-v" . evil-quoted-insert)
+ ("\C-k" . evil-insert-digraph)
+ ("\C-o" . evil-execute-in-normal-state)
+ ("\C-r" . evil-paste-from-register)
+ ("\C-y" . evil-copy-from-above)
+ ("\C-e" . evil-copy-from-below)
+ ("\C-n" . evil-complete-next) ;; Completion commands
+ ("\C-p" . evil-complete-previous) ;; don't yet behave correctly
+ ("\C-x\C-n" . evil-complete-next-line) ;; in replace state
+ ("\C-x\C-p" . evil-complete-previous-line) ;; TODO - fix this
+ ("\C-t" . evil-shift-right-line)
+ ("\C-d" . evil-shift-left-line)
+ ("\C-a" . evil-paste-last-insertion)
+ ("\C-@" . evil-paste-last-insertion-and-stop-insert)
+ ([remap delete-backward-char] . evil-delete-backward-char-and-join)
+ ([S-left] . evil-backward-word-begin)
+ ([S-right] . evil-forward-word-begin)
+ ,(if evil-want-C-w-delete
+ '("\C-w" . evil-delete-backward-word)
+ '("\C-w" . evil-window-map))
+ ,@(when evil-want-C-u-delete
+ '(("\C-u" . evil-delete-back-to-indentation)))
+ ,@(when evil-want-C-h-delete
+ '(("\C-h" . evil-delete-backward-char-and-join)))
+ ([mouse-2] . mouse-yank-primary))
+ "Evil's bindings for insert & replace states.
+Used in `evil-insert-state-map' and `evil-replace-state-map',
+excluding <delete>, <escape>, and `evil-toggle-key'.")
+
+(defun evil-update-insert-state-bindings (&optional _option-name remove force)
+ "Update bindings in `evil-insert-state-map'.
+If no arguments are given add the bindings specified in
+`evil-insert-state-bindings'. If REMOVE is non nil, remove only
+these bindings. Unless FORCE is non nil, this will not
+overwriting existing bindings, which means bindings will not be
+added if one already exists for a key and only default bindings
+are removed.
+
+Note that <delete>, <escape> and `evil-toggle-key' are not
+included in `evil-insert-state-bindings' by default."
+ (interactive)
+ (dolist (binding evil-insert-state-bindings)
+ (cond
+ ((and remove
+ (or force
+ ;; Only remove if the default binding has not changed
+ (eq (evil-lookup-key evil-insert-state-map (car binding))
+ (cdr binding))))
+ (define-key evil-insert-state-map (car binding) nil))
+ ((and (null remove)
+ (or force
+ ;; Check to see that nothing is bound here before adding
+ (not (evil-lookup-key evil-insert-state-map (car binding)))))
+ (define-key evil-insert-state-map (car binding) (cdr binding))))))
+
+(define-key evil-insert-state-map [delete] 'delete-char)
+(define-key evil-insert-state-map [escape] 'evil-normal-state)
+(define-key evil-insert-state-map
+ (read-kbd-macro evil-toggle-key) 'evil-emacs-state)
+
+;;; Replace state
+
+(dolist (binding evil-insert-state-bindings)
+ (define-key evil-replace-state-map (car binding) (cdr binding)))
+(define-key evil-replace-state-map (kbd "DEL") 'evil-replace-backspace)
+(when evil-want-C-h-delete
+ (define-key evil-replace-state-map "\C-h" 'evil-replace-backspace))
+(define-key evil-replace-state-map [escape] 'evil-normal-state)
+(define-key evil-replace-state-map [insert] 'evil-append)
+
+;;; Emacs state
+
+(define-key evil-emacs-state-map
+ (read-kbd-macro evil-toggle-key) 'evil-exit-emacs-state)
+
+(when evil-want-C-w-in-emacs-state
+ (define-key evil-emacs-state-map "\C-w" 'evil-window-map))
+
+;;; Mouse
+(define-key evil-motion-state-map [down-mouse-1] 'evil-mouse-drag-region)
+(define-key evil-visual-state-map [mouse-2] 'evil-exit-visual-and-repeat)
+(define-key evil-normal-state-map [mouse-2] 'mouse-yank-primary)
+
+;; Ex
+(define-key evil-motion-state-map ":" 'evil-ex)
+(define-key evil-motion-state-map "!" 'evil-shell-command)
+
+(evil-ex-define-cmd "e[dit]" 'evil-edit)
+(evil-ex-define-cmd "vie[w]" 'evil-view)
+(evil-ex-define-cmd "w[rite]" 'evil-write)
+(evil-ex-define-cmd "up[date]" 'evil-update)
+(evil-ex-define-cmd "wa[ll]" 'evil-write-all)
+(evil-ex-define-cmd "sav[eas]" 'evil-save)
+(evil-ex-define-cmd "r[ead]" 'evil-read)
+(evil-ex-define-cmd "b[uffer]" 'evil-buffer)
+(evil-ex-define-cmd "bad[d]" 'evil-buffer-add)
+(evil-ex-define-cmd "bn[ext]" 'evil-next-buffer)
+(evil-ex-define-cmd "bp[revious]" 'evil-prev-buffer)
+(evil-ex-define-cmd "bN[ext]" "bprevious")
+(evil-ex-define-cmd "sb[uffer]" 'evil-split-buffer)
+(evil-ex-define-cmd "sbn[ext]" 'evil-split-next-buffer)
+(evil-ex-define-cmd "sbp[revious]" 'evil-split-prev-buffer)
+(evil-ex-define-cmd "sbN[ext]" "sbprevious")
+(evil-ex-define-cmd "buffers" 'buffer-menu)
+(evil-ex-define-cmd "files" 'evil-show-files)
+(evil-ex-define-cmd "ls" "buffers")
+
+(evil-ex-define-cmd "c[hange]" 'evil-change)
+(evil-ex-define-cmd "co[py]" 'evil-copy)
+(evil-ex-define-cmd "t" "copy")
+(evil-ex-define-cmd "m[ove]" 'evil-move)
+(evil-ex-define-cmd "d[elete]" 'evil-ex-delete)
+(evil-ex-define-cmd "y[ank]" 'evil-ex-yank)
+(evil-ex-define-cmd "pu[t]" 'evil-ex-put)
+(evil-ex-define-cmd "go[to]" 'evil-goto-char)
+(evil-ex-define-cmd "j[oin]" 'evil-ex-join)
+(evil-ex-define-cmd "le[ft]" 'evil-align-left)
+(evil-ex-define-cmd "ri[ght]" 'evil-align-right)
+(evil-ex-define-cmd "ce[nter]" 'evil-align-center)
+(evil-ex-define-cmd "sp[lit]" 'evil-window-split)
+(evil-ex-define-cmd "sv[iew]" 'evil-window-split-view)
+(evil-ex-define-cmd "vs[plit]" 'evil-window-vsplit)
+(evil-ex-define-cmd "new" 'evil-window-new)
+(evil-ex-define-cmd "ene[w]" 'evil-buffer-new)
+(evil-ex-define-cmd "vne[w]" 'evil-window-vnew)
+(evil-ex-define-cmd "clo[se]" 'evil-window-delete)
+(evil-ex-define-cmd "on[ly]" 'delete-other-windows)
+(evil-ex-define-cmd "q[uit]" 'evil-quit)
+(evil-ex-define-cmd "wq" 'evil-save-and-close)
+(evil-ex-define-cmd "quita[ll]" 'evil-quit-all)
+(evil-ex-define-cmd "qa[ll]" "quitall")
+(evil-ex-define-cmd "cq[uit]" 'evil-quit-all-with-error-code)
+(evil-ex-define-cmd "wqa[ll]" 'evil-save-and-quit)
+(evil-ex-define-cmd "xa[ll]" "wqall")
+(evil-ex-define-cmd "x[it]" 'evil-save-modified-and-close)
+(evil-ex-define-cmd "exi[t]" 'evil-save-modified-and-close)
+(evil-ex-define-cmd "bd[elete]" 'evil-delete-buffer)
+(evil-ex-define-cmd "bw[ipeout]" 'evil-delete-buffer)
+(evil-ex-define-cmd "g[lobal]" 'evil-ex-global)
+(evil-ex-define-cmd "v[global]" 'evil-ex-global-inverted)
+(evil-ex-define-cmd "norm[al]" 'evil-ex-normal)
+(evil-ex-define-cmd "s[ubstitute]" 'evil-ex-substitute)
+(evil-ex-define-cmd "&" 'evil-ex-repeat-substitute)
+(evil-ex-define-cmd "&&" 'evil-ex-repeat-substitute-with-flags)
+(evil-ex-define-cmd "~" 'evil-ex-repeat-substitute-with-search)
+(evil-ex-define-cmd "~&" 'evil-ex-repeat-substitute-with-search-and-flags)
+(evil-ex-define-cmd "mat[ch]" 'evil-ex-match)
+(evil-ex-define-cmd "registers" 'evil-show-registers)
+(evil-ex-define-cmd "di[splay]" "registers")
+(evil-ex-define-cmd "ma[rk]" 'evil-set-col-0-mark)
+(evil-ex-define-cmd "marks" 'evil-show-marks)
+(evil-ex-define-cmd "delm[arks]" 'evil-delete-marks)
+(evil-ex-define-cmd "ju[mps]" 'evil-show-jumps)
+(evil-ex-define-cmd "noh[lsearch]" 'evil-ex-nohighlight)
+(evil-ex-define-cmd "f[ile]" 'evil-show-file-info)
+(evil-ex-define-cmd "<" 'evil-shift-left)
+(evil-ex-define-cmd ">" 'evil-shift-right)
+(evil-ex-define-cmd "=" 'evil-ex-line-number)
+(evil-ex-define-cmd "!" 'evil-shell-command)
+(evil-ex-define-cmd "@:" 'evil-ex-repeat)
+(evil-ex-define-cmd "mak[e]" 'evil-make)
+(evil-ex-define-cmd "cc" 'evil-goto-error)
+(evil-ex-define-cmd "cfir[st]" 'first-error)
+(evil-ex-define-cmd "cr[ewind]" 'first-error)
+(evil-ex-define-cmd "cn[ext]" 'next-error)
+(evil-ex-define-cmd "cp[revious]" 'previous-error)
+(evil-ex-define-cmd "set-initial-state" 'evil-ex-set-initial-state)
+(evil-ex-define-cmd "show-digraphs" 'evil-ex-show-digraphs)
+(evil-ex-define-cmd "sor[t]" 'evil-ex-sort)
+(evil-ex-define-cmd "res[ize]" 'evil-ex-resize)
+(evil-ex-define-cmd "u[ndo]" 'evil-undo)
+(evil-ex-define-cmd "red[o]" 'evil-redo)
+(evil-ex-define-cmd "p[rint]" 'evil-ex-print)
+(evil-ex-define-cmd "P[rint]" 'evil-ex-print)
+(evil-ex-define-cmd "nu[mber]" 'evil-ex-numbered-print)
+(evil-ex-define-cmd "#" 'evil-ex-numbered-print)
+(evil-ex-define-cmd "z" 'evil-ex-z)
+(evil-ex-define-cmd "ret[ab]" 'evil-retab)
+
+(when (featurep 'tab-bar)
+ (evil-ex-define-cmd "tabnew" 'tab-bar-new-tab)
+ (evil-ex-define-cmd "tabc[lose]" 'tab-bar-close-tab)
+ (evil-ex-define-cmd "tabo[nly]" 'tab-bar-close-other-tabs)
+ (evil-ex-define-cmd "tabn[ext]" 'evil-tab-next)
+ (evil-ex-define-cmd "tabp[revious]" 'tab-bar-switch-to-prev-tab))
+
+;; Command-line editing
+(define-key evil-command-line-map "\d" #'evil-ex-delete-backward-char)
+(define-key evil-command-line-map "\t" #'completion-at-point)
+(define-key evil-command-line-map [tab] #'completion-at-point)
+(define-key evil-command-line-map "\C-a" #'completion-at-point)
+(define-key evil-command-line-map "\C-b" #'move-beginning-of-line)
+(define-key evil-command-line-map "\C-c" #'abort-recursive-edit)
+(define-key evil-command-line-map "\C-d" #'completion-at-point)
+(define-key evil-command-line-map "\C-f" 'evil-command-window)
+(define-key evil-command-line-map "\C-g" #'abort-minibuffers)
+(define-key evil-command-line-map "\C-k" 'evil-insert-digraph)
+(define-key evil-command-line-map "\C-l" #'completion-at-point)
+(define-key evil-command-line-map "\C-n" #'next-history-element)
+(define-key evil-command-line-map "\C-p" #'previous-history-element)
+(define-key evil-command-line-map "\C-r" 'evil-paste-from-register)
+(define-key evil-command-line-map "\C-u" 'evil-delete-whole-line)
+(define-key evil-command-line-map "\C-v" #'quoted-insert)
+(when evil-want-C-w-delete
+ (define-key evil-command-line-map "\C-w" #'evil-delete-backward-word))
+(define-key evil-command-line-map [escape] #'abort-recursive-edit)
+(define-key evil-command-line-map [S-left] #'backward-word)
+(define-key evil-command-line-map [S-right] #'forward-word)
+(define-key evil-command-line-map [up] #'previous-complete-history-element)
+(define-key evil-command-line-map [down] #'next-complete-history-element)
+(define-key evil-command-line-map [prior] #'previous-history-element)
+(define-key evil-command-line-map [next] #'next-history-element)
+(define-key evil-command-line-map [return] #'exit-minibuffer)
+(define-key evil-command-line-map (kbd "RET") #'exit-minibuffer)
+
+;; search command line
+(set-keymap-parent evil-ex-search-keymap evil-command-line-map)
+(unless evil-want-C-w-delete
+ (define-key evil-ex-search-keymap "\C-w" 'evil-search-yank-word))
+
+;; Ex command line
+(set-keymap-parent evil-ex-completion-map evil-command-line-map)
+
+;; eval prompt (the `=' register)
+(define-key evil-eval-map "\C-b" 'move-beginning-of-line)
+(define-key evil-eval-map "\C-c" 'abort-recursive-edit)
+(define-key evil-eval-map "\C-g" 'abort-recursive-edit)
+(define-key evil-eval-map "\C-k" 'evil-insert-digraph)
+(define-key evil-eval-map "\C-p" #'previous-complete-history-element)
+(define-key evil-eval-map "\C-r" 'evil-paste-from-register)
+(define-key evil-eval-map "\C-n" #'next-complete-history-element)
+(define-key evil-eval-map "\C-u" 'evil-delete-whole-line)
+(define-key evil-eval-map "\C-v" #'quoted-insert)
+(define-key evil-eval-map "\C-w" 'evil-delete-backward-word)
+(define-key evil-eval-map [escape] 'abort-recursive-edit)
+(define-key evil-eval-map [S-left] 'backward-word)
+(define-key evil-eval-map [S-right] 'forward-word)
+(define-key evil-eval-map [up] 'previous-complete-history-element)
+(define-key evil-eval-map [down] 'next-complete-history-element)
+(define-key evil-eval-map [prior] 'previous-history-element)
+(define-key evil-eval-map [next] 'next-history-element)
+(define-key evil-eval-map [return] 'exit-minibuffer)
+(define-key evil-eval-map (kbd "RET") 'exit-minibuffer)
+
+;; evil-read-key
+(define-key evil-read-key-map (kbd "ESC") #'keyboard-quit)
+(define-key evil-read-key-map (kbd "C-]") #'keyboard-quit)
+(define-key evil-read-key-map (kbd "C-g") #'keyboard-quit)
+(define-key evil-read-key-map (kbd "C-q") #'evil-read-quoted-char)
+(define-key evil-read-key-map (kbd "C-v") #'evil-read-quoted-char)
+(define-key evil-read-key-map (kbd "C-k") #'evil-read-digraph-char)
+(define-key evil-read-key-map "\r" "\n")
+
+;; command line window
+(evil-define-key* '(normal insert) evil-command-window-mode-map
+ (kbd "RET") 'evil-command-window-execute)
+
+(provide 'evil-maps)
+
+;;; evil-maps.el ends here
diff --git a/.config/emacs/lisp/evil/evil-repeat.el b/.config/emacs/lisp/evil/evil-repeat.el
new file mode 100644
index 0000000..75727ef
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-repeat.el
@@ -0,0 +1,641 @@
+;;; evil-repeat.el --- Repeat system -*- lexical-binding: t -*-
+
+;; Author: Frank Fischer <frank.fischer at mathematik.tu-chemnitz.de>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A repeat begins when leaving Normal state; it ends when re-entering
+;; Normal state. The diagram below shows possible routes between
+;; Normal state (N), Insert state (I), Visual state (V),
+;; Operator-Pending state (O) and Replace state (R). (Emacs state
+;; is an exception: nothing is repeated in that state.)
+;; ___
+;; / \
+;; | R |
+;; \___/
+;; ^ |
+;; | |
+;; ___ |___V ___
+;; / \ <------- / \ -------> / \
+;; | V | | N | | O |
+;; \___/ -------> \___/ <------- \___/
+;; | | ^ |
+;; | | | |
+;; | V___| |
+;; | / \ |
+;; +--------> | I | <--------+
+;; \___/
+;;
+;; The recording of a repeat is started in one of two cases: Either a
+;; command is about to be executed (in pre-command-hook) or normal
+;; state is exited. The recording is stopped whenever a command has
+;; been completed and evil is in normal state afterwards. Therefore,
+;; a non-inserting command in normal-state is recorded as a single
+;; repeat unit. In contrast, if the command leaves normal state and
+;; starts insert-state, all commands that are executed until
+;; insert-state is left and normal state is reactivated are recorded
+;; together in one repeat unit. In other words, a repeat unit consists
+;; of all commands that are executed starting and ending in normal
+;; state.
+;;
+;; Not all commands are recorded. There are several commands that are
+;; completely ignored and other commands that even abort the currently
+;; active recording, e.g., commands that switch buffer.
+;;
+;; During recording the repeat information is appended to the variable
+;; `evil-repeat-info', which is cleared when the recording
+;; starts. This accumulated repeat information is put into the
+;; `evil-repeat-ring' when the recording is finished. The dot command,
+;; `\[evil-repeat]' (`evil-repeat') replays the most recent entry in
+;; the ring, preceeding repeats can be replayed using
+;; `\[evil-repeat-pop]' (`evil-repeat-pop').
+;;
+;; Repeat information can be stored in almost arbitrary form. How the
+;; repeat information for each single command is recorded is
+;; determined by the :repeat property of the command. This property
+;; has the following interpretation:
+;;
+;; t record commands by storing the key-sequence that invoked it
+;; nil ignore this command completely
+;; ignore synonym to nil
+;; motion command is recorded by storing the key-sequence but only in
+;; insert state, otherwise it is ignored.
+;; abort stop recording of repeat information immediately
+;; change record commands by storing buffer changes
+;; SYMBOL if SYMBOL is contained as key in `evil-repeat-types' call
+;; the corresponding (function-)value, otherwise call the
+;; function associated with SYMBOL. In both cases the
+;; function should take exactly one argument which is either
+;; `pre', `pre-read-key-sequence' or `post' specifying on
+;; whether the function is called before or after the
+;; execution of the command.
+;;
+;; Therefore, using a certain SYMBOL one can write specific repeation
+;; functions for each command.
+;;
+;; Each value of ring `evil-repeat-info', i.e., each single repeat
+;; information must be one of the following two possibilities:
+;; If element is a sequence, it is regarded as a key-sequence to
+;; be repeated. Otherwise the element must be a list
+;; (FUNCTION PARAMS ...) which will be called using
+;; (apply FUNCTION PARAMS) whenever this repeat is being executed.
+;;
+;; A user supplied repeat function can use the functions
+;; `evil-record-repeat' to append further repeat-information of the
+;; form described above to `evil-repeat-info'. See the implementation
+;; of `evil-repeat-keystrokes' and `evil-repeat-changes' for examples.
+;;
+;; The repeat information is executed with `evil-execute-repeat-info',
+;; which passes key-sequence elements to `execute-kbd-macro' and
+;; executes other elements as defined above. A special version is
+;; `evil-execute-repeat-info-with-count'. This function works as
+;; `evil-execute-repeat-info', but replaces the count of the first
+;; command. This is done by parsing the key-sequence, ignoring all
+;; calls to `digit-prefix-argument' and `negative-argument', and
+;; prepending the count as a string to the vector of the remaining
+;; key-sequence.
+
+;;; Code:
+
+(require 'evil-states)
+
+(defmacro evil-without-repeat (&rest body)
+ (declare (indent defun)
+ (debug t))
+ `(let ((pre-command-hook (remq 'evil-repeat-pre-hook pre-command-hook))
+ (post-command-hook (remq 'evil-repeat-post-hook post-command-hook)))
+ ,@body
+ (evil-repeat-abort)))
+
+(defsubst evil-repeat-recording-p ()
+ "Return non-nil if a recording is in progress."
+ (eq evil-recording-repeat t))
+
+(defun evil-repeat-start ()
+ "Start recording a new repeat into `evil-repeat-info'."
+ (evil-repeat-reset t)
+ (evil-repeat-record-buffer)
+ (when (evil-visual-state-p)
+ (let* ((range (evil-visual-range))
+ (beg (evil-range-beginning range))
+ (end (max 1 (1- (evil-range-end range))))
+ (nfwdlines (evil-count-lines beg end)))
+ (evil-repeat-record
+ (cond
+ ((eq evil-visual-selection 'char)
+ (list #'evil-repeat-visual-char
+ nfwdlines
+ (- end
+ (if (zerop nfwdlines)
+ beg
+ (save-excursion
+ (goto-char end)
+ (line-beginning-position))))))
+ ((eq evil-visual-selection 'line)
+ (list #'evil-repeat-visual-line nfwdlines))
+ ((eq evil-visual-selection 'block)
+ (list #'evil-repeat-visual-block
+ nfwdlines
+ (abs (- (evil-column beg) (evil-column end))))))))))
+
+(defun evil-repeat-stop ()
+ "Stop recording a repeat.
+Update `evil-repeat-ring' with the accumulated changes
+in `evil-repeat-info' and clear variables."
+ (unwind-protect
+ (when (evil-repeat-recording-p)
+ (setq evil-repeat-info (evil-normalize-repeat-info evil-repeat-info))
+ (when (and evil-repeat-info evil-repeat-ring)
+ (ring-insert evil-repeat-ring evil-repeat-info)))
+ (evil-repeat-reset nil)))
+
+(defun evil-repeat-abort ()
+ "Abort current repeation."
+ (evil-repeat-reset 'abort))
+
+(defun evil-repeat-reset (flag)
+ "Clear all repeat recording variables.
+Set `evil-recording-repeat' to FLAG."
+ (setq evil-recording-repeat flag
+ evil-repeat-info nil
+ evil-repeat-buffer nil))
+
+(defsubst evil-repeat-record-position (&optional pos)
+ "Set `evil-repeat-pos' to POS or point."
+ (setq evil-repeat-pos (or pos (point))))
+
+(defun evil-repeat-record-buffer ()
+ "Set `evil-repeat-buffer' to the current buffer."
+ (unless (minibufferp)
+ (setq evil-repeat-buffer (current-buffer))))
+
+(defmacro evil-save-repeat-info (&rest body)
+ "Execute BODY, protecting the values of repeat variables."
+ (declare (indent defun)
+ (debug t))
+ `(let (evil-repeat-ring
+ evil-recording-repeat
+ evil-recording-current-command
+ evil-repeat-info
+ evil-repeat-changes
+ evil-repeat-pos
+ evil-repeat-keys
+ evil-repeat-buffer
+ this-command
+ last-command)
+ ,@body))
+
+(defun evil-repeat-different-buffer-p (&optional strict)
+ "Whether the buffer has changed in a repeat.
+If STRICT is non-nil, returns t if the previous buffer
+is unknown; otherwise returns t only if the previous
+buffer is known and different from the current buffer."
+ (and (or (buffer-live-p evil-repeat-buffer) strict)
+ (not (minibufferp))
+ (not (eq (current-buffer) evil-repeat-buffer))))
+
+(defvar evil-repeat-types
+ '((t . evil-repeat-keystrokes)
+ (change . evil-repeat-changes)
+ (motion . evil-repeat-motion)
+ (insert-at-point . evil-repeat-insert-at-point)
+ (ignore . nil))
+ "Alist of defined repeat-types.")
+
+(defun evil--repeat-type (command)
+ "Return the :repeat property of COMMAND."
+ (when (functionp command) ; ignore keyboard macros
+ (let* ((type (evil-get-command-property command :repeat t))
+ (repeat-type (assq type evil-repeat-types)))
+ (if repeat-type (cdr repeat-type) type))))
+
+(defun evil-repeat-type (command &optional default)
+ "Return the :repeat property of COMMAND.
+If COMMAND doesn't have this property, return DEFAULT."
+ (declare (obsolete evil--repeat-type "1.15.0"))
+ (when (functionp command) ; ignore keyboard macros
+ (let* ((type (evil-get-command-property command :repeat default))
+ (repeat-type (assq type evil-repeat-types)))
+ (if repeat-type (cdr repeat-type) type))))
+
+(defun evil-repeat-force-abort-p (repeat-type)
+ "Whether the current command should abort the recording of repeat information.
+Return non-nil if so."
+ (or (evil-repeat-different-buffer-p) ; ... buffer changed
+ (eq repeat-type 'abort) ; ... explicitly forced
+ (eq evil-recording-repeat 'abort) ; ... already aborted
+ (evil-emacs-state-p) ; ... in Emacs state
+ (and (evil-mouse-events-p ; ... mouse events
+ (this-command-keys-vector))
+ (null repeat-type))
+ (minibufferp))) ; ... minibuffer activated
+
+(defun evil-repeat-record (info)
+ "Append INFO to `evil-repeat-info'."
+ (when (evil-repeat-recording-p)
+ (setq evil-repeat-info (nconc evil-repeat-info (list info)))))
+
+;; called from `pre-command-hook'
+(defun evil-repeat-pre-hook ()
+ "Prepare the current command for recording the repeation."
+ (when evil-local-mode
+ (let ((repeat-type (evil--repeat-type this-command)))
+ (cond
+ ;; abort the repeat
+ ((evil-repeat-force-abort-p repeat-type)
+ ;; We mark the current record as being aborted, because there
+ ;; may be further pre-hooks following before the post-hook is
+ ;; called.
+ (evil-repeat-abort))
+ ;; ignore those commands completely
+ ((or (null repeat-type)
+ (evil-mouse-events-p (this-command-keys-vector))))
+ ;; record command
+ (t
+ ;; In normal-state or visual state, each command is a single
+ ;; repeation, therefore start a new repeation.
+ (when (or (evil-normal-state-p)
+ (evil-visual-state-p))
+ (evil-repeat-start))
+ (setq evil-recording-current-command t)
+ (funcall repeat-type 'pre))))))
+(put 'evil-repeat-pre-hook 'permanent-local-hook t)
+
+;; called from `post-command-hook'
+(defun evil-repeat-post-hook ()
+ "Finish recording of repeat-information for the current-command."
+ (when (and evil-local-mode evil-recording-repeat)
+ (let ((repeat-type (evil--repeat-type this-command)))
+ (cond
+ ;; abort the repeat
+ ((evil-repeat-force-abort-p repeat-type)
+ ;; The command has been aborted but is complete, so just reset
+ ;; the recording state.
+ (evil-repeat-reset nil))
+ ;; ignore if command should not be recorded or the current
+ ;; command is not being recorded
+ ((or (null repeat-type)
+ (not evil-recording-current-command)))
+ ;; record command
+ (t
+ (funcall repeat-type 'post)
+ ;; In normal state, the repeat sequence is complete, so record it.
+ (when (evil-normal-state-p)
+ (evil-repeat-stop)))))
+ ;; done with recording the current command
+ (setq evil-recording-current-command nil)))
+(put 'evil-repeat-post-hook 'permanent-local-hook t)
+
+(defun evil-clear-command-keys ()
+ "Clear `this-command-keys' and all information about the current command keys.
+Calling this function prevents further recording of the keys that
+invoked the current command"
+ (clear-this-command-keys t)
+ (setq evil-repeat-keys ""))
+
+(defun evil-this-command-keys (&optional post-cmd)
+ "Version of `this-command-keys' with finer control over prefix args."
+ (vconcat
+ (let ((arg (if post-cmd current-prefix-arg prefix-arg)))
+ (and (numberp arg)
+ ;; Only add prefix if no repeat info recorded yet
+ (null evil-repeat-info)
+ (number-to-string arg)))
+ (this-single-command-keys)))
+
+(defun evil-repeat-keystrokes (flag)
+ "Repeation recording function for commands that are repeated by keystrokes."
+ (cond
+ ((eq flag 'pre)
+ (when evil-this-register
+ (evil-repeat-record
+ `(set evil-this-register ,evil-this-register)))
+ (setq evil-repeat-keys (evil-this-command-keys)))
+ ((memq flag '(post pre-read-key-sequence))
+ (evil-repeat-record (if (zerop (length (evil-this-command-keys t)))
+ evil-repeat-keys
+ (evil-this-command-keys t)))
+ ;; erase commands keys to prevent double recording
+ (evil-clear-command-keys))))
+
+(defun evil-repeat-motion (flag)
+ "Repetition for motions.
+Motions are recorded by keystroke but only in Insert state."
+ (when (memq evil-state '(insert replace))
+ (evil-repeat-keystrokes flag)))
+
+(defun evil-repeat-changes (flag)
+ "Repeation recording function for commands that are repeated by buffer changes."
+ (cond
+ ((eq flag 'pre)
+ (add-hook 'after-change-functions #'evil-repeat-change-hook nil t)
+ (evil-repeat-start-record-changes))
+ ((eq flag 'post)
+ (remove-hook 'after-change-functions #'evil-repeat-change-hook t)
+ (evil-repeat-finish-record-changes))))
+
+;; called from the `after-change-functions' hook
+(defun evil-repeat-change-hook (beg end length)
+ "Record change information for current command."
+ (let ((repeat-type (evil--repeat-type this-command)))
+ (when (and (evil-repeat-recording-p)
+ (eq repeat-type 'evil-repeat-changes)
+ (not (evil-emacs-state-p))
+ (not (evil-repeat-different-buffer-p t))
+ evil-state)
+ (unless (evil-repeat-recording-p)
+ (evil-repeat-start))
+ (evil-repeat-record-change (- beg evil-repeat-pos)
+ (buffer-substring beg end)
+ length))))
+(put 'evil-repeat-change-hook 'permanent-local-hook t)
+
+(defun evil-repeat-record-change (relpos ins ndel)
+ "Record the current buffer changes during a repeat.
+If CHANGE is specified, it is added to `evil-repeat-changes'."
+ (when (evil-repeat-recording-p)
+ (push (list relpos ins ndel) evil-repeat-changes)))
+
+(defun evil-repeat-start-record-changes ()
+ "Start the recording of a new set of buffer changes."
+ (setq evil-repeat-changes nil)
+ (evil-repeat-record-position))
+
+(defun evil-repeat-finish-record-changes ()
+ "Finish the recording of buffer changes and record them as repeat."
+ (when (evil-repeat-recording-p)
+ (evil-repeat-record `(evil-execute-change
+ ,(nreverse evil-repeat-changes)
+ ,(- (point) evil-repeat-pos)))
+ (setq evil-repeat-changes nil)))
+
+(defun evil-repeat-insert-at-point (flag)
+ "Repeation recording function for commands that insert text in region.
+For example `mouse-yank-primary'. This records text insertion when a command
+inserts some text in a buffer between (point) and (mark)."
+ (cond
+ ((eq flag 'pre)
+ (add-hook 'after-change-functions #'evil-repeat-insert-at-point-hook nil t))
+ ((eq flag 'post)
+ (remove-hook 'after-change-functions #'evil-repeat-insert-at-point-hook t))))
+
+(defun evil-repeat-insert-at-point-hook (beg end _length)
+ (let ((repeat-type (evil--repeat-type this-command)))
+ (when (and (evil-repeat-recording-p)
+ (eq repeat-type 'evil-repeat-insert-at-point)
+ (not (evil-emacs-state-p))
+ (not (evil-repeat-different-buffer-p t))
+ evil-state)
+ (setq evil-repeat-pos beg)
+ (evil-repeat-record (list 'insert (buffer-substring beg end))))))
+(put 'evil-repeat-insert-at-point-hook 'permanent-local-hook t)
+
+(defun evil-normalize-repeat-info (repeat-info)
+ "Concatenate consecutive arrays in REPEAT-INFO.
+Return a single array."
+ (let* ((result (cons nil nil))
+ (result-last result)
+ cur cur-last)
+ (dolist (rep repeat-info)
+ (cond
+ ((null rep))
+ ((arrayp rep)
+ (setq rep (listify-key-sequence rep))
+ (cond
+ (cur
+ (setcdr cur-last (cons rep nil))
+ (setq cur-last (cdr cur-last)))
+ (t (setq cur (cons rep nil)
+ cur-last cur))))
+ (t
+ (when cur
+ (setcdr result-last (cons (apply #'vconcat cur) nil))
+ (setq result-last (cdr result-last)
+ cur nil))
+ (setcdr result-last (cons rep nil))
+ (setq result-last (cdr result-last)))))
+ (when cur
+ (setcdr result-last (cons (apply #'vconcat cur) nil)))
+ (cdr result)))
+
+(defun evil-repeat-visual-char (nfwdlines nfwdchars)
+ "Restore a character visual selection.
+If the selection is in a single line, the restored visual
+selection covers the same number of characters. If the selection
+covers several lines, the restored selection covers the same
+number of lines and the same number of characters in the last
+line as the original selection."
+ (evil-visual-char)
+ (when (> nfwdlines 0)
+ (forward-line nfwdlines))
+ (forward-char nfwdchars))
+
+(defun evil-repeat-visual-line (nfwdlines)
+ "Restore a character visual selection.
+If the selection is in a single line, the restored visual
+selection covers the same number of characters. If the selection
+covers several lines, the restored selection covers the same
+number of lines and the same number of characters in the last
+line as the original selection."
+ (evil-visual-line)
+ (forward-line nfwdlines))
+
+(defun evil-repeat-visual-block (nfwdlines nfwdchars)
+ "Restore a character visual selection.
+If the selection is in a single line, the restored visual
+selection covers the same number of characters. If the selection
+covers several lines, the restored selection covers the same
+number of lines and the same number of characters in the last
+line as the original selection."
+ (evil-visual-block)
+ (let ((col (current-column)))
+ (forward-line nfwdlines)
+ (move-to-column (+ col nfwdchars) t)))
+
+(defun evil-execute-change (changes rel-point)
+ "Execute as list of changes.
+
+CHANGES is a list of triples (REL-BEG INSERT-TEXT NDEL).
+REL-BEG is the relative position (to point) where the change
+takes place. INSERT-TEXT is the text to be inserted at that
+position and NDEL the number of characters to be deleted at that
+position before insertion.
+
+REL-POINT is the relative position to point before the changed
+where point should be placed after all changes."
+ (evil-save-repeat-info
+ (let ((point (point)))
+ (dolist (change changes)
+ (goto-char (+ point (nth 0 change)))
+ (delete-char (nth 2 change))
+ (insert (nth 1 change)))
+ (goto-char (+ point rel-point)))))
+
+(defun evil-execute-repeat-info (repeat-info)
+ "Execute a repeat-information REPEAT-INFO."
+ (evil-save-repeat-info
+ (dolist (rep repeat-info)
+ (cond
+ ((or (arrayp rep) (stringp rep))
+ (let ((input-method current-input-method)
+ (evil-input-method nil))
+ (deactivate-input-method)
+ (unwind-protect
+ (execute-kbd-macro rep)
+ (activate-input-method input-method))))
+ ((consp rep)
+ (when (and (= 3 (length rep))
+ (eq (nth 0 rep) 'set)
+ (eq (nth 1 rep) 'evil-this-register)
+ (>= (nth 2 rep) ?0)
+ (< (nth 2 rep) ?9))
+ (setcar (nthcdr 2 rep) (1+ (nth 2 rep))))
+ (apply (car rep) (cdr rep)))
+ (t (error "Unexpected repeat-info: %S" rep))))))
+
+;; TODO: currently we prepend the replacing count before the
+;; key-sequence that calls the command. Can we use direct
+;; modification of prefix-arg instead? Does it work in
+;; conjunction with `execute-kbd-macro'?
+(defun evil-execute-repeat-info-with-count (count repeat-info)
+ "Repeat the repeat-information REPEAT-INFO with the count of
+the first command replaced by COUNT. The count is replaced if
+and only if COUNT is non-nil."
+ (evil-save-repeat-info
+ (cond
+ ;; do nothing (zero repeating)
+ ((and count (zerop count)))
+ ;; replace count
+ (count
+ (let ((evil-repeat-count count)
+ done)
+ (while (and repeat-info
+ (arrayp (car repeat-info))
+ (not done))
+ (let* ((count-and-cmd (evil-extract-count (pop repeat-info))))
+ (push (vconcat (number-to-string count)
+ (nth 2 count-and-cmd)
+ (nth 3 count-and-cmd))
+ repeat-info)
+ (setq done t)))
+ (evil-execute-repeat-info repeat-info)))
+ ;; repeat with original count
+ (t (evil-execute-repeat-info repeat-info)))))
+
+;; Keep the compiler happy - this is a buffer local var
+(defvar evil--execute-normal-return-state)
+
+(evil-define-command evil-repeat (count &optional save-point)
+ "Repeat the last editing command with count replaced by COUNT.
+If SAVE-POINT is non-nil, do not move point."
+ :repeat ignore
+ :suppress-operator t
+ (interactive (list current-prefix-arg
+ (not evil-repeat-move-cursor)))
+ (cond
+ ((null evil-repeat-ring)
+ (error "Already executing repeat"))
+ (save-point
+ (save-excursion
+ (evil-repeat count)))
+ (t
+ (unwind-protect
+ (let ((evil-last-find-temp evil-last-find)
+ (confirm-kill-emacs t)
+ (kill-buffer-hook
+ (cons #'(lambda ()
+ (user-error "Cannot delete buffer in repeat command"))
+ kill-buffer-hook))
+ (undo-pointer buffer-undo-list))
+ (evil-with-single-undo
+ (setq evil-last-repeat (list (point) count undo-pointer))
+ (evil-execute-repeat-info-with-count
+ count (ring-ref evil-repeat-ring 0))
+ (setq evil-last-find evil-last-find-temp)))
+ (if (eq 'evil-execute-in-normal-state last-command)
+ (evil-change-state evil--execute-normal-return-state)
+ (evil-normal-state))))))
+
+;; TODO: the same issue concerning disabled undos as for `evil-paste-pop'
+(evil-define-command evil-repeat-pop (count &optional save-point)
+ "Replace the just repeated command with a previously executed command.
+Only allowed after `evil-repeat', `evil-repeat-pop' or
+`evil-repeat-pop-next'. Uses the same repeat count that
+was used for the first repeat.
+
+The COUNT argument inserts the COUNT-th previous kill.
+If COUNT is negative, this is a more recent kill."
+ :repeat nil
+ :suppress-operator t
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ (not evil-repeat-move-cursor)))
+ (cond
+ ((not (and (eq last-command #'evil-repeat)
+ evil-last-repeat))
+ (user-error "Previous command was not evil-repeat: %s" last-command))
+ (save-point
+ (save-excursion
+ (evil-repeat-pop count)))
+ (t
+ (unless (eq buffer-undo-list (nth 2 evil-last-repeat))
+ (evil-undo-pop))
+ (goto-char (car evil-last-repeat))
+ ;; rotate the repeat-ring
+ (while (> count 0)
+ (when evil-repeat-ring
+ (ring-insert-at-beginning evil-repeat-ring
+ (ring-remove evil-repeat-ring 0)))
+ (setq count (1- count)))
+ (while (< count 0)
+ (when evil-repeat-ring
+ (ring-insert evil-repeat-ring
+ (ring-remove evil-repeat-ring)))
+ (setq count (1+ count)))
+ (setq this-command #'evil-repeat)
+ (evil-repeat (cadr evil-last-repeat)))))
+
+(evil-define-command evil-repeat-pop-next (count &optional save-point)
+ "Same as `evil-repeat-pop', but with negative COUNT."
+ :repeat nil
+ :suppress-operator t
+ (interactive (list (prefix-numeric-value current-prefix-arg)
+ (not evil-repeat-move-cursor)))
+ (evil-repeat-pop (- count) save-point))
+
+(defun evil--read-key-sequence-advice (&rest _)
+ "Record `this-command-keys' before it is overwritten."
+ (when (and (evil-repeat-recording-p)
+ evil-recording-current-command)
+ (let ((repeat-type (evil--repeat-type this-command)))
+ (when (functionp repeat-type)
+ (funcall repeat-type 'pre-read-key-sequence)))))
+
+(advice-add 'read-key-sequence :before #'evil--read-key-sequence-advice)
+(advice-add 'read-key-sequence-vector :before #'evil--read-key-sequence-advice)
+
+(provide 'evil-repeat)
+
+;;; evil-repeat.el ends here
diff --git a/.config/emacs/lisp/evil/evil-search.el b/.config/emacs/lisp/evil/evil-search.el
new file mode 100644
index 0000000..c882a8e
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-search.el
@@ -0,0 +1,1249 @@
+;;; evil-search.el --- Search and substitute -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'evil-core)
+(require 'evil-common)
+(require 'evil-ex)
+
+(defun evil-select-search-module (option module)
+ "Change the search module according to MODULE.
+If MODULE is `isearch', then Emacs' isearch module is used.
+If MODULE is `evil-search', then Evil's own interactive
+search module is used."
+ (let ((search-functions
+ '(forward
+ backward
+ word-forward
+ word-backward
+ unbounded-word-forward
+ unbounded-word-backward
+ next
+ previous)))
+ (dolist (fun search-functions)
+ (let ((isearch (intern (format "evil-search-%s" fun)))
+ (evil-search (intern (format "evil-ex-search-%s" fun))))
+ (if (eq module 'isearch)
+ (substitute-key-definition
+ evil-search isearch evil-motion-state-map)
+ (substitute-key-definition
+ isearch evil-search evil-motion-state-map)))))
+ (set-default option module))
+
+;; this customization is here because it requires
+;; the knowledge of `evil-select-search-mode'
+(defcustom evil-search-module 'isearch
+ "The search module to be used. May be either `isearch', for
+Emacs' isearch module, or `evil-search', for Evil's own
+interactive search module. N.b. changing this will not affect keybindings.
+To swap out relevant keybindings, see `evil-select-search-module' function."
+ :type '(radio (const :tag "Emacs built-in isearch." :value isearch)
+ (const :tag "Evil interactive search." :value evil-search))
+ :group 'evil
+ :set #'evil-select-search-module
+ :initialize #'evil-custom-initialize-pending-reset)
+
+(defun evil-push-search-history (string forward)
+ "Push STRING into the appropriate search history (determined by FORWARD)."
+ (let ((var (if forward
+ 'evil-search-forward-history
+ 'evil-search-backward-history)))
+ (unless (equal string (car (symbol-value var)))
+ (push string (symbol-value var)))))
+
+(defun evil-search-incrementally (forward regexp-p)
+ "Search incrementally for user-entered text."
+ (let ((evil-search-prompt (evil-search-prompt forward))
+ (isearch-search-fun-function 'evil-isearch-function)
+ (point (point))
+ search-nonincremental-instead)
+ (setq isearch-forward forward)
+ (evil-save-echo-area
+ (evil-without-input-method-hooks
+ ;; set the input method locally rather than globally to ensure that
+ ;; isearch clears the input method when it's finished
+ (setq current-input-method evil-input-method)
+ (if forward
+ (isearch-forward regexp-p)
+ (isearch-backward regexp-p))
+ (evil-push-search-history isearch-string forward)
+ (setq current-input-method nil))
+ (when (/= (point) point)
+ ;; position the point at beginning of the match only if the call to
+ ;; `isearch' has really moved the point. `isearch' doesn't move the
+ ;; point only if "C-g" is hit twice to exit the search, in which case we
+ ;; shouldn't move the point either.
+ (when (and forward isearch-other-end)
+ (goto-char isearch-other-end))
+ (when (and (eq point (point))
+ (not (string= isearch-string "")))
+ (if forward
+ (isearch-repeat-forward)
+ (isearch-repeat-backward))
+ (isearch-exit)
+ (when (and forward isearch-other-end)
+ (goto-char isearch-other-end)))
+ (evil-flash-search-pattern
+ (evil-search-message isearch-string forward))))))
+
+(defun evil-flash-search-pattern (string &optional all)
+ "Flash last search matches for duration of `evil-flash-delay'.
+If ALL is non-nil, flash all matches. STRING is a message
+to display in the echo area."
+ (let ((lazy-highlight-initial-delay 0)
+ (isearch-search-fun-function 'evil-isearch-function)
+ (isearch-case-fold-search case-fold-search)
+ (disable #'(lambda (&optional _arg) (evil-flash-hook t))))
+ (when evil-flash-timer
+ (cancel-timer evil-flash-timer))
+ (unless (or (null string)
+ (string= string ""))
+ (evil-echo-area-save)
+ (evil-echo "%s" string)
+ (isearch-highlight (match-beginning 0) (match-end 0))
+ (when all
+ (setq isearch-lazy-highlight-wrapped nil
+ isearch-lazy-highlight-start (point)
+ isearch-lazy-highlight-end (point))
+ (isearch-lazy-highlight-new-loop)
+ (unless isearch-lazy-highlight-overlays
+ (isearch-lazy-highlight-update)))
+ (add-hook 'pre-command-hook #'evil-flash-hook nil t)
+ (add-hook 'evil-operator-state-exit-hook #'evil-flash-hook nil t)
+ (add-hook 'pre-command-hook #'evil-clean-isearch-overlays nil t)
+ (setq evil-flash-timer
+ (run-at-time evil-flash-delay nil disable)))))
+
+(defun evil-clean-isearch-overlays ()
+ "Clean isearch overlays unless `this-command' is search."
+ (remove-hook 'pre-command-hook #'evil-clean-isearch-overlays t)
+ (unless (memq this-command
+ '(evil-search-backward
+ evil-search-forward
+ evil-search-next
+ evil-search-previous
+ evil-search-word-backward
+ evil-search-word-forward))
+ (isearch-clean-overlays)))
+(put 'evil-clean-isearch-overlays 'permanent-local-hook t)
+
+(defun evil-flash-hook (&optional force)
+ "Disable hightlighting if `this-command' is not search.
+Disable anyway if FORCE is t."
+ (when (or force
+ ;; to avoid flicker, don't disable highlighting
+ ;; if the next command is also a search command
+ (not (memq this-command
+ '(evil-search-backward
+ evil-search-forward
+ evil-search-next
+ evil-search-previous
+ evil-search-word-backward
+ evil-search-word-forward))))
+ (evil-echo-area-restore)
+ (isearch-dehighlight)
+ (setq isearch-lazy-highlight-last-string nil)
+ (lazy-highlight-cleanup t)
+ (when evil-flash-timer
+ (cancel-timer evil-flash-timer)))
+ (remove-hook 'pre-command-hook #'evil-flash-hook t)
+ (remove-hook 'evil-operator-state-exit-hook #'evil-flash-hook t))
+(put 'evil-flash-hook 'permanent-local-hook t)
+
+(defun evil-search-with-predicate (search-fun pred string bound noerror count)
+ "Execute a search with a predicate function.
+SEARCH-FUN is a search function (e.g. `re-search-forward') and
+PREDICATE is a two-argument function satisfying the interface of
+`isearch-filter-predicate', or `nil'. STRING, BOUND, NOERROR and
+COUNT are passed unchanged to SEARCH-FUN. The first match
+satisfying the predicate (or `nil') is returned."
+ (catch 'done
+ (while t
+ (let ((result (funcall search-fun string bound noerror count)))
+ (cond
+ ((not result) (throw 'done nil))
+ ((not pred) (throw 'done result))
+ ((funcall pred (match-beginning 0) (match-end 0)) (throw 'done result)))))))
+
+(defun evil-search-function (&optional forward regexp-p wrap predicate)
+ "Return a search function.
+If FORWARD is nil, search backward, otherwise forward.
+If REGEXP-P is non-nil, the input is a regular expression.
+If WRAP is non-nil, the search wraps around the top or bottom
+of the buffer.
+If PREDICATE is non-nil, it must be a function accepting two
+arguments: the bounds of a match, returning non-nil if that match is
+acceptable."
+ `(lambda (string &optional bound noerror count)
+ (let ((start (point))
+ (search-fun ',(if regexp-p
+ (if forward
+ 're-search-forward
+ 're-search-backward)
+ (if forward
+ 'search-forward
+ 'search-backward)))
+ result)
+ (setq result (evil-search-with-predicate
+ search-fun ,predicate string
+ bound ,(if wrap t 'noerror) count))
+ (when (and ,wrap (null result))
+ (goto-char ,(if forward '(point-min) '(point-max)))
+ (unwind-protect
+ (setq result (evil-search-with-predicate
+ search-fun ,predicate string bound noerror count))
+ (unless result
+ (goto-char start))))
+ result)))
+
+(defun evil-isearch-function ()
+ "Return a search function for use with isearch.
+Based on `isearch-regexp' and `isearch-forward'."
+ (evil-search-function isearch-forward evil-regexp-search evil-search-wrap 'isearch-filter-predicate))
+
+(defun evil-search (string forward &optional regexp-p start)
+ "Search for STRING and highlight matches.
+If FORWARD is nil, search backward, otherwise forward.
+If REGEXP-P is non-nil, STRING is taken to be a regular expression.
+START is the position to search from; if unspecified, it is
+one more than the current position."
+ (when (and (stringp string)
+ (not (string= string "")))
+ (let* ((orig (point))
+ (start (or start
+ (if forward
+ (min (point-max) (1+ orig))
+ orig)))
+ (isearch-regexp regexp-p)
+ (isearch-forward forward)
+ (case-fold-search
+ (unless (and search-upper-case
+ (not (isearch-no-upper-case-p string nil)))
+ case-fold-search))
+ (search-func (evil-search-function
+ forward regexp-p evil-search-wrap 'isearch-filter-predicate)))
+ ;; no text properties, thank you very much
+ (set-text-properties 0 (length string) nil string)
+ ;; position to search from
+ (goto-char start)
+ (setq isearch-string string)
+ (isearch-update-ring string regexp-p)
+ (condition-case nil
+ (funcall search-func string)
+ (search-failed
+ (goto-char orig)
+ (user-error "\"%s\": %s not found"
+ string (if regexp-p "pattern" "string"))))
+ ;; always position point at the beginning of the match
+ (goto-char (match-beginning 0))
+ ;; determine message for echo area
+ (cond
+ ((and forward (< (point) start))
+ (when evil-search-wrap-ring-bell (ding))
+ (setq string "Search wrapped around BOTTOM of buffer"))
+ ((and (not forward) (> (point) start))
+ (when evil-search-wrap-ring-bell (ding))
+ (setq string "Search wrapped around TOP of buffer"))
+ (t
+ (setq string (evil-search-message string forward))))
+ (evil-flash-search-pattern string t))))
+
+(defun evil-search-word (forward unbounded symbol)
+ "Search for word near point.
+If FORWARD is nil, search backward, otherwise forward. If SYMBOL
+is non-nil then the functions searches for the symbol at point,
+otherwise for the word at point."
+ (let ((string (car regexp-search-ring)))
+ (setq isearch-forward forward)
+ (cond
+ ((and (memq last-command
+ '(evil-search-word-forward
+ evil-search-word-backward))
+ (stringp string)
+ (not (string= string "")))
+ (evil-search string forward t))
+ (t
+ (setq string (evil-find-thing forward (if symbol 'symbol 'evil-word)))
+ (cond
+ ((null string)
+ (user-error "No word under point"))
+ (unbounded
+ (setq string (regexp-quote string)))
+ (t
+ (setq string
+ (format (if symbol "\\_<%s\\_>" "\\<%s\\>")
+ (regexp-quote string)))))
+ (evil-push-search-history string forward)
+ (evil-search string forward t)))))
+
+(defun evil--find-thing (forward thing)
+ "Return a cons of THING near point as a string and its position.
+THING should be a symbol understood by `thing-at-point',
+e.g. `symbol' or `word'. If FORWARD is nil, search backward,
+otherwise forward. Returns nil if nothing is found."
+ (let ((move (if forward #'forward-char #'backward-char))
+ (end (if forward #'eobp #'bobp))
+ string)
+ (save-excursion
+ (setq string (thing-at-point thing))
+ ;; if there's nothing under point, go forwards
+ ;; (or backwards) to find it
+ (while (and (null string) (not (funcall end)))
+ (funcall move)
+ (setq string (thing-at-point thing)))
+ (when (stringp string)
+ (set-text-properties 0 (length string) nil string))
+ (when (> (length string) 0)
+ (cons string (point))))))
+
+(defun evil-find-thing (forward thing)
+ "Return a THING near point as a string.
+THING should be a symbol understood by `thing-at-point',
+e.g. `symbol' or `word'. If FORWARD is nil, search backward,
+otherwise forward. Returns nil if nothing is found."
+ (car (evil--find-thing forward thing)))
+
+(defun evil-find-word (forward)
+ "Return word near point as a string.
+If FORWARD is nil, search backward, otherwise forward. Returns
+nil if nothing is found."
+ (evil-find-thing forward 'word))
+
+(defun evil-find-symbol (forward)
+ "Return word near point as a string.
+If FORWARD is nil, search backward, otherwise forward. Returns
+nil if nothing is found."
+ (evil-find-thing forward 'symbol))
+
+(defun evil-search-prompt (forward)
+ "Return the search prompt for the given direction."
+ (if forward "/" "?"))
+
+(defun evil-search-message (string forward)
+ "Prefix STRING with the search prompt."
+ (format "%s%s" (evil-search-prompt forward) string))
+
+(advice-add 'isearch-message-prefix :around #'evil--use-search-prompt)
+(defun evil--use-search-prompt (orig-fun &rest args)
+ "Use `evil-search-prompt'."
+ (or evil-search-prompt
+ (apply orig-fun args)))
+
+(advice-add 'isearch-delete-char :around #'evil--exit-search-when-empty)
+(defun evil--exit-search-when-empty (orig-fun &rest args)
+ "Exit search if no search string."
+ (cond
+ ((and evil-search-prompt (string= isearch-string ""))
+ (let (search-nonincremental-instead)
+ (setq isearch-success nil)
+ (isearch-exit)))
+ (t (apply orig-fun args))))
+
+(advice-add 'isearch-lazy-highlight-search :around #'evil--without-search-wrap)
+(defun evil--without-search-wrap (orig-fun &rest args)
+ "Never wrap the search in this context."
+ (let (evil-search-wrap)
+ (apply orig-fun args)))
+
+;;; Ex search
+
+(defun evil-ex-regex-without-case (re)
+ "Return the regular expression without all occurrences of \\c and \\C."
+ (evil-transform-regexp re '((?c . "") (?C . ""))))
+
+(defun evil-ex-regex-case (re default-case)
+ "Return the case as implied by \\c or \\C in regular expression RE.
+If \\c appears anywhere in the pattern, the pattern is case
+insensitive. If \\C appears, the pattern is case sensitive.
+Only the first occurrence of \\c or \\C is used, all others are
+ignored. If neither \\c nor \\C appears in the pattern, the case
+specified by DEFAULT-CASE is used. DEFAULT-CASE should be either
+`sensitive', `insensitive' or `smart'. In the latter case, the pattern
+will be case-sensitive if and only if it contains an upper-case
+letter, otherwise it will be case-insensitive."
+ (cond
+ ((string-match "\\(?:^\\|[^\\\\]\\)\\(?:\\\\\\\\\\)*\\\\\\([cC]\\)" re)
+ (if (eq (aref (match-string 1 re) 0) ?c) 'insensitive 'sensitive))
+ ((eq default-case 'smart)
+ (if (isearch-no-upper-case-p re t) 'insensitive 'sensitive))
+ (t default-case)))
+
+;; a pattern
+(defun evil-ex-make-substitute-pattern (regexp flags)
+ "Create a PATTERN for substitution with FLAGS.
+This function respects the values of `evil-ex-substitute-case'
+and `evil-ex-substitute-global'."
+ (evil-ex-make-pattern
+ regexp
+ (cond ((memq ?i flags) 'insensitive)
+ ((memq ?I flags) 'sensitive)
+ ((not evil-ex-substitute-case) evil-ex-search-case)
+ (t evil-ex-substitute-case))
+ (if (memq ?g flags)
+ (not evil-ex-substitute-global)
+ evil-ex-substitute-global)))
+
+(defun evil-ex-make-search-pattern (regexp)
+ "Create a PATTERN for search.
+This function respects the values of `evil-ex-search-case'."
+ (evil-ex-make-pattern regexp evil-ex-search-case t))
+
+(defun evil-ex-make-pattern (regexp case whole-line)
+ "Create a new search pattern.
+REGEXP is the regular expression to be searched for. CASE should
+be either `sensitive', `insensitive' for case-sensitive and
+case-insensitive search respectively, or `smart'. In the latter case
+the pattern is smart-case, i.e. it is automatically sensitive of the
+pattern contains an upper case letter, otherwise it is insensitive.
+The input REGEXP is considered a Vim-style regular expression if
+`evil-ex-search-vim-style-regexp' is non-nil, in which case it is
+transformed to an Emacs style regular expression (i.e. certain
+backslash-codes are transformed. Otherwise REGEXP must be an Emacs
+style regular expression and is not transformed."
+ (let ((re (evil-ex-regex-without-case regexp))
+ (ignore-case (eq (evil-ex-regex-case regexp case) 'insensitive)))
+ ;; possibly transform regular expression from vim-style to
+ ;; Emacs-style.
+ (if (and evil-ex-search-vim-style-regexp
+ (not (or (string-prefix-p "\\_<" regexp)
+ (string-suffix-p "\\_>" regexp))))
+ (setq re (evil-transform-vim-style-regexp re))
+ ;; Even for Emacs regular expressions we translate certain
+ ;; whitespace sequences
+ (setq re (evil-transform-regexp re '((?t . "\t")
+ (?n . "\n")
+ (?r . "\r")))))
+ (list re ignore-case whole-line)))
+
+(defun evil-ex-pattern-regex (pattern)
+ "Return the regular expression of a search PATTERN."
+ (nth 0 pattern))
+
+(defun evil-ex-pattern-ignore-case (pattern)
+ "Return t if and only if PATTERN should ignore case."
+ (nth 1 pattern))
+
+(defun evil-ex-pattern-whole-line (pattern)
+ "Return t if and only if PATTERN should match all occurences of a line.
+Otherwise PATTERN matches only the first occurence."
+ (nth 2 pattern))
+
+;;; Highlight
+
+(cl-defstruct (evil-ex-hl (:type vector) (:constructor nil)
+ (:copier nil) (:predicate nil))
+ (name nil :read-only t) pattern
+ (face nil :read-only t) (window nil :read-only t)
+ (min nil :documentation "The minimal buffer position of the highlight.")
+ (max nil :documentation "The maximal buffer position of the highlight.")
+ (match-hook nil :read-only t) (update-hook nil :read-only t)
+ (overlays nil :documentation "The active overlays of the highlight."))
+
+(cl-defun evil-ex-make-hl
+ (name &key (face 'evil-ex-lazy-highlight) (win (selected-window))
+ min max match-hook update-hook)
+ "Create a new highlight object with name NAME and properties ARGS.
+The following properties are supported:
+:face The face to be used for the highlighting overlays.
+:win The window in which the highlighting should be shown.
+ Note that the highlight will be visible in all windows showing
+ the corresponding buffer, but only the matches visible in the
+ specified window will actually be highlighted. If :win is nil,
+ the matches in all windows will be highlighted.
+:min The minimal buffer position for highlighted matches.
+:max The maximal buffer position for highlighted matches.
+:match-hook A hook to be called once for each highlight.
+ The hook must take two arguments, the highlight and
+ the overlay for that highlight.
+:update-hook A hook called once after updating the highlighting
+ with two arguments, the highlight and a message string
+ describing the current match status."
+ (unless (symbolp name)
+ (user-error "Expected symbol as name of highlight"))
+ (when (assq name evil-ex-active-highlights-alist)
+ (evil-ex-delete-hl name))
+ (unless evil-ex-active-highlights-alist
+ (add-hook 'window-scroll-functions
+ #'evil-ex-hl-update-highlights-scroll nil t)
+ (add-hook 'window-size-change-functions
+ #'evil-ex-hl-update-highlights-resize nil))
+ (push (cons name (vector name
+ nil
+ face
+ win
+ min max
+ match-hook update-hook
+ nil))
+ evil-ex-active-highlights-alist))
+
+(defun evil-ex-delete-hl (name)
+ "Remove the highlighting object with a certain NAME."
+ (let ((hl (cdr (assq name evil-ex-active-highlights-alist))))
+ (when hl
+ (mapc #'delete-overlay (evil-ex-hl-overlays hl))
+ (setq evil-ex-active-highlights-alist
+ (assq-delete-all name evil-ex-active-highlights-alist))
+ (evil-ex-hl-update-highlights))
+ (unless evil-ex-active-highlights-alist
+ (remove-hook 'window-scroll-functions
+ #'evil-ex-hl-update-highlights-scroll t)
+ (remove-hook 'window-size-change-functions
+ #'evil-ex-hl-update-highlights-resize))))
+
+(defun evil-ex-hl-active-p (name)
+ "Whether the highlight with a certain NAME is active."
+ (and (assq name evil-ex-active-highlights-alist) t))
+
+(defun evil-ex-hl-change (name pattern)
+ "Set the regular expression of highlight NAME to PATTERN."
+ (let ((hl (cdr (assq name evil-ex-active-highlights-alist))))
+ (when hl
+ (setf (evil-ex-hl-pattern hl) pattern)
+ (evil-ex-hl-idle-update))))
+
+(defun evil-ex-hl-set-region (name beg end &optional _type)
+ "Set minimal and maximal position of highlight NAME to BEG and END."
+ (let ((hl (cdr (assq name evil-ex-active-highlights-alist))))
+ (when hl
+ (setf (evil-ex-hl-min hl) beg
+ (evil-ex-hl-max hl) end)
+ (evil-ex-hl-idle-update))))
+
+(defun evil-ex-hl-get-max (name)
+ "Return the maximal position of the highlight with name NAME."
+ (let ((hl (cdr (assq name evil-ex-active-highlights-alist))))
+ (and hl (evil-ex-hl-max hl))))
+
+(defun evil-ex-hl-update-highlights ()
+ "Update the overlays of all active highlights."
+ (dolist (hl (mapcar #'cdr evil-ex-active-highlights-alist))
+ (let* ((old-ovs (evil-ex-hl-overlays hl))
+ new-ovs
+ (pattern (evil-ex-hl-pattern hl))
+ (case-fold-search (evil-ex-pattern-ignore-case pattern))
+ (case-replace case-fold-search)
+ (face (evil-ex-hl-face hl))
+ (match-hook (evil-ex-hl-match-hook hl))
+ result)
+ (if pattern
+ ;; collect all visible ranges
+ (let (ranges sranges)
+ (dolist (win (if (eq evil-ex-interactive-search-highlight
+ 'all-windows)
+ (get-buffer-window-list (current-buffer) nil t)
+ (list (evil-ex-hl-window hl))))
+ (when (window-live-p win)
+ (let ((beg (max (window-start win)
+ (or (evil-ex-hl-min hl) (point-min))))
+ (end (min (window-end win)
+ (or (evil-ex-hl-max hl) (point-max)))))
+ (when (< beg end)
+ (push (cons beg end) ranges)))))
+ (setq ranges (sort ranges #'car-less-than-car))
+ (while ranges
+ (let ((r1 (pop ranges))
+ (r2 (pop ranges)))
+ (cond
+ ;; last range
+ ((null r2) (push r1 sranges))
+ ;; ranges overlap, union
+ ((>= (cdr r1) (car r2))
+ (push (cons (car r1)
+ (max (cdr r1) (cdr r2)))
+ ranges))
+ ;; ranges distinct
+ (t (push r1 sranges)
+ (push r2 ranges)))))
+
+ ;; run through all ranges
+ (condition-case lossage
+ (save-match-data
+ (dolist (r sranges)
+ (let ((beg (car r))
+ (end (cdr r)))
+ (save-excursion
+ (goto-char beg)
+ ;; set the overlays for the current highlight,
+ ;; reusing old overlays (if possible)
+ (while (and (not (eobp))
+ (evil-ex-search-find-next-pattern pattern)
+ (<= (match-end 0) end)
+ (not (and (= (match-beginning 0) end)
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (bolp)))))
+ (let ((ov (or (pop old-ovs) (make-overlay 0 0))))
+ (move-overlay ov (match-beginning 0) (match-end 0))
+ (overlay-put ov 'face face)
+ (overlay-put ov 'evil-ex-hl (evil-ex-hl-name hl))
+ (overlay-put ov 'priority 1000)
+ (push ov new-ovs)
+ (when match-hook (funcall match-hook hl ov)))
+ (cond
+ ((not (or (evil-ex-pattern-whole-line pattern)
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (search-forward "\n" (match-end 0) t))))
+ (forward-line))
+ ((= (match-beginning 0) (match-end 0))
+ (forward-char))
+ (t (goto-char (match-end 0))))))))
+ (mapc #'delete-overlay old-ovs)
+ (setf (evil-ex-hl-overlays hl) new-ovs)
+ (if (or (null pattern) new-ovs)
+ (setq result t)
+ ;; Maybe the match could just not be found somewhere else?
+ (save-excursion
+ (goto-char (or (evil-ex-hl-min hl) (point-min)))
+ (if (and (evil-ex-search-find-next-pattern pattern)
+ (< (match-end 0) (or (evil-ex-hl-max hl)
+ (point-max))))
+ (setq result (format "Match in line %d"
+ (line-number-at-pos
+ (match-beginning 0))))
+ (setq result "No match")))))
+
+ (invalid-regexp (setq result (cadr lossage)))
+ (search-failed (setq result (nth 2 lossage)))
+ (error (setq result (format "%s" (cadr lossage))))))
+ ;; no pattern, remove all highlights
+ (mapc #'delete-overlay old-ovs)
+ (setf (evil-ex-hl-overlays hl) new-ovs))
+ (when (evil-ex-hl-update-hook hl)
+ (funcall (evil-ex-hl-update-hook hl) hl result)))))
+
+(defun evil-ex-search-find-next-pattern (pattern &optional direction)
+ "Look for the next occurrence of PATTERN in a certain DIRECTION.
+Note that this function ignores the whole-line property of PATTERN."
+ (setq direction (or direction 'forward))
+ (let ((case-fold-search (evil-ex-pattern-ignore-case pattern)))
+ (cond
+ ((eq direction 'forward)
+ (re-search-forward (evil-ex-pattern-regex pattern) nil t))
+ ((eq direction 'backward)
+ (let* ((pnt (point))
+ (ret (re-search-backward (evil-ex-pattern-regex pattern) nil t))
+ (m (and ret (match-data))))
+ (if ret
+ (forward-char)
+ (goto-char (point-min)))
+ (let ((fwdret
+ (re-search-forward (evil-ex-pattern-regex pattern) nil t)))
+ (cond
+ ((and fwdret (< (match-beginning 0) pnt))
+ (setq ret fwdret)
+ (goto-char (match-beginning 0)))
+ (ret
+ (set-match-data m)
+ (goto-char (match-beginning 0)))
+ (t
+ (goto-char pnt)
+ ret)))))
+ (t (user-error "Unknown search direction `%s'" direction)))))
+
+(defun evil-ex-hl-idle-update ()
+ "Trigger the timer to update the highlights in the current buffer."
+ (when (and evil-ex-interactive-search-highlight
+ evil-ex-active-highlights-alist)
+ (when evil-ex-hl-update-timer
+ (cancel-timer evil-ex-hl-update-timer))
+ (setq evil-ex-hl-update-timer
+ (run-at-time evil-ex-hl-update-delay nil
+ #'evil-ex-hl-do-update-highlight
+ (current-buffer)))))
+
+(defun evil-ex-hl-do-update-highlight (&optional buffer)
+ "Timer function for updating the highlights."
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (evil-ex-hl-update-highlights)))
+ (setq evil-ex-hl-update-timer nil))
+
+(defun evil-ex-hl-update-highlights-scroll (win _beg)
+ "Update highlights after scrolling in some window."
+ (with-current-buffer (window-buffer win)
+ (evil-ex-hl-idle-update)))
+(put 'evil-ex-hl-update-highlights-scroll 'permanent-local-hook t)
+
+(defun evil-ex-hl-update-highlights-resize (frame)
+ "Update highlights after resizing a window."
+ (let ((buffers (delete-dups (mapcar #'window-buffer (window-list frame)))))
+ (dolist (buf buffers)
+ (with-current-buffer buf
+ (evil-ex-hl-idle-update)))))
+(put 'evil-ex-hl-update-highlights-resize 'permanent-local-hook t)
+
+;; interactive search
+(defun evil-ex-search-activate-highlight (pattern)
+ "Activate highlighting of the search pattern set to PATTERN.
+This function does nothing if `evil-ex-search-interactive' or
+`evil-ex-search-highlight-all' is nil. "
+ (when (and evil-ex-search-interactive evil-ex-search-highlight-all)
+ (with-current-buffer (or evil-ex-original-buffer (current-buffer))
+ (unless (evil-ex-hl-active-p 'evil-ex-search)
+ (evil-ex-make-hl 'evil-ex-search
+ :win (or (minibuffer-selected-window) (selected-window))))
+ (when pattern
+ (evil-ex-hl-change 'evil-ex-search pattern)))))
+
+(defun evil-ex-search (&optional count)
+ "Search forward or backward COUNT times for the current Ex search pattern.
+The search pattern is determined by `evil-ex-search-pattern', and the
+direction by `evil-ex-search-direction'."
+ (setq evil-ex-search-start-point (point)
+ evil-ex-last-was-search t
+ count (or count 1))
+ (let ((orig (point))
+ wrapped)
+ (dotimes (_ (or count 1))
+ (when (and (eq evil-ex-search-direction 'forward) (not (eobp)))
+ (forward-char)
+ ;; maybe skip end-of-line
+ (and (not evil-move-beyond-eol) (eolp) (not (eobp))
+ (forward-char)))
+ (let ((res (evil-ex-find-next nil nil (not evil-search-wrap))))
+ (cond
+ ((not res)
+ (goto-char orig)
+ (signal 'search-failed
+ (list (evil-ex-pattern-regex evil-ex-search-pattern))))
+ ((eq res 'wrapped) (setq wrapped t)))))
+ (if wrapped
+ (let (message-log-max)
+ (when evil-search-wrap-ring-bell (ding))
+ (message "Search wrapped")))
+ (goto-char (match-beginning 0))
+ (setq evil-ex-search-match-beg (match-beginning 0)
+ evil-ex-search-match-end (match-end 0))
+ (evil-ex-search-goto-offset evil-ex-search-offset)
+ (evil-ex-search-activate-highlight evil-ex-search-pattern)))
+
+(defun evil-ex-find-next (&optional pattern direction nowrap)
+ "Search for the next occurrence of the PATTERN in DIRECTION.
+PATTERN must be created using `evil-ex-make-pattern', DIRECTION is
+either `forward' or `backward'. If NOWRAP is non-nil, the search does
+not wrap at buffer boundaries. Furthermore this function only searches
+invisible text if `search-invisible' is t. If PATTERN is not specified
+the current global pattern `evil-ex-search-pattern' and if DIRECTION
+is not specified the current global direction
+`evil-ex-search-direction' is used. This function returns t if the
+search was successful, nil if it was unsuccessful and `wrapped' if the
+search was successful but wrapped around at buffer boundaries."
+ (setq pattern (or pattern evil-ex-search-pattern)
+ direction (or direction evil-ex-search-direction))
+ (unless (and pattern (evil-ex-pattern-regex pattern))
+ (signal 'search-failed (list "No search pattern")))
+ (catch 'done
+ (let (wrapped)
+ (while t
+ (if (evil-ex-search-find-next-pattern pattern direction)
+ (when (or (eq search-invisible t)
+ (not (isearch-range-invisible
+ (match-beginning 0) (match-end 0))))
+ ;; Successful search and not invisible
+ (throw 'done (if wrapped 'wrapped t)))
+ ;; Unsuccessful search
+ (if nowrap
+ (throw 'done nil)
+ (setq nowrap t
+ wrapped t)
+ (goto-char (if (eq direction 'forward)
+ (point-min)
+ (point-max)))))))))
+
+(defun evil-ex-search-update (pattern offset beg end)
+ "Update the highlighting for the search pattern.
+PATTERN is the search pattern and OFFSET the associated offset.
+BEG and END specify the current match."
+ (cond
+ ((and beg end)
+ ;; update overlay
+ (if evil-ex-search-overlay
+ (move-overlay evil-ex-search-overlay beg end)
+ (setq evil-ex-search-overlay (make-overlay beg end))
+ (overlay-put evil-ex-search-overlay 'priority 1001)
+ (overlay-put evil-ex-search-overlay 'face 'evil-ex-search))
+ ;; move point
+ (goto-char beg)
+ (evil-ex-search-goto-offset offset)
+ ;; update highlights
+ (when evil-ex-search-highlight-all
+ (evil-ex-hl-change 'evil-ex-search pattern)))
+ (t
+ ;; no match
+ (when evil-ex-search-overlay
+ ;; remove overlay
+ (delete-overlay evil-ex-search-overlay)
+ (setq evil-ex-search-overlay nil))
+ ;; no highlights
+ (when evil-ex-search-highlight-all
+ (evil-ex-hl-change 'evil-ex-search nil))
+ ;; and go to initial position
+ (goto-char evil-ex-search-start-point))))
+
+(defvar evil--ex-search-update-timer nil
+ "Timer to coalesce `evil-ex-search-update-pattern' calls after pattern changes.")
+
+(defun evil-ex-search-after-change-function (_beg _end _old-len)
+ (when evil--ex-search-update-timer
+ (cancel-timer evil--ex-search-update-timer))
+ (setq evil--ex-search-update-timer
+ (run-with-idle-timer 0 nil #'evil-ex-search-update-pattern)))
+
+(defun evil-ex-search-start-session ()
+ "Initialize Ex for interactive search."
+ (add-hook 'pre-command-hook #'evil-ex-remove-default nil t)
+ (and evil-ex-search-interactive evil-ex-search-incremental
+ (add-hook 'after-change-functions
+ #'evil-ex-search-after-change-function nil t))
+ (add-hook 'minibuffer-exit-hook #'evil-ex-search-stop-session nil t)
+ (add-hook 'mouse-leave-buffer-hook #'evil-ex-search-exit)
+ (evil-ex-search-activate-highlight nil))
+
+(defvar evil-ex-search-yank-point nil)
+
+(defun evil-ex-search-stop-session ()
+ "Stop interactive search."
+ (with-current-buffer evil-ex-original-buffer
+ ;; TODO: This is a bad fix to remove duplicates. The duplicates
+ ;; exist because `isearch-range-invisible' may add a single
+ ;; overlay multiple times if we are in an unlucky situation
+ ;; of overlapping overlays. This happens in our case because
+ ;; of the overlays that are used for (lazy) highlighting.
+ ;; Perhaps it would be better to disable those overlays
+ ;; temporarily before calling `isearch-range-invisible'.
+ (setq isearch-opened-overlays (delete-dups isearch-opened-overlays))
+ (isearch-clean-overlays))
+ (remove-hook 'mouse-leave-buffer-hook #'evil-ex-search-exit)
+ (when evil--ex-search-update-timer
+ (cancel-timer evil--ex-search-update-timer)
+ (setq evil--ex-search-update-timer nil))
+ (when evil-ex-search-overlay
+ (delete-overlay evil-ex-search-overlay)
+ (setq evil-ex-search-overlay nil))
+ (setq evil-ex-search-yank-point nil))
+
+(defun evil-ex-split-search-pattern (pattern direction)
+ "Split PATTERN in regexp, offset and next-pattern parts.
+Return a triplet (REGEXP OFFSET NEXT-SEARCH)."
+ (if (string-match
+ (if (eq direction 'forward)
+ "\\(?:^\\|[^\\\\]\\)\\(?:\\\\\\\\\\)*\\(/\\([^;]*\\)\\(?:;\\([/?].*\\)?\\)?\\)?$"
+ "\\(?:^\\|[^\\\\]\\)\\(?:\\\\\\\\\\)*\\(\\?\\([^;]*\\)\\(?:;\\([/?].*\\)?\\)?\\)?$")
+ pattern)
+ (list (substring pattern 0 (match-beginning 1))
+ (match-string 2 pattern)
+ (match-string 3 pattern))
+ (list pattern nil nil)))
+
+(defun evil-ex-search-full-pattern (string count direction)
+ "Search for a full search pattern STRING in DIRECTION.
+This function splits STRING into \"pattern/offset/;next-pattern\"
+parts and performs the search in DIRECTION which must be either
+`forward' or `backward'. The first search is repeated COUNT times. If
+the pattern part of STRING is empty, the last global pattern stored in
+`evil-ex-search-pattern' is used instead if in addition the offset
+part is nil (i.e. no pattern/offset separator), the last global offset
+stored in `evil-ex-search-offset' is used as offset. The current match
+data will correspond to the last successful match. This function
+returns a triplet (RESULT PATTERN OFFSET) where RESULT is one of
+
+ t the search was successful without wrapping
+ `wrap' the search was successful with wrapping
+ `empty-pattern' the last pattern was empty
+ nil the search was unsuccessful
+
+and PATTERN and OFFSET are the last pattern and offset this
+function searched for. Note that this function does not handle
+any error conditions."
+ (setq count (or count 1))
+ (catch 'done
+ (while t
+ (let* ((res (evil-ex-split-search-pattern string direction))
+ (pat (pop res))
+ (offset (pop res))
+ (next-pat (pop res))
+ (orig-pat pat)
+ new-dir repeat-last wrapped)
+ (if (> (length pat) 0)
+ (setq pat (evil-ex-make-search-pattern pat))
+ ;; use last pattern if no new pattern has been specified
+ (setq pat (or evil-ex-search-pattern
+ (throw 'done (list 'empty-pattern pat offset)))
+ offset (or offset evil-ex-search-offset)))
+ (while (> count 0)
+ (when (eq (or (evil-ex-find-next pat direction
+ (not evil-search-wrap))
+ (throw 'done (list nil pat offset)))
+ 'wrapped)
+ (setq wrapped t))
+ (setq count (1- count)))
+ (cond
+ ;; no next pattern, search complete
+ ((zerop (length next-pat))
+ (evil-ex-search-goto-offset offset)
+ (throw 'done (list (if wrapped 'wrap t) pat offset)))
+ ;; single \"?\" or \"/\" means repeat last pattern and finish
+ ((= 1 (length next-pat))
+ (evil-ex-search-goto-offset offset)
+ (setq new-dir (if (string= "/" next-pat) 'forward 'backward)
+ count (if (eq direction new-dir) 1 2)
+ string orig-pat
+ direction new-dir))
+ ;; next non-empty pattern, next search iteration
+ (t (evil-ex-search-goto-offset offset)
+ (setq new-dir (if (= (aref next-pat 0) ?/) 'forward 'backward)
+ repeat-last (when (<= 2 (length next-pat))
+ (member (substring next-pat 0 2) '("//" "??")))
+ count (if (or (eq direction new-dir) (not repeat-last)) 1 2)
+ string (if repeat-last
+ (concat orig-pat (substring next-pat 1))
+ (substring next-pat 1))
+ direction new-dir)))))))
+
+(defun evil-ex-search-update-pattern ()
+ "Update the current search pattern."
+ (let ((pattern-string (minibuffer-contents-no-properties))
+ message)
+ (with-selected-window (minibuffer-selected-window)
+ (goto-char (1+ evil-ex-search-start-point))
+ (condition-case err
+ (cl-destructuring-bind (success pattern offset)
+ (evil-ex-search-full-pattern pattern-string
+ (or evil-ex-search-count 1)
+ evil-ex-search-direction)
+ (cond
+ ((eq success 'wrap)
+ (evil-ex-search-update pattern offset
+ (match-beginning 0) (match-end 0))
+ (setq message "Wrapped"))
+ ((eq success 'empty-pattern)
+ (evil-ex-search-update nil nil nil nil))
+ (success
+ (evil-ex-search-update pattern offset
+ (match-beginning 0) (match-end 0)))
+ (t (evil-ex-search-update nil nil nil nil)
+ (setq message "Search failed"))))
+ (invalid-regexp
+ (evil-ex-search-update nil nil nil nil)
+ (setq message (cadr err)))
+ (error
+ (evil-ex-search-update nil nil nil nil)
+ (setq message (error-message-string err)))))
+ (when message (evil-ex-echo "%s" message))))
+
+(defun evil-ex-search-exit ()
+ "Exit interactive search, keeping lazy highlighting active."
+ (interactive)
+ (exit-minibuffer))
+
+(defun evil-ex-search-abort ()
+ "Abort interactive search, disabling lazy highlighting."
+ (interactive)
+ (evil-ex-delete-hl 'evil-ex-search)
+ (abort-recursive-edit))
+
+(defun evil-ex-search-goto-offset (offset)
+ "Move point according to search OFFSET and set `evil-this-type' accordingly.
+This function assumes that the current match data represents the
+current search result."
+ (unless (zerop (length offset))
+ (let ((beg (match-beginning 0))
+ (end (match-end 0)))
+ (save-match-data
+ (unless (string-match
+ "^\\([esb]\\)?\\(\\([-+]\\)?\\([0-9]*\\)\\)$"
+ offset)
+ (user-error "Invalid search offset: %s" offset))
+ (let ((count (if (= (match-beginning 4) (match-end 4))
+ (cond
+ ((not (match-beginning 3)) 0)
+ ((= (aref offset (match-beginning 3)) ?+) +1)
+ (t -1))
+ (string-to-number (match-string 2 offset)))))
+ (cond
+ ((not (match-beginning 1))
+ (setq evil-this-type 'line)
+ (forward-line count))
+ ((= (aref offset (match-beginning 1)) ?e)
+ (goto-char (+ end count -1))
+ (setq evil-this-type 'inclusive))
+ ((memq (aref offset (match-beginning 1)) '(?s ?b))
+ (goto-char (+ beg count))
+ (setq evil-this-type 'inclusive))))))))
+
+(defun evil-ex-start-search (direction count)
+ "Start a new search in a certain DIRECTION."
+ (setq evil-ex-search-count count
+ evil-ex-search-direction direction
+ evil-ex-search-start-point (point)
+ evil-ex-last-was-search t)
+ ;; store buffer and window where the search started
+ (let* ((evil-ex-original-buffer (current-buffer))
+ ;; read the search string
+ (minibuffer-local-map evil-ex-search-keymap)
+ (search-string
+ (condition-case err
+ (minibuffer-with-setup-hook #'evil-ex-search-start-session
+ (read-string
+ (if (eq evil-ex-search-direction 'forward) "/" "?")
+ (when evil-ex-search-history
+ (propertize (car evil-ex-search-history) 'face 'shadow))
+ 'evil-ex-search-history))
+ (quit
+ (evil-ex-delete-hl 'evil-ex-search)
+ (goto-char evil-ex-search-start-point)
+ (signal (car err) (cdr err))))))
+ ;; pattern entered successful
+ (goto-char (if (eq evil-ex-search-direction 'forward)
+ (1+ evil-ex-search-start-point)
+ (1- evil-ex-search-start-point)))
+ (cl-destructuring-bind (success pattern offset)
+ (evil-ex-search-full-pattern search-string
+ evil-ex-search-count
+ evil-ex-search-direction)
+ (setq evil-ex-search-pattern pattern
+ evil-ex-search-offset offset)
+ (cond
+ ((memq success '(t wrap))
+ (goto-char (match-beginning 0))
+ (setq evil-ex-search-match-beg (match-beginning 0)
+ evil-ex-search-match-end (match-end 0))
+ (evil-ex-search-goto-offset offset)
+ (evil-push-search-history search-string (eq direction 'forward))
+ (if evil-ex-search-incremental
+ (unless evil-ex-search-persistent-highlight
+ (evil-ex-delete-hl 'evil-ex-search))
+ (when evil-ex-search-highlight-all
+ (evil-ex-search-activate-highlight pattern))))
+ (t
+ (goto-char evil-ex-search-start-point)
+ (evil-ex-delete-hl 'evil-ex-search)
+ (signal 'search-failed (list search-string)))))))
+
+(declare-function evil-ex-search-next "evil-commands")
+(defun evil-ex-start-word-search (unbounded direction count &optional symbol)
+ "Search for the symbol under point.
+The search matches the COUNT-th occurrence of the word. If the
+UNBOUNDED argument is nil, the search matches only at symbol
+boundaries, otherwise it matches anywhere. The DIRECTION
+argument should be either `forward' or `backward', determining
+the search direction. If SYMBOL is non-nil then the functions
+searches for the symbol at point, otherwise for the word at
+point."
+ (let* ((string (or (evil-find-thing (eq direction 'forward)
+ (if symbol 'symbol 'word))
+ (user-error "No word under point")))
+ (regex (if unbounded
+ (regexp-quote string)
+ (format (if symbol "\\_<%s\\_>" "\\<%s\\>")
+ (regexp-quote string)))))
+ (setq evil-ex-search-count count
+ evil-ex-search-direction direction
+ evil-ex-search-pattern
+ (let (evil-ex-search-vim-style-regexp)
+ (evil-ex-make-search-pattern regex))
+ evil-ex-search-offset nil
+ evil-ex-last-was-search t)
+ ;; update search history unless this pattern equals the
+ ;; previous pattern
+ (unless (equal regex (car evil-ex-search-history))
+ (push regex evil-ex-search-history))
+ (evil-push-search-history regex (eq direction 'forward)))
+ (evil-ex-delete-hl 'evil-ex-search)
+ (evil-ex-search-next count))
+
+;; substitute
+(evil-ex-define-argument-type substitution
+ "A substitution pattern argument /pattern/replacement/flags.
+This handler highlights the pattern of the current substitution."
+ :runner
+ (lambda (flag &optional arg)
+ (with-current-buffer evil-ex-original-buffer
+ (cond
+ ((eq flag 'start)
+ (evil-ex-make-hl
+ 'evil-ex-substitute
+ :face 'evil-ex-substitute-matches
+ :win (minibuffer-selected-window)
+ :update-hook #'evil-ex-pattern-update-ex-info
+ :match-hook (and evil-ex-substitute-interactive-replace
+ #'evil-ex-pattern-update-replacement))
+ (setq flag 'update))
+ ((eq flag 'stop)
+ (evil-ex-delete-hl 'evil-ex-substitute)))
+
+ (when (and (eq flag 'update)
+ evil-ex-substitute-highlight-all
+ (> (length arg) 0))
+ (condition-case err
+ (cl-destructuring-bind (pattern replacement _flags)
+ (evil-ex-get-substitute-info (or arg "") t)
+ (evil-ex-hl-change 'evil-ex-substitute pattern)
+ (setq evil-ex-substitute-current-replacement replacement)
+ (cl-destructuring-bind (beg end &rest)
+ (if evil-ex-range
+ (evil-expand-range evil-ex-range t)
+ (evil-range (line-beginning-position) (line-end-position)
+ 'line :expanded t))
+ (evil-ex-hl-set-region 'evil-ex-substitute beg end)))
+ (end-of-file (evil-ex-echo "Incomplete replacement"))
+ (user-error (evil-ex-echo (error-message-string err))))))))
+
+(defun evil-ex-pattern-update-ex-info (_hl result)
+ "Update the Ex info string."
+ (when (stringp result)
+ (evil-ex-echo "%s" result)))
+
+(defun evil-ex-pattern-update-replacement (_hl overlay)
+ "Update the replacement display."
+ (let ((repl (if evil-ex-substitute-current-replacement
+ (evil-match-substitute-replacement
+ evil-ex-substitute-current-replacement
+ (not case-replace))
+ "")))
+ (put-text-property 0 (length repl)
+ 'face 'evil-ex-substitute-replacement
+ repl)
+ (overlay-put overlay 'after-string repl)))
+
+(defun evil-ex-parse-global (string)
+ "Parse STRING as a global argument."
+ (let* ((pattern (nth 0 (evil-delimited-arguments string 2)))
+ (command (and pattern
+ (>= (- (length string) (length pattern)) 2)
+ (substring string (+ (length pattern) 2)))))
+ ;; use last pattern if none given
+ (when (zerop (length pattern))
+ (setq pattern
+ (cond
+ ((and (eq evil-search-module 'evil-search) evil-ex-search-pattern)
+ (evil-ex-pattern-regex evil-ex-search-pattern))
+ ((and (eq evil-search-module 'isearch) (not (zerop (length isearch-string))))
+ isearch-string)
+ (t (user-error "No previous pattern")))))
+ (list pattern command)))
+
+(defun evil-ex-get-substitute-info (string &optional implicit-r)
+ "Return the substitution info of :substitute argument STRING.
+The result is a triplet \(PATTERN REPLACEMENT FLAGS). PATTERN is an
+Ex-pattern (see `evil-ex-make-pattern') and REPLACEMENT is a compiled
+replacement expression (see `evil-compile-replacement'). The
+information returned is the actual substitution information w.r.t. to
+special situations like empty patterns or repetition of previous
+substitution commands. If IMPLICIT-R is non-nil, then the \"r\" flag
+is assumed, i.e. in case of an empty pattern the last search pattern
+is used. It is meant for :substitute commands with arguments."
+ (let (pattern replacement flags using-prev-pattern)
+ (cond
+ ((or (string= string "") (string-match-p "\\`[a-zA-Z]" string))
+ ;; No pattern, since it starts with a letter which cannot be a
+ ;; separator: Repeat last substitute.
+ (setq replacement evil-ex-substitute-replacement)
+ ;; flags are everything that is not whitespace
+ (when (string-match "[^[:space:]]+" string)
+ (setq flags (match-string 0 string))))
+ (t (let ((args (evil-delimited-arguments string 3)))
+ (setq pattern (pop args)
+ replacement (pop args)
+ flags (pop args))
+ ;; if replacment equals "~" use previous replacement
+ (setq replacement (if (equal replacement "~")
+ evil-ex-substitute-replacement
+ (evil-compile-replacement replacement)))
+ ;; append implicit "r" flag if required
+ (when (and implicit-r (not (memq ?r (append flags nil))))
+ (setq flags (concat flags "r"))))))
+ ;; if flags equals "&" add previous flags
+ (setq flags
+ (if (and (> (length flags) 0) (= (aref flags 0) ?&))
+ (append (substring flags 1) evil-ex-substitute-flags)
+ (append flags nil)))
+ ;; if no pattern, use previous pattern, either search or
+ ;; substitute pattern depending on `evil-ex-last-was-search' and
+ ;; the r flag
+ (when (zerop (length pattern))
+ (setq pattern
+ (if (eq evil-search-module 'evil-search)
+ (if (and evil-ex-last-was-search (memq ?r flags))
+ (and evil-ex-search-pattern
+ (setq using-prev-pattern t)
+ (evil-ex-pattern-regex evil-ex-search-pattern))
+ (and evil-ex-substitute-pattern
+ (setq using-prev-pattern t)
+ (evil-ex-pattern-regex evil-ex-substitute-pattern)))
+ (if (eq case-fold-search t)
+ isearch-string
+ (concat isearch-string "\\C")))
+ flags (remq ?r flags)))
+ (when (and using-prev-pattern
+ (not (evil-ex-pattern-ignore-case evil-ex-search-pattern)))
+ (setq pattern (concat pattern "\\C")))
+ ;; generate pattern
+ (when pattern
+ ;; Disable vim-style regexp conversion if using a previous pattern, because
+ ;; this conversion will already have been done before storing it
+ (let ((evil-ex-search-vim-style-regexp (and evil-ex-search-vim-style-regexp
+ (not using-prev-pattern))))
+ (setq pattern (evil-ex-make-substitute-pattern pattern flags))))
+ (list pattern replacement flags)))
+
+(defun evil-ex-nohighlight ()
+ "Disable the active search highlightings."
+ (interactive)
+ (evil-ex-delete-hl 'evil-ex-substitute)
+ (evil-ex-delete-hl 'evil-ex-search))
+
+(defun evil-search-yank-word ()
+ "Pull next word from buffer into search string."
+ (interactive)
+ (let ((minibuf-content (minibuffer-contents-no-properties))
+ (word "") start)
+ (with-current-buffer evil-ex-original-buffer
+ ;; Start to initial point if C-w have never been hit.
+ (unless evil-ex-search-yank-point
+ (if (string= "" minibuf-content)
+ (setq evil-ex-search-yank-point evil-ex-search-start-point)
+ (setq evil-ex-search-yank-point (point))))
+ (save-excursion
+ (goto-char evil-ex-search-yank-point)
+ (setq start (point))
+ (when (looking-at-p (regexp-quote minibuf-content))
+ (forward-char (length minibuf-content))
+ (setq start (point))
+ (forward-word))
+ (setq word (buffer-substring-no-properties start (point)))))
+ (and (eq evil-ex-search-case 'smart)
+ (let (case-fold-search)
+ (not (string-match-p "[A-Z]" minibuf-content)))
+ (setq word (downcase word)))
+ (insert word)))
+
+(provide 'evil-search)
+
+;;; evil-search.el ends here
diff --git a/.config/emacs/lisp/evil/evil-states.el b/.config/emacs/lisp/evil/evil-states.el
new file mode 100644
index 0000000..499154e
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-states.el
@@ -0,0 +1,930 @@
+;;; evil-states.el --- States -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'evil-core)
+
+;;; Normal state
+
+(evil-define-state normal
+ "Normal state.
+AKA \"Command\" state."
+ :tag " <N> "
+ :enable (motion)
+ (cond
+ ((evil-normal-state-p)
+ (overwrite-mode -1)
+ (add-hook 'post-command-hook #'evil-normal-post-command nil t))
+ (t
+ (remove-hook 'post-command-hook #'evil-normal-post-command t))))
+
+(defun evil-normal-post-command (&optional command)
+ "Reset command loop variables in Normal state.
+Also prevent point from reaching the end of the line.
+If the region is activated, enter Visual state."
+ (unless (null this-command)
+ (setq command (or command this-command))
+ (when (evil-normal-state-p)
+ (setq evil-this-type nil
+ evil-this-operator nil
+ evil-this-motion nil
+ evil-this-motion-count nil
+ evil-inhibit-operator nil
+ evil-inhibit-operator-value nil)
+ (unless (memq command '(evil-use-register
+ digit-argument
+ negative-argument
+ universal-argument
+ universal-argument-minus
+ universal-argument-more
+ universal-argument-other-key))
+ (setq evil-this-register nil))
+ (evil-adjust-cursor))))
+(put 'evil-normal-post-command 'permanent-local-hook t)
+
+;;; Insert state
+
+(defun evil-maybe-remove-spaces (&optional do-remove)
+ "Remove space from newly opened empty line.
+This function removes (indentation) spaces that have been
+inserted by opening a new empty line. The behavior depends on the
+variable `evil-maybe-remove-spaces'. If this variable is nil the
+function does nothing. Otherwise the behavior depends on
+DO-REMOVE. If DO-REMOVE is non-nil the spaces are
+removed. Otherwise `evil-maybe-remove-spaces' is set to nil
+unless the last command opened yet another new line.
+
+This function should be added as a post-command-hook to track
+commands opening a new line."
+ (cond
+ ((not evil-maybe-remove-spaces)
+ (remove-hook 'post-command-hook #'evil-maybe-remove-spaces))
+ (do-remove
+ (when (save-excursion
+ (beginning-of-line)
+ (looking-at "^\\s-*$"))
+ (delete-region (line-beginning-position)
+ (line-end-position)))
+ (setq evil-maybe-remove-spaces nil)
+ (remove-hook 'post-command-hook #'evil-maybe-remove-spaces))
+ ((not (memq this-command
+ '(evil-open-above
+ evil-open-below
+ evil-append
+ evil-append-line
+ evil-change-whole-line
+ newline
+ newline-and-indent
+ indent-and-newline)))
+ (setq evil-maybe-remove-spaces nil)
+ (remove-hook 'post-command-hook #'evil-maybe-remove-spaces))))
+
+(evil-define-state insert
+ "Insert state."
+ :tag " <I> "
+ :cursor (bar . 2)
+ :message "-- INSERT --"
+ :entry-hook (evil-start-track-last-insertion)
+ :exit-hook (evil-cleanup-insert-state evil-stop-track-last-insertion)
+ :input-method t
+ (cond
+ ((evil-insert-state-p)
+ (add-hook 'post-command-hook #'evil-maybe-remove-spaces)
+ (add-hook 'pre-command-hook #'evil-insert-repeat-hook)
+ (setq evil-maybe-remove-spaces t)
+ (unless (eq evil-want-fine-undo t)
+ (evil-start-undo-step)))
+ (t
+ (remove-hook 'post-command-hook #'evil-maybe-remove-spaces)
+ (remove-hook 'pre-command-hook #'evil-insert-repeat-hook)
+ (evil-maybe-remove-spaces t)
+ (setq evil-insert-repeat-info evil-repeat-info)
+ (evil-set-marker ?^ nil t)
+ (unless (eq evil-want-fine-undo t)
+ (evil-end-undo-step))
+ (when (or (evil-normal-state-p evil-next-state)
+ (evil-motion-state-p evil-next-state))
+ (evil-move-cursor-back
+ (and (eolp) (not evil-move-beyond-eol)))))))
+
+(defun evil-insert-repeat-hook ()
+ "Record insertion keys in `evil-insert-repeat-info'."
+ (setq evil-insert-repeat-info (last evil-repeat-info))
+ (remove-hook 'pre-command-hook #'evil-insert-repeat-hook))
+(put 'evil-insert-repeat-hook 'permanent-local-hook t)
+
+(eval-when-compile
+ ;; TODO remove this once support for emacs 26 is dropped
+ (unless (fboundp 'combine-change-calls)
+ (defmacro combine-change-calls (_beg _end &rest body) `(progn ,@body))))
+(declare-function evil-execute-repeat-info "evil-repeat")
+(defun evil-cleanup-insert-state ()
+ "Called when Insert or Replace state is about to be exited.
+Handles the repeat-count of the insertion command."
+ (when evil-insert-count
+ (let (pre-command-hook post-command-hook)
+ (dotimes (_ (1- evil-insert-count))
+ (when evil-insert-lines
+ (evil-insert-newline-below)
+ (when evil-auto-indent
+ (indent-according-to-mode)))
+ (evil-execute-repeat-info (cdr evil-insert-repeat-info)))))
+ (when evil-insert-vcount
+ (let ((buffer-invisibility-spec
+ (if (listp buffer-invisibility-spec)
+ ;; make all lines hidden by hideshow temporarily visible
+ (cl-remove-if (lambda (x) (eq (or (car-safe x) x) 'hs))
+ buffer-invisibility-spec)
+ buffer-invisibility-spec)))
+ (cl-destructuring-bind (line col vcount) evil-insert-vcount
+ (save-excursion
+ (combine-change-calls ; For performance
+ (progn (goto-char (point-min))
+ (line-beginning-position line))
+ (line-end-position (+ line vcount -1))
+ (let (pre-command-hook post-command-hook) ; For performance
+ (dotimes (v (1- vcount))
+ (goto-char (point-min))
+ (forward-line (+ line v))
+ (when (or (not evil-insert-skip-empty-lines)
+ (not (integerp col))
+ (save-excursion
+ (evil-move-end-of-line)
+ (>= (current-column) col)))
+ (if (integerp col)
+ (move-to-column col t)
+ (funcall col))
+ (dotimes (_ (or evil-insert-count 1))
+ (evil-execute-repeat-info (cdr evil-insert-repeat-info)))))))))))
+ (and evil-want-fine-undo (evil-end-undo-step)))
+
+;;; Visual state
+
+;; Visual selections are implemented in terms of types, and are
+;; compatible with the Emacs region. This is achieved by "translating"
+;; the region to the selected text right before a command is executed.
+;; If the command is a motion, the translation is postponed until a
+;; non-motion command is invoked (distinguished by the :keep-visual
+;; command property).
+;;
+;; Visual state activates the region, enabling Transient Mark mode if
+;; not already enabled. This is only temporay: if Transient Mark mode
+;; was disabled before entering Visual state, it is disabled when
+;; exiting Visual state. This allows Visual state to harness the
+;; "transient" behavior of many commands without overriding the user's
+;; preferences in other states.
+
+(defmacro evil-define-visual-selection (selection doc &rest body)
+ "Define a Visual selection SELECTION.
+Creates a command evil-visual-SELECTION for enabling the selection.
+DOC is the function's documentation string. The following keywords
+may be specified in BODY:
+
+:message STRING Status message when enabling the selection.
+:type TYPE Type to use (defaults to SELECTION).
+
+Following the keywords is optional code which is executed each time
+the selection is enabled.
+
+\(fn SELECTION DOC [[KEY VAL]...] BODY...)"
+ (declare (indent defun)
+ (doc-string 2)
+ (debug (&define name stringp
+ [&rest keywordp sexp]
+ def-body)))
+ (let* ((name (intern (format "evil-visual-%s" selection)))
+ (message (intern (format "%s-message" name)))
+ (tagvar (intern (format "%s-tag" name)))
+ (type selection)
+ (tag " <V> ")
+ arg key string)
+ ;; collect keywords
+ (while (keywordp (car-safe body))
+ (setq key (pop body)
+ arg (pop body))
+ (cond
+ ((eq key :message)
+ (setq string arg))
+ ((eq key :type)
+ (setq type arg))
+ ((eq key :tag)
+ (setq tag arg))))
+ ;; macro expansion
+ `(progn
+ (add-to-list 'evil-visual-alist (cons ',selection ',name))
+ (defvar ,name ',type ,(format "*%s" doc))
+ (defvar ,message ,string ,doc)
+ (defvar ,tagvar ,tag ,doc)
+ (evil-define-command ,name (&optional mark point type message)
+ ,@(when doc `(,doc))
+ :keep-visual t
+ :repeat nil
+ (interactive
+ (list nil nil
+ (if (and (evil-visual-state-p)
+ (eq evil-visual-selection ',selection))
+ 'exit ,name) t))
+ (setq evil--region-from-mouse nil)
+ (if (eq type 'exit)
+ (evil-exit-visual-state)
+ (setq type (or type ,name)
+ evil-visual-selection ',selection)
+ (evil-visual-make-region mark point type message)
+ ,@body))
+ ',selection)))
+
+(evil-define-visual-selection char
+ "Characterwise selection."
+ :type inclusive
+ :message "-- VISUAL --"
+ :tag " <V> ")
+
+(evil-define-visual-selection line
+ "Linewise selection."
+ :message "-- VISUAL LINE --"
+ :tag " <Vl> ")
+
+(evil-define-visual-selection screen-line
+ "Linewise selection in `visual-line-mode'."
+ :message "-- SCREEN LINE --"
+ :tag " <Vs> ")
+
+(evil-define-visual-selection block
+ "Blockwise selection."
+ :message "-- VISUAL BLOCK --"
+ :tag " <Vb> "
+ (evil-transient-mark -1)
+ ;; refresh the :corner property
+ (setq evil-visual-properties
+ (plist-put evil-visual-properties :corner
+ (evil-visual-block-corner))))
+
+(evil-define-state visual
+ "Visual state."
+ :tag 'evil-visual-tag
+ :enable (motion normal)
+ :message 'evil-visual-message
+ (cond
+ ((evil-visual-state-p)
+ (evil-save-transient-mark-mode)
+ (setq select-active-regions nil)
+ (cond
+ ((region-active-p)
+ (if (< (evil-visual-direction) 0)
+ (evil-visual-select (region-beginning) (region-end)
+ evil-visual-char
+ (evil-visual-direction))
+ (evil-visual-make-selection (mark t) (point)
+ evil-visual-char))
+ (evil-visual-highlight))
+ (t
+ (evil-visual-make-region (point) (point) evil-visual-char)))
+ (add-hook 'pre-command-hook #'evil-visual-pre-command nil t)
+ (add-hook 'post-command-hook #'evil-visual-post-command nil t)
+ (add-hook 'deactivate-mark-hook #'evil-visual-deactivate-hook nil t))
+ (t
+ ;; Postpone deactivation of region if next state is Insert.
+ ;; This gives certain insertion commands (auto-pairing characters,
+ ;; for example) an opportunity to access the region.
+ (if (and (eq evil-next-state 'insert)
+ (eq evil-visual-selection 'char))
+ (add-hook 'evil-normal-state-entry-hook
+ #'evil-visual-deactivate-hook nil t)
+ (evil-visual-deactivate-hook))
+ (setq evil-visual-region-expanded nil)
+ (remove-hook 'pre-command-hook #'evil-visual-pre-command t)
+ (remove-hook 'post-command-hook #'evil-visual-post-command t)
+ (remove-hook 'deactivate-mark-hook #'evil-visual-deactivate-hook t)
+ (evil-visual-highlight -1))))
+
+(defun evil-visual-pre-command (&optional command)
+ "Run before each COMMAND in Visual state.
+Expand the region to the selection unless COMMAND is a motion."
+ (when (evil-visual-state-p)
+ (setq command (or command this-command))
+ (if (and evil-transient-mouse-selection
+ evil--region-from-mouse
+ (not (rassq command evil-visual-alist)))
+ (progn (setq evil--region-from-mouse nil)
+ (evil-exit-visual-state))
+ (when (and evil-transient-mouse-selection
+ evil--region-from-mouse
+ (rassq command evil-visual-alist))
+ (setq evil-visual-selection nil ;; maintain visual state
+ evil--region-from-mouse nil))
+ (when evil-visual-x-select-timer
+ (cancel-timer evil-visual-x-select-timer))
+ (unless (evil-get-command-property command :keep-visual)
+ (evil-visual-update-x-selection)
+ (evil-visual-expand-region
+ ;; exclude final newline from linewise selection
+ ;; unless the command has real need of it
+ (and (eq (evil-visual-type) 'line)
+ (evil-get-command-property command :exclude-newline)))))))
+
+(put 'evil-visual-pre-command 'permanent-local-hook t)
+
+(defun evil-visual-post-command (&optional command)
+ "Run after each COMMAND in Visual state.
+If COMMAND is a motion, refresh the selection;
+otherwise exit Visual state."
+ (when (evil-visual-state-p)
+ (setq command (or command this-command))
+ (if (or quit-flag
+ (memq command '(keyboard-quit keyboard-escape-quit))
+ ;; Is `mark-active' nil for an unexpanded region?
+ deactivate-mark
+ (and (not evil-visual-region-expanded)
+ (not (region-active-p))
+ (not (eq evil-visual-selection 'block))
+ transient-mark-mode))
+ (progn
+ (evil-exit-visual-state)
+ (evil-adjust-cursor))
+ (if evil-visual-region-expanded
+ (evil-visual-contract-region)
+ (evil-visual-refresh))
+ (setq evil-visual-x-select-timer
+ (run-with-idle-timer evil-visual-x-select-timeout nil
+ #'evil-visual-update-x-selection
+ (current-buffer)))
+ (evil-visual-highlight))))
+(put 'evil-visual-post-command 'permanent-local-hook t)
+
+(defun evil-visual-update-x-selection (&optional buffer)
+ "Update the X selection with the current visual region of BUFFER."
+ (let ((buf (or buffer (current-buffer))))
+ (when (and evil-visual-update-x-selection-p
+ (buffer-live-p buf)
+ (evil-visual-state-p)
+ (display-selections-p)
+ (not (eq evil-visual-selection 'block)))
+ (with-current-buffer buf
+ (evil-set-selection 'PRIMARY (buffer-substring-no-properties
+ evil-visual-beginning
+ evil-visual-end))))))
+
+(defun evil-visual-activate-hook (&optional _command)
+ "Enable Visual state if the region is activated."
+ (unless (evil-visual-state-p)
+ (evil-with-delay nil
+ (post-command-hook nil t "evil-activate-visual-state")
+ ;; the activation may only be momentary, so re-check
+ ;; in `post-command-hook' before entering Visual state
+ (unless (or (evil-visual-state-p)
+ (evil-insert-state-p)
+ (evil-emacs-state-p))
+ (when (and (region-active-p)
+ (not deactivate-mark))
+ (evil-visual-state))))))
+(put 'evil-visual-activate-hook 'permanent-local-hook t)
+
+(defun evil-visual-deactivate-hook (&optional command)
+ "Deactivate the region and restore Transient Mark mode."
+ (setq command (or command this-command))
+ (remove-hook 'deactivate-mark-hook
+ #'evil-visual-deactivate-hook t)
+ (remove-hook 'evil-normal-state-entry-hook
+ #'evil-visual-deactivate-hook t)
+ (cond
+ ((and (evil-visual-state-p) command
+ (not (evil-get-command-property command :keep-visual)))
+ (setq evil-visual-region-expanded nil)
+ (evil-exit-visual-state))
+ ((not (evil-visual-state-p))
+ (evil-active-region -1)
+ (evil-restore-transient-mark-mode))))
+(put 'evil-visual-deactivate-hook 'permanent-local-hook t)
+
+(evil-define-command evil-exit-visual-state (&optional later buffer)
+ "Exit from Visual state to the previous state.
+If LATER is non-nil, exit after the current command."
+ :keep-visual t
+ :repeat abort
+ (with-current-buffer (or buffer (current-buffer))
+ (when (evil-visual-state-p)
+ (if later
+ (setq deactivate-mark t)
+ (when evil-visual-region-expanded
+ (evil-visual-contract-region))
+ (setq evil-this-register nil
+ evil-prev-visual-selection evil-visual-selection
+ evil-prev-visual-mark (copy-marker evil-visual-mark)
+ evil-prev-visual-point (copy-marker evil-visual-point))
+ (evil-change-to-previous-state)))))
+
+(defun evil-visual-tag (&optional selection)
+ "Return a mode-line tag for SELECTION.
+SELECTION is a kind of selection as defined by
+`evil-define-visual-selection', such as `char', `line'
+or `block'."
+ (setq selection (or selection evil-visual-selection))
+ (when selection
+ (symbol-value (intern (format "evil-visual-%s-tag" selection)))))
+
+(defun evil-visual-message (&optional selection)
+ "Create an echo area message for SELECTION.
+SELECTION is a kind of selection as defined by
+`evil-define-visual-selection', such as `char', `line'
+or `block'."
+ (unless selection (setq selection evil-visual-selection))
+ (when selection
+ (let ((message (symbol-value (intern (format "evil-visual-%s-message"
+ selection)))))
+ (cond
+ ((functionp message) (funcall message))
+ ((stringp message) (evil-echo "%s" message))))))
+
+(defun evil-visual-select (beg end &optional type dir message)
+ "Create a Visual selection of type TYPE from BEG to END.
+Point and mark are positioned so that the resulting selection
+has the specified boundaries. If DIR is negative, point precedes mark,
+otherwise it succedes it. To specify point and mark directly,
+use `evil-visual-make-selection'."
+ (let* ((range (evil-contract beg end type))
+ (mark (evil-range-beginning range))
+ (point (evil-range-end range))
+ (dir (or dir 1)))
+ (when (< dir 0)
+ (evil-swap mark point))
+ (evil-visual-make-selection mark point type message)))
+
+(defun evil-visual-make-selection (mark point &optional type message)
+ "Create a Visual selection with point at POINT and mark at MARK.
+The boundaries of the selection are inferred from these
+and the current TYPE. To specify the boundaries and infer
+mark and point, use `evil-visual-select' instead."
+ (let* ((selection (evil-visual-selection-for-type type))
+ (func (evil-visual-selection-function selection))
+ (prev (and (evil-visual-state-p) evil-visual-selection))
+ (mark (evil-normalize-position mark))
+ (point (evil-normalize-position point))
+ (state evil-state))
+ (unless (evil-visual-state-p)
+ (evil-visual-state))
+ (setq evil-visual-selection selection)
+ (funcall func mark point type
+ ;; signal a message when changing the selection
+ (when (or (not (evil-visual-state-p state))
+ (not (eq selection prev)))
+ message))))
+
+(defun evil-visual-make-region (mark point &optional type message)
+ "Create an active region from MARK to POINT.
+If TYPE is given, also set the Visual type.
+If MESSAGE is given, display it in the echo area."
+ (interactive)
+ (let* ((point (or point (point)))
+ (mark (or mark
+ (when (or (evil-visual-state-p)
+ (region-active-p))
+ (mark t))
+ point)))
+ (unless (evil-visual-state-p)
+ (evil-visual-state))
+ (evil-active-region 1)
+ (setq evil-visual-region-expanded nil)
+ (evil-visual-refresh mark point type)
+ (cond
+ ((null evil-echo-state))
+ ((stringp message)
+ (evil-echo "%s" message))
+ (message
+ (cond
+ ((stringp evil-visual-state-message)
+ (evil-echo "%s" evil-visual-state-message))
+ ((functionp evil-visual-state-message)
+ (funcall evil-visual-state-message)))))))
+
+(defun evil-visual-expand-region (&optional exclude-newline)
+ "Expand the region to the Visual selection.
+If EXCLUDE-NEWLINE is non-nil and the selection ends with a newline,
+exclude that newline from the region."
+ (when (and (evil-visual-state-p)
+ (not evil-visual-region-expanded))
+ (let ((mark evil-visual-beginning)
+ (point evil-visual-end))
+ (when (< evil-visual-direction 0)
+ (evil-swap mark point))
+ (setq evil-visual-region-expanded t)
+ (evil-visual-refresh mark point)
+ (when (and exclude-newline
+ (save-excursion
+ (goto-char evil-visual-end)
+ (and (bolp) (not (bobp)))))
+ (if (< evil-visual-direction 0)
+ (evil-move-mark (max point (1- (mark))))
+ (goto-char (max mark (1- (point)))))))))
+
+(defun evil-visual-contract-region ()
+ "The inverse of `evil-visual-expand-region'.
+Create a Visual selection that expands to the current region."
+ (evil-visual-refresh)
+ (setq evil-visual-region-expanded nil)
+ (evil-visual-refresh evil-visual-mark evil-visual-point))
+
+(defun evil-visual-refresh (&optional mark point type &rest properties)
+ "Refresh point, mark and Visual variables.
+Refreshes `evil-visual-beginning', `evil-visual-end',
+`evil-visual-mark', `evil-visual-point', `evil-visual-selection',
+`evil-visual-direction', `evil-visual-properties' and `evil-this-type'."
+ (let* ((point (or point (point)))
+ (mark (or mark (mark t) point))
+ (dir (evil-visual-direction))
+ (type (or type (evil-visual-type evil-visual-selection)
+ (evil-visual-type)))
+ range)
+ (evil-move-mark mark)
+ (goto-char point)
+ (setq evil-visual-beginning
+ (or evil-visual-beginning
+ (let ((marker (make-marker)))
+ (move-marker marker (min point mark))))
+ evil-visual-end
+ (or evil-visual-end
+ (let ((marker (make-marker)))
+ (set-marker-insertion-type marker t)
+ (move-marker marker (max point mark))))
+ evil-visual-mark
+ (or evil-visual-mark
+ (let ((marker (make-marker)))
+ (move-marker marker mark)))
+ evil-visual-point
+ (or evil-visual-point
+ (let ((marker (make-marker)))
+ (move-marker marker point))))
+ (setq evil-visual-properties
+ (evil-concat-plists evil-visual-properties properties))
+ (cond
+ (evil-visual-region-expanded
+ (setq type (or (evil-visual-type) type))
+ (move-marker evil-visual-beginning (min point mark))
+ (move-marker evil-visual-end (max point mark))
+ ;; if the type is one-to-one, we can safely refresh
+ ;; the unexpanded positions as well
+ (when (evil-type-property type :one-to-one)
+ (setq range (apply #'evil-contract point mark type
+ evil-visual-properties)
+ mark (evil-range-beginning range)
+ point (evil-range-end range))
+ (when (< dir 0)
+ (evil-swap mark point))
+ (move-marker evil-visual-mark mark)
+ (move-marker evil-visual-point point)))
+ (t
+ (setq range (apply #'evil-expand point mark type
+ evil-visual-properties)
+ type (evil-type range type))
+ (move-marker evil-visual-beginning (evil-range-beginning range))
+ (move-marker evil-visual-end (evil-range-end range))
+ (move-marker evil-visual-mark mark)
+ (move-marker evil-visual-point point)))
+ (setq evil-visual-direction dir
+ evil-this-type type)))
+
+(defun evil-visual-highlight (&optional arg)
+ "Highlight Visual selection, depending on the Visual type.
+With negative ARG, disable highlighting."
+ (cond
+ ((and (numberp arg) (< arg 1))
+ (when evil-visual-overlay
+ (delete-overlay evil-visual-overlay)
+ (setq evil-visual-overlay nil))
+ (when evil-visual-block-overlays
+ (mapc #'delete-overlay evil-visual-block-overlays)
+ (setq evil-visual-block-overlays nil)))
+ ((eq evil-visual-selection 'block)
+ (when evil-visual-overlay
+ (evil-visual-highlight -1))
+ (evil-visual-highlight-block
+ evil-visual-beginning
+ evil-visual-end))
+ (t
+ (when evil-visual-block-overlays
+ (evil-visual-highlight -1))
+ (if evil-visual-overlay
+ (move-overlay evil-visual-overlay
+ evil-visual-beginning evil-visual-end)
+ (setq evil-visual-overlay
+ (make-overlay evil-visual-beginning evil-visual-end)))
+ (overlay-put evil-visual-overlay 'face 'region)
+ (overlay-put evil-visual-overlay 'priority 99))))
+
+(defun evil-visual-highlight-block (beg end &optional overlays)
+ "Highlight rectangular region from BEG to END.
+Do this by putting an overlay on each line within the rectangle.
+Each overlay extends across all the columns of the rectangle.
+Reuse overlays where possible to prevent flicker."
+ (let* ((point (point))
+ (overlays (or overlays 'evil-visual-block-overlays))
+ (old (symbol-value overlays))
+ beg-col end-col new nlines overlay window-beg window-end)
+ (save-excursion
+ ;; calculate the rectangular region represented by BEG and END,
+ ;; but put BEG in the upper-left corner and END in the
+ ;; lower-right if not already there
+ (setq beg-col (evil-column beg)
+ end-col (evil-column end))
+ (when (>= beg-col end-col)
+ (if (= beg-col end-col)
+ (setq end-col (1+ end-col))
+ (evil-swap beg-col end-col))
+ (setq beg (progn (goto-char beg) (evil-move-to-column beg-col))
+ end (progn (goto-char end) (evil-move-to-column end-col 1))))
+ ;; maybe extend end column to EOL
+ (and (memq this-command '(next-line previous-line evil-use-register))
+ (eq temporary-goal-column most-positive-fixnum)
+ (setq end-col most-positive-fixnum))
+ ;; force a redisplay so we can do reliable window
+ ;; BEG/END calculations
+ (sit-for 0)
+ (setq window-beg (max (window-start) beg)
+ window-end (min (window-end) (1+ end))
+ nlines (count-lines window-beg
+ (min window-end (point-max))))
+ ;; iterate over those lines of the rectangle which are
+ ;; visible in the currently selected window
+ (goto-char window-beg)
+ (dotimes (_ nlines)
+ (let (before after row-beg row-end)
+ ;; beginning of row
+ (evil-move-to-column beg-col)
+ (when (< (current-column) beg-col)
+ ;; prepend overlay with virtual spaces if unable to
+ ;; move directly to the first column
+ (setq before
+ (propertize
+ (make-string
+ (- beg-col (current-column)) ?\s)
+ 'face
+ (or (get-text-property (1- (point)) 'face)
+ 'default))))
+ (setq row-beg (point))
+ ;; end of row
+ (evil-move-to-column end-col)
+ (when (and (not (eolp))
+ (< (current-column) end-col))
+ ;; append overlay with virtual spaces if unable to
+ ;; move directly to the last column
+ (setq after
+ (propertize
+ (make-string
+ (if (= (point) row-beg)
+ (- end-col beg-col)
+ (- end-col (current-column)))
+ ?\s) 'face 'region))
+ ;; place cursor on one of the virtual spaces
+ (if (= point row-beg)
+ (put-text-property
+ 0 (min (length after) 1)
+ 'cursor t after)
+ (put-text-property
+ (max 0 (1- (length after))) (length after)
+ 'cursor t after)))
+ (setq row-end (min (point) (line-end-position)))
+ ;; trim old leading overlays
+ (while (and old
+ (setq overlay (car old))
+ (< (overlay-start overlay) row-beg)
+ (/= (overlay-end overlay) row-end))
+ (delete-overlay overlay)
+ (setq old (cdr old)))
+ ;; reuse an overlay if possible, otherwise create one
+ (cond
+ ((and old (setq overlay (car old))
+ (or (= (overlay-start overlay) row-beg)
+ (= (overlay-end overlay) row-end)))
+ (move-overlay overlay row-beg row-end)
+ (overlay-put overlay 'before-string before)
+ (overlay-put overlay 'after-string after)
+ (setq new (cons overlay new)
+ old (cdr old)))
+ (t
+ (setq overlay (make-overlay row-beg row-end))
+ (overlay-put overlay 'before-string before)
+ (overlay-put overlay 'after-string after)
+ (setq new (cons overlay new)))))
+ (forward-line 1))
+ ;; display overlays
+ (dolist (overlay new)
+ (overlay-put overlay 'face 'region)
+ (overlay-put overlay 'priority 99))
+ ;; trim old overlays
+ (dolist (overlay old)
+ (delete-overlay overlay))
+ (set overlays (nreverse new)))))
+
+(defun evil-visual-range ()
+ "Return the Visual selection as a range.
+This is a list (BEG END TYPE PROPERTIES...), where BEG is the
+beginning of the selection, END is the end of the selection,
+TYPE is the selection's type, and PROPERTIES is a property list
+of miscellaneous selection attributes."
+ (apply #'evil-range
+ evil-visual-beginning evil-visual-end
+ (evil-visual-type)
+ :expanded t
+ evil-visual-properties))
+
+(defun evil-visual-direction ()
+ "Return direction of Visual selection.
+The direction is -1 if point precedes mark and 1 otherwise.
+See also the variable `evil-visual-direction', which holds
+the direction of the last selection."
+ (let* ((point (point))
+ (mark (or (mark t) point)))
+ (if (< point mark) -1 1)))
+
+(defun evil-visual-type (&optional selection)
+ "Return the type of the Visual selection.
+If SELECTION is specified, return the type of that instead."
+ (or (and (null selection) (evil-visual-state-p) evil-this-type)
+ (symbol-value (cdr (assq (or selection evil-visual-selection)
+ evil-visual-alist)))))
+
+(defun evil-visual-goto-end ()
+ "Go to the last line of the Visual selection.
+This position may differ from `evil-visual-end' depending on
+the selection type, and is contained in the selection."
+ (let ((range (evil-contract-range (evil-visual-range))))
+ (goto-char (evil-range-end range))))
+
+(defun evil-visual-alist ()
+ "Return an association list from types to selection symbols."
+ (mapcar #'(lambda (e)
+ (cons (symbol-value (cdr-safe e)) (cdr-safe e)))
+ evil-visual-alist))
+
+(defun evil-visual-selection-function (selection)
+ "Return a selection function for TYPE.
+Default to `evil-visual-make-region'."
+ (or (cdr-safe (assq selection evil-visual-alist))
+ ;; generic selection function
+ 'evil-visual-make-region))
+
+(defun evil-visual-selection-for-type (type)
+ "Return a Visual selection for TYPE."
+ (catch 'done
+ (dolist (selection evil-visual-alist)
+ (when (memq (symbol-value (cdr selection))
+ (list type (evil-visual-type type)))
+ (throw 'done (car selection))))))
+
+(defun evil-visual-block-corner (&optional corner point mark)
+ "Block corner corresponding to POINT, with MARK in opposite corner.
+Depending on POINT and MARK, the return value is `upper-left',
+`upper-right', `lower-left' or `lower-right':
+
+ upper-left +---+ upper-right
+ | |
+ lower-left +---+ lower-right
+
+One-column or one-row blocks are ambiguous. In such cases,
+the horizontal or vertical component of CORNER is used.
+CORNER defaults to `upper-left'."
+ (let* ((point (or point (point)))
+ (mark (or mark (mark t)))
+ (corner (or corner
+ (when evil-visual-overlay
+ (overlay-get evil-visual-overlay :corner))
+ 'upper-left))
+ (point-col (evil-column point))
+ (mark-col (evil-column mark))
+ (upperp (if (save-excursion (goto-char (min point mark))
+ (search-forward "\n" (max point mark) t))
+ (< point mark)
+ (memq corner '(upper-left upper-right))))
+ (leftp (if (= point-col mark-col)
+ (memq corner '(upper-left lower-left))
+ (< point-col mark-col))))
+ (if upperp
+ (if leftp 'upper-left 'upper-right)
+ (if leftp 'lower-left 'lower-right))))
+
+;;; Operator-Pending state
+
+(evil-define-state operator
+ "Operator-Pending state."
+ :tag " <O> "
+ :cursor evil-half-cursor
+ :enable (evil-operator-shortcut-map operator motion normal))
+
+(evil-define-keymap evil-operator-shortcut-map
+ "Keymap for Operator-Pending shortcuts like \"dd\" and \"gqq\"."
+ :local t
+ (setq evil-operator-shortcut-map (make-sparse-keymap))
+ (evil-initialize-local-keymaps))
+
+;; the half-height "Operator-Pending cursor" cannot be specified
+;; as a static `cursor-type' value, since its height depends on
+;; the current font size
+(defun evil-half-cursor ()
+ "Change cursor to a half-height box.
+\(This is really just a thick horizontal bar.)"
+ (let ((height (/ (window-pixel-height) (* (window-height) 2))))
+ (setq cursor-type (cons 'hbar height))))
+
+;;; Replace state
+
+(evil-define-state replace
+ "Replace state."
+ :tag " <R> "
+ :cursor hbar
+ :message "-- REPLACE --"
+ :entry-hook (evil-start-track-last-insertion)
+ :exit-hook (evil-cleanup-insert-state evil-stop-track-last-insertion)
+ :input-method t
+ (cond
+ ((evil-replace-state-p)
+ (overwrite-mode 1)
+ (add-hook 'pre-command-hook #'evil-replace-pre-command nil t)
+ (add-hook 'pre-command-hook #'evil-insert-repeat-hook)
+ (unless (eq evil-want-fine-undo t)
+ (evil-start-undo-step)))
+ (t
+ (overwrite-mode -1)
+ (remove-hook 'pre-command-hook #'evil-replace-pre-command t)
+ (remove-hook 'pre-command-hook #'evil-insert-repeat-hook)
+ (setq evil-insert-repeat-info evil-repeat-info)
+ (evil-set-marker ?^ nil t)
+ (unless (eq evil-want-fine-undo t)
+ (evil-end-undo-step))
+ (evil-move-cursor-back)))
+ (setq evil-replace-alist nil))
+
+(defun evil-replace-pre-command ()
+ "Remember the character under point."
+ (when (evil-replace-state-p)
+ (let ((char (unless (eolp) (char-after)))
+ (prev (assq (point) evil-replace-alist)))
+ (if prev
+ (setcdr prev char)
+ (push (cons (point) char) evil-replace-alist)))))
+(put 'evil-replace-pre-command 'permanent-local-hook t)
+
+(defun evil-replace-backspace ()
+ "Restore character under cursor."
+ (interactive)
+ (backward-char)
+ (let* ((prev (assq (point) evil-replace-alist))
+ (char (cdr prev))
+ (this-command #'evil-replace-backspace))
+ (when prev
+ (delete-char 1)
+ (when char (save-excursion (insert char))))))
+
+(defun evil-update-replace-alist (opoint count chars-to-delete &optional offset)
+ "Add CHARS-TO-DELETE chars to evil-replace-alist, starting at OPOINT.
+If COUNT is greater than CHARS-TO-DELETE, pad the alist with nils.
+Decrement recorded position by optional offset, or 0."
+ (when (evil-replace-state-p)
+ (dotimes (c count)
+ (let ((pos (+ c opoint)))
+ (add-to-list 'evil-replace-alist
+ (cons (- pos (or offset 0)) (when (< c chars-to-delete)
+ (char-after pos))))))))
+
+;;; Motion state
+
+(evil-define-state motion
+ "Motion state."
+ :tag " <M> "
+ :suppress-keymap t)
+
+;;; Emacs state
+
+(evil-define-state emacs
+ "Emacs state."
+ :tag " <E> "
+ :message "-- EMACS --"
+ :input-method t
+ :intercept-esc nil)
+
+(provide 'evil-states)
+
+;;; evil-states.el ends here
diff --git a/.config/emacs/lisp/evil/evil-test-helpers.el b/.config/emacs/lisp/evil/evil-test-helpers.el
new file mode 100644
index 0000000..c7eeb71
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-test-helpers.el
@@ -0,0 +1,416 @@
+;;; evil-test-helpers.el --- unit test helpers for Evil -*- coding: utf-8; lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+;; Package-Requires: ((evil "1.15.0"))
+;; Version: 1.15.0
+
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file contains helper functions for writing tests for
+;; evil-mode. These helpers can also be used by other packages which
+;; extend evil-mode.
+
+;; To write a test use `evil-test-buffer':
+
+;; (require 'evil-test-helpers)
+;;
+;; (ert-deftest evil-test ()
+;; :tags '(evil)
+;; (evil-test-buffer
+;; "[T]his creates a test buffer." ; cursor on "T"
+;; ("w") ; key sequence
+;; "This [c]reates a test buffer."))) ; cursor moved to "c"
+;;
+;; The initial state, the cursor syntax, etc., can be changed
+;; with keyword arguments. See the documentation string of
+;; `evil-test-buffer' for more details.
+;;
+;; This file is NOT part of Evil itself.
+
+(require 'elp)
+(require 'ert)
+(require 'evil)
+
+;;; Code:
+
+(when (fboundp 'font-lock-add-keywords)
+ (font-lock-add-keywords 'emacs-lisp-mode
+ '(("(\\(evil-test-buffer\\)\\>"
+ 1 font-lock-keyword-face))))
+
+(defvar evil-test-point nil
+ "Marker for point.")
+(make-variable-buffer-local 'evil-test-point)
+(defvar evil-test-visual-start nil
+ "Marker for Visual beginning.")
+(make-variable-buffer-local 'evil-test-visual-start)
+(defvar evil-test-visual-end nil
+ "Marker for Visual end.")
+(make-variable-buffer-local 'evil-test-visual-end)
+
+(defvaralias 'evil-test-select-enable-clipboard
+ (if (boundp 'select-enable-clipboard)
+ 'select-enable-clipboard
+ 'x-select-enable-clipboard))
+
+(defmacro evil-test-buffer (&rest body)
+ "Execute FORMS in a temporary buffer.
+The following optional keywords specify the buffer's properties:
+
+:state STATE The initial state, defaults to `normal'.
+:visual SELECTION The Visual selection, defaults to `char'.
+:point-start STRING String for matching beginning of point,
+ defaults to \"[\".
+:point-end STRING String for matching end of point,
+ defaults to \"]\".
+:visual-start STRING String for matching beginning of
+ Visual selection, defaults to \"<\".
+:visual-end STRING String for matching end of
+ Visual selection, defaults to \">\".
+
+Then follows one or more forms. If the first form is a string,
+it is taken to be a buffer description as passed to
+`evil-test-buffer-from-string', and initializes the buffer.
+Subsequent string forms validate the buffer.
+
+If a form is a list of strings or vectors, it is taken to be a
+key sequence and is passed to `execute-kbd-macro'. If the form
+is \(file FILENAME CONTENTS), then the test fails unless the
+contents of FILENAME equal CONTENTS. If the form is \(error
+SYMBOL ...) then the test fails unless an error of type SYMBOL is
+raised. Remaining forms are evaluated as-is.
+
+\(fn [[KEY VALUE]...] FORMS...)"
+ (declare (indent defun))
+ (let ((state 'normal)
+ arg key point-start point-end string
+ visual visual-start visual-end)
+ ;; collect keywords
+ (while (keywordp (car-safe body))
+ (setq key (pop body)
+ arg (pop body))
+ (cond
+ ((eq key :point-start)
+ (setq point-start (or arg "")))
+ ((eq key :point-end)
+ (setq point-end (or arg "")))
+ ((eq key :state)
+ (setq state arg))
+ ((eq key :visual)
+ (setq visual arg))
+ ((eq key :visual-start)
+ (setq visual-start (or arg "")))
+ ((eq key :visual-end)
+ (setq visual-end (or arg "")))))
+ ;; collect buffer initialization
+ (when (stringp (car-safe body))
+ (setq string (pop body)))
+ ;; macro expansion
+ `(let ((buffer (evil-test-buffer-from-string
+ ,string ',state
+ ,point-start ,point-end
+ ',visual ,visual-start ,visual-end))
+ (kill-ring kill-ring)
+ (kill-ring-yank-pointer kill-ring-yank-pointer)
+ evil-test-select-enable-clipboard
+ message-log-max)
+ (unwind-protect
+ (save-window-excursion
+ (with-current-buffer buffer
+ ;; necessary for keyboard macros to work
+ (switch-to-buffer-other-window (current-buffer))
+ (buffer-enable-undo)
+ ;; parse remaining forms
+ ,@(mapcar
+ #'(lambda (form)
+ (let (error-symbol)
+ (when (and (listp form)
+ (eq (car-safe form) 'error))
+ (setq error-symbol (car-safe (cdr-safe form))
+ form (cdr-safe (cdr-safe form))))
+ (let ((result
+ (cond
+ ((stringp form)
+ `(evil-test-buffer-string
+ ,form
+ ',point-start ',point-end
+ ',visual-start ',visual-end))
+ ((eq (car-safe form) 'file)
+ `(evil-test-file-contents ,(cadr form)
+ ,(car (cddr form))))
+ ((or (stringp (car-safe form))
+ (vectorp (car-safe form))
+ (memq (car-safe (car-safe form))
+ '(kbd vconcat)))
+ ;; we need to execute everything as a single
+ ;; sequence for command loop hooks to work
+ `(execute-kbd-macro
+ (apply #'vconcat
+ (mapcar #'listify-key-sequence
+ (list ,@form)))))
+ ((memq (car-safe form) '(kbd vconcat))
+ `(execute-kbd-macro ,form))
+ (t form))))
+ (if error-symbol
+ `(should-error ,result :type ',error-symbol)
+ result))))
+ body)))
+ (when (buffer-name buffer) (kill-buffer buffer))))))
+
+(defmacro evil-test-selection (string &optional end-string
+ before-predicate after-predicate)
+ "Verify that the Visual selection contains STRING."
+ (declare (indent defun))
+ `(progn
+ (save-excursion
+ (goto-char (or evil-visual-beginning (region-beginning)))
+ (evil-test-text nil (or ,string ,end-string) ,before-predicate))
+ (save-excursion
+ (goto-char (or evil-visual-end (region-end)))
+ (evil-test-text (or ,end-string ,string) nil nil ,after-predicate))))
+
+(defun evil-test-buffer-string (string &optional
+ point-start point-end
+ visual-start visual-end)
+ "Validate the current buffer according to STRING.
+If STRING contains an occurrence of POINT-START immediately
+followed by POINT-END, that position is compared against point.
+If STRING contains an occurrence of VISUAL-START followed by
+VISUAL-END, those positions are compared against the Visual selection.
+POINT-START and POINT-END default to [ and ].
+VISUAL-START and VISUAL-END default to < and >."
+ (let ((actual-buffer (current-buffer))
+ (marker-buffer (evil-test-marker-buffer-from-string
+ string
+ point-start point-end
+ visual-start visual-end))
+ before-point after-point string selection)
+ (unwind-protect
+ (with-current-buffer marker-buffer
+ (setq string (buffer-string))
+ (when evil-test-point
+ (setq before-point (buffer-substring (point-min) evil-test-point)
+ after-point (buffer-substring evil-test-point (point-max))))
+ (when (and evil-test-visual-start evil-test-visual-end)
+ (setq selection (buffer-substring
+ evil-test-visual-start evil-test-visual-end)))
+ (with-current-buffer actual-buffer
+ (if (or before-point after-point)
+ (evil-test-text before-point after-point)
+ ;; if the cursor isn't specified, just test the whole buffer
+ (save-excursion
+ (goto-char (point-min))
+ (evil-test-text nil string #'bobp #'eobp)))
+ (when selection
+ (evil-test-selection selection))))
+ (kill-buffer marker-buffer))))
+
+(defun evil-test-buffer-from-string (string &optional
+ state
+ point-start point-end
+ visual visual-start visual-end)
+ "Create a new buffer according to STRING.
+If STRING contains an occurrence of POINT-START immediately
+followed by POINT-END, then point is moved to that position.
+If STRING contains an occurrence of VISUAL-START followed by
+VISUAL-END, then a Visual selection is created with those boundaries.
+POINT-START and POINT-END default to [ and ].
+VISUAL-START and VISUAL-END default to < and >.
+STATE is the initial state; it defaults to `normal'.
+VISUAL is the Visual selection: it defaults to `char'."
+ (let ((type (evil-visual-type (or visual 'char)))
+ (buffer (evil-test-marker-buffer-from-string
+ string point-start point-end
+ visual-start visual-end)))
+ (with-current-buffer buffer
+ (prog1 buffer
+ (evil-change-state state)
+ ;; let the buffer change its major mode without disabling Evil
+ (add-hook 'after-change-major-mode-hook #'evil-initialize)
+ (when (and (markerp evil-test-visual-start)
+ (markerp evil-test-visual-end))
+ (evil-visual-select
+ evil-test-visual-start evil-test-visual-end type)
+ (when evil-test-point
+ (goto-char evil-test-point)
+ (evil-visual-refresh)
+ (unless (and (= evil-visual-beginning
+ evil-test-visual-start)
+ (= evil-visual-end
+ evil-test-visual-end))
+ (evil-visual-select
+ evil-test-visual-start evil-test-visual-end type -1)
+ (goto-char evil-test-point)
+ (evil-visual-refresh))))
+ (when (markerp evil-test-point)
+ (goto-char evil-test-point))))))
+
+(defun evil-test-marker-buffer-from-string (string &optional
+ point-start point-end
+ visual-start visual-end)
+ "Create a new marker buffer according to STRING.
+If STRING contains an occurrence of POINT-START immediately
+followed by POINT-END, that position is stored in the
+buffer-local variable `evil-test-point'. Similarly,
+if STRING contains an occurrence of VISUAL-START followed by
+VISUAL-END, those positions are stored in the variables
+`evil-test-visual-beginning' and `evil-test-visual-end'.
+POINT-START and POINT-END default to [ and ].
+VISUAL-START and VISUAL-END default to < and >."
+ (let ((string (or string ""))
+ (point-start (regexp-quote
+ (if (characterp point-start)
+ (string point-start)
+ (or point-start "["))))
+ (point-end (regexp-quote
+ (if (characterp point-end)
+ (string point-end)
+ (or point-end "]"))))
+ (visual-start (regexp-quote
+ (if (characterp visual-start)
+ (string visual-start)
+ (or visual-start "<"))))
+ (visual-end (regexp-quote
+ (if (characterp visual-end)
+ (string visual-end)
+ (or visual-end ">")))))
+ (with-current-buffer (generate-new-buffer " *test*")
+ (prog1 (current-buffer)
+ (save-excursion
+ (insert string))
+ (save-excursion
+ (when (> (length point-start) 0)
+ (if (> (length point-end) 0)
+ (when (re-search-forward
+ (format "\\(%s\\)[^%s]?\\(%s\\)"
+ point-start point-end point-end) nil t)
+ (goto-char (match-beginning 0))
+ (delete-region (match-beginning 2) (match-end 2))
+ (delete-region (match-beginning 1) (match-end 1))
+ (setq evil-test-point
+ (move-marker (make-marker) (point))))
+ (when (re-search-forward point-start nil t)
+ (goto-char (match-beginning 0))
+ (delete-region (match-beginning 0) (match-end 0))
+ (setq evil-test-point
+ (move-marker (make-marker) (point)))))))
+ (save-excursion
+ (when (and (> (length visual-start) 0)
+ (> (length visual-end) 0))
+ (when (re-search-forward visual-start nil t)
+ (goto-char (match-beginning 0))
+ (delete-region (match-beginning 0) (match-end 0))
+ (setq evil-test-visual-start
+ (move-marker (make-marker) (point))))
+ (when (re-search-forward visual-end nil t)
+ (goto-char (match-beginning 0))
+ (delete-region (match-beginning 0) (match-end 0))
+ (setq evil-test-visual-end
+ (move-marker (make-marker) (point))))))))))
+
+(defun evil-test-text (before after &optional before-predicate after-predicate)
+ "Verify the text around point.
+BEFORE is the expected text before point, and AFTER is
+the text after point. BEFORE-PREDICATE is a predicate function
+to execute at the beginning of the text, and AFTER-PREDICATE
+is executed at the end."
+ (when before
+ (if (functionp before)
+ (setq before-predicate before
+ before nil)
+ (should (string= (buffer-substring
+ (max (point-min) (- (point) (length before)))
+ (point))
+ before))))
+ (when after
+ (if (functionp after)
+ (setq after-predicate after
+ after nil)
+ (should (string= (buffer-substring
+ (point)
+ (min (point-max) (+ (point) (length after))))
+ after))))
+ (when before-predicate
+ (ert-info ((format "Expect `%s' at the beginning" before-predicate))
+ (save-excursion
+ (backward-char (length before))
+ (should (funcall before-predicate)))))
+ (when after-predicate
+ (ert-info ((format "Expect `%s' at the end" after-predicate))
+ (save-excursion
+ (forward-char (length after))
+ (should (funcall after-predicate))))))
+
+(defmacro evil-test-region (string &optional end-string
+ before-predicate after-predicate)
+ "Verify that the region contains STRING."
+ (declare (indent defun))
+ `(progn
+ (save-excursion
+ (goto-char (region-beginning))
+ (evil-test-text nil (or ,string ,end-string) ,before-predicate))
+ (save-excursion
+ (goto-char (region-end))
+ (evil-test-text (or ,end-string ,string) nil nil ,after-predicate))))
+
+(defmacro evil-test-overlay (overlay string &optional end-string
+ before-predicate after-predicate)
+ "Verify that OVERLAY contains STRING."
+ (declare (indent defun))
+ `(progn
+ (save-excursion
+ (goto-char (overlay-start ,overlay))
+ (evil-test-text nil (or ,string ,end-string) ,before-predicate))
+ (save-excursion
+ (goto-char (overlay-end ,overlay))
+ (evil-test-text (or ,end-string ,string) nil nil ,after-predicate))))
+
+(defmacro evil-with-temp-file (file-var content &rest body)
+ "Create a temp file with CONTENT and bind its name to FILE-VAR within BODY.
+FILE-VAR must be a symbol which contains the name of the
+temporary file within the macro body. CONTENT is either a string
+to be used as the content of the temporary file or a form to be
+executed with the temporary file's buffer as \(current-buffer),
+see `with-temp-file'. BODY contains the forms to be executed
+while the temporary file exists. The temporary file is deleted at
+the end of the execution of BODY."
+ (declare (indent 2)
+ (debug (symbolp form body)))
+ `(let ((,file-var (make-temp-file "evil-test")))
+ (with-temp-file ,file-var
+ ,(if (stringp content)
+ `(insert ,content)
+ content))
+ ,@body
+ (delete-file ,file-var)))
+
+(defun evil-test-file-contents (name contents)
+ "Ensure that the contents of file with NAME equal CONTENTS."
+ (with-temp-buffer
+ (insert-file-contents name)
+ (should (string= (buffer-string)
+ contents))))
+
+(provide 'evil-test-helpers)
+
+;;; evil-test-helpers.el ends here
diff --git a/.config/emacs/lisp/evil/evil-tests.el b/.config/emacs/lisp/evil/evil-tests.el
new file mode 100644
index 0000000..01af626
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-tests.el
@@ -0,0 +1,10130 @@
+;; evil-tests.el --- unit tests for Evil -*- coding: utf-8; lexical-binding: t; -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file is for developers. It runs some tests on Evil.
+;; To load it, run the Makefile target "make test" or add
+;; the following lines to .emacs:
+;;
+;; (setq evil-tests-run nil) ; set to t to run tests immediately
+;; (global-set-key [f12] 'evil-tests-run) ; hotkey
+;; (require 'evil-tests)
+;;
+;; Loading this file enables profiling on Evil. The current numbers
+;; can be displayed with `elp-results'. The Makefile target
+;; "make profiler" shows profiling results in the terminal on the
+;; basis of running all tests.
+;;
+;; To write a test, use `ert-deftest' and specify a :tags value of at
+;; least '(evil). The test may inspect the output of functions given
+;; certain input, or it may execute a key sequence in a temporary
+;; buffer and investigate the results. For the latter approach, the
+;; macro `evil-test-buffer' creates a temporary buffer in Normal
+;; state. String descriptors initialize and match the contents of
+;; the buffer:
+;;
+;; (ert-deftest evil-test ()
+;; :tags '(evil)
+;; (evil-test-buffer
+;; "[T]his creates a test buffer." ; cursor on "T"
+;; ("w") ; key sequence
+;; "This [c]reates a test buffer."))) ; cursor moved to "c"
+;;
+;; The initial state, the cursor syntax, etc., can be changed
+;; with keyword arguments. See the documentation string of
+;; `evil-test-buffer' for more details.
+;;
+;; This file is NOT part of Evil itself.
+
+;; FIXME: Merely loading an ELisp file should not change Emacs's config!
+(setq load-prefer-newer t)
+
+(require 'cl-lib)
+(require 'elp)
+(require 'ert)
+;; Load non-compiled `evil-ex'. (It defines `evil-parser' - which is
+;; needed by `evil-test-parser' - only inside an `eval-when-compile'.)
+(require 'evil-ex "evil-ex.el")
+(require 'evil)
+(require 'evil-digraphs)
+(require 'evil-test-helpers)
+(require 'ispell)
+
+;;; Code:
+
+(defvar evil-tests-run nil
+ "*Run Evil tests.")
+
+(defvar evil-tests-profiler nil
+ "*Profile Evil tests.")
+
+(defun evil-tests-initialize (&optional tests profiler interactive)
+ (setq profiler (or profiler evil-tests-profiler))
+ (when (consp profiler)
+ (setq profiler (car profiler)))
+ (when profiler
+ (setq evil-tests-profiler t)
+ (setq profiler
+ (cdr (assq profiler
+ '((call . elp-sort-by-call-count)
+ (average . elp-sort-by-average-time)
+ (total . elp-sort-by-total-time)))))
+ (setq elp-sort-by-function (or profiler 'elp-sort-by-call-count))
+ (elp-instrument-package "evil"))
+ (if interactive
+ (if (y-or-n-p-with-timeout "Run tests? " 2 t)
+ (evil-tests-run tests interactive)
+ (message "You can run the tests at any time with `M-x evil-tests-run'"))
+ (evil-tests-run tests)))
+
+(defun evil-tests-run (&optional tests interactive)
+ "Run Evil tests."
+ (interactive '(nil t))
+ (let ((elp-use-standard-output (not interactive)))
+ (setq tests
+ (or (null tests)
+ `(or ,@(mapcar #'(lambda (test)
+ (or (null test)
+ (and (memq test '(evil t)) t)
+ `(or (tag ,test)
+ ,(format "^%s$" test))))
+ tests))))
+ (cond
+ (interactive
+ (ert-run-tests-interactively tests)
+ (when evil-tests-profiler
+ (elp-results)))
+ (evil-tests-profiler
+ (ert-run-tests-batch tests)
+ (elp-results))
+ (t
+ ;; We would like to use `ert-run-tests-batch-and-exit'
+ ;; Unfortunately it doesn't work outside of batch mode, and we
+ ;; can't use batch mode because we have tests that need windows.
+ ;; Instead, run the tests interactively, copy the results to a
+ ;; text file, and then exit with an appropriate code.
+ (setq attempt-stack-overflow-recovery nil
+ attempt-orderly-shutdown-on-fatal-signal nil)
+ (unwind-protect
+ (progn
+ (ert-run-tests-interactively tests)
+ (with-current-buffer "*ert*"
+ (append-to-file (point-min) (point-max) "test-results.txt")
+ (kill-emacs (if (zerop (ert-stats-completed-unexpected ert--results-stats)) 0 1))))
+ (unwind-protect
+ (progn
+ (append-to-file "Error running tests\n" nil "test-results.txt")
+ (append-to-file (backtrace-to-string (backtrace-get-frames 'backtrace)) nil "test-results.txt"))
+ (kill-emacs 2)))))))
+
+(defun evil-tests-profiler (&optional force)
+ "Profile Evil tests."
+ (when (or evil-tests-profiler force)
+ (setq evil-tests-profiler t)
+ (elp-instrument-package "evil")))
+
+;;; States
+
+(defun evil-test-local-mode-enabled ()
+ "Verify that `evil-local-mode' is enabled properly"
+ (ert-info ("Set the mode variable to t")
+ (should (eq evil-local-mode t)))
+ (ert-info ("Refresh `emulation-mode-map-alist'")
+ (should (memq 'evil-mode-map-alist emulation-mode-map-alists)))
+ (ert-info ("Create a buffer-local value for `evil-mode-map-alist'")
+ (should (assq 'evil-mode-map-alist (buffer-local-variables))))
+ (ert-info ("Initialize buffer-local keymaps")
+ (should (assq 'evil-normal-state-local-map (buffer-local-variables)))
+ (should (keymapp evil-normal-state-local-map))
+ (should (assq 'evil-emacs-state-local-map (buffer-local-variables)))
+ (should (keymapp evil-emacs-state-local-map)))
+ (ert-info ("Don't add buffer-local entries to the default value")
+ (should-not (rassq evil-normal-state-local-map
+ (default-value 'evil-mode-map-alist)))
+ (should-not (rassq evil-emacs-state-local-map
+ (default-value 'evil-mode-map-alist)))))
+
+(defun evil-test-local-mode-disabled ()
+ "Verify that `evil-local-mode' is disabled properly"
+ (ert-info ("Set the mode variable to nil")
+ (should-not evil-local-mode))
+ (ert-info ("Disable all states")
+ (evil-test-no-states)))
+
+(defun evil-test-no-states ()
+ "Verify that all states are disabled"
+ (ert-info ("Set `evil-state' to nil")
+ (should-not evil-state))
+ (ert-info ("Disable all state keymaps")
+ (dolist (state (mapcar #'car evil-state-properties) t)
+ (should-not (evil-state-property state :mode t))
+ (should-not (memq (evil-state-property state :keymap t)
+ (current-active-maps)))
+ (should-not (evil-state-property state :local t))
+ (should-not (memq (evil-state-property state :local-keymap t)
+ (current-active-maps)))
+ (dolist (map (evil-state-auxiliary-keymaps state))
+ (should-not (memq map (current-active-maps)))))))
+
+(ert-deftest evil-test-toggle-local-mode ()
+ "Toggle `evil-local-mode'"
+ :tags '(evil state)
+ (with-temp-buffer
+ (ert-info ("Enable `evil-local-mode'")
+ (evil-local-mode 1)
+ (evil-test-local-mode-enabled))
+ (ert-info ("Disable `evil-local-mode'")
+ (evil-local-mode -1)
+ (evil-test-local-mode-disabled))))
+
+(defun evil-test-change-state (state)
+ "Change state to STATE and check keymaps"
+ (evil-change-state state)
+ (let ((mode (evil-state-property state :mode))
+ ;; (keymap (evil-state-property state :keymap t))
+ (local-mode (evil-state-property state :local))
+ ;; (local-keymap (evil-state-property state :local-keymap t))
+ (tag (evil-state-property state :tag t)))
+ (when (functionp tag)
+ (setq tag (funcall tag)))
+ (ert-info ("Update `evil-state'")
+ (should (eq evil-state state)))
+ (ert-info ("Ensure `evil-local-mode' is enabled")
+ (evil-test-local-mode-enabled))
+ (ert-info ("Enable state modes")
+ (should (symbol-value mode))
+ (should (symbol-value local-mode)))
+ (ert-info ("Push state keymaps to the top")
+ (evil-test-state-keymaps state))
+ (ert-info ("Refresh mode line tag")
+ (should (equal evil-mode-line-tag tag)))))
+
+(defun evil-test-state-keymaps (state)
+ "Verify that STATE's keymaps are pushed to the top"
+ (let ((actual (evil-state-keymaps state))
+ (expected `((,(evil-state-property state :local)
+ . , (evil-state-property state :local-keymap t))
+ (,(evil-state-property state :mode)
+ . ,(evil-state-property state :keymap t)))))
+ ;; additional keymaps inherited with :enable
+ (cond
+ ((eq state 'operator)
+ (setq expected
+ `((evil-operator-shortcut-mode
+ . ,evil-operator-shortcut-map)
+ (evil-operator-state-local-minor-mode
+ . ,evil-operator-state-local-map)
+ (evil-operator-state-minor-mode
+ . ,evil-operator-state-map)
+ (evil-motion-state-local-minor-mode
+ . ,evil-motion-state-local-map)
+ (evil-motion-state-minor-mode
+ . ,evil-motion-state-map)
+ (evil-normal-state-local-minor-mode
+ . ,evil-normal-state-local-map)
+ (evil-normal-state-minor-mode
+ . ,evil-normal-state-map)))))
+ (let ((actual (butlast actual (- (length actual)
+ (length expected)))))
+ (should (equal actual expected))
+ (dolist (map actual)
+ (setq map (cdr-safe map))
+ (should (keymapp map))))))
+
+(ert-deftest evil-test-exit-normal-state ()
+ "Enter Normal state and then disable all states"
+ :tags '(evil state)
+ (with-temp-buffer
+ (evil-test-change-state 'normal)
+ (evil-normal-state -1)
+ (evil-test-no-states)))
+
+(ert-deftest evil-test-change-states ()
+ "Change between Normal state, Emacs state and Operator-Pending state"
+ :tags '(evil state)
+ (with-temp-buffer
+ (evil-test-change-state 'normal)
+ (evil-test-change-state 'emacs)
+ (evil-test-change-state 'normal)
+ (evil-test-change-state 'operator)
+ (evil-test-change-state 'normal)
+ (evil-test-change-state 'emacs)
+ (evil-test-change-state 'replace)
+ (evil-test-change-state 'normal)))
+
+(ert-deftest evil-test-change-to-previous-state ()
+ "Change to some state and back."
+ :tags '(evil state)
+ (with-temp-buffer
+ (evil-test-change-state 'normal)
+ (evil-test-change-state 'visual)
+ (evil-test-change-state 'emacs)
+ (evil-change-to-previous-state)
+ (should (eq evil-state 'visual))
+ (evil-change-to-previous-state)
+ (should (eq evil-state 'normal))))
+
+(ert-deftest evil-test-enter-normal-state-disabled ()
+ "Enter Normal state even if `evil-local-mode' is disabled"
+ :tags '(evil state)
+ (with-temp-buffer
+ (evil-local-mode -1)
+ (evil-test-local-mode-disabled)
+ (evil-test-change-state 'normal)))
+
+(ert-deftest evil-test-execute-in-normal-state ()
+ "Execute Normal state command in Insert state (`evil-execute-in-normal-state')."
+ :tags '(evil)
+ (evil-test-buffer "[a]bcdef\n"
+ ("I")
+ (should (evil-insert-state-p))
+ ("\C-ox")
+ (ert-info ("Should return to Insert state") (should (evil-insert-state-p)))
+ "[b]cdef\n"
+ ("\C-oA")
+ (ert-info ("Should return to Insert state after Insert state command")
+ (should (evil-insert-state-p)))
+ ("bcdef[]\n"))
+ (ert-info ("Cursor is placed correctly afterwards")
+ (evil-test-buffer
+ :state insert
+ "abcdefg[]"
+ ("\C-o~")
+ "abcdefG[]")
+ (evil-test-buffer
+ :state insert
+ "abcdefg[]"
+ ("\C-ozz")
+ "abcdefg[]")
+ (evil-test-buffer
+ :state insert
+ "abc[]defg"
+ ("\C-o$")
+ "abcdefg[]")
+ (evil-test-buffer
+ :state insert
+ "abcdefg[]"
+ ("\C-o^")
+ "[]abcdefg")
+ (evil-test-buffer
+ :state insert
+ "abcdefg[]"
+ ("\C-oi")
+ "abcdef[]g")
+ (evil-test-buffer
+ :state insert
+ "\n[]"
+ ("\C-ok")
+ "[]\n")
+ (evil-test-buffer
+ "line1\nli[n]e2"
+ ("ma" "kA" "\C-o`a")
+ "line1\nli[]ne2"))
+ (ert-info ("Can enter replace state and stay in it")
+ (evil-test-buffer
+ :state insert
+ "abc[]defg"
+ ("\C-oRfoo")
+ "abcfoog"))
+ (ert-info ("Insert count is ignored")
+ (evil-test-buffer "[]"
+ ("2i" "abcdef" "\C-o~" "g" [escape])
+ "abcdeF[g]"))
+ (ert-info ("Can execute evil-repeat in normal state")
+ (evil-test-buffer
+ ;; Although this is the same in Vim, text inserted after the temporary
+ ;; normal command is not recorded for repetition, which is a subtle
+ ;; (but arguably more useful) difference.
+ :state insert
+ "ab[]cfg"
+ ("\C-o~de\C-o.")
+ "abCdeF[]g")))
+
+(defun evil-test-suppress-keymap (state)
+ "Verify that `self-insert-command' is suppressed in STATE"
+ (evil-test-buffer
+ ";; This buffer is for notes."
+ (evil-test-change-state state)
+ ;; TODO: this should be done better
+ (ert-info ("Disable the state's own keymaps so that the
+suppression keymap comes first")
+ (setq evil-operator-state-minor-mode nil
+ evil-operator-state-local-minor-mode nil))
+ (should (eq (key-binding "£") #'undefined))
+ (ert-info ("Don't insert text")
+ ;; may or may not signal an error, depending on batch mode
+ (condition-case nil
+ (execute-kbd-macro "£££")
+ (error nil))
+ (should (string= (buffer-substring 1 4) ";; ")))))
+
+(ert-deftest evil-test-emacs-state-suppress-keymap ()
+ "`self-insert-command' works in Emacs state"
+ :tags '(evil state)
+ (should-error (evil-test-suppress-keymap 'emacs)))
+
+(ert-deftest evil-test-normal-state-suppress-keymap ()
+ "No `self-insert-command' in Normal state"
+ :tags '(evil state)
+ (evil-test-suppress-keymap 'normal))
+
+(ert-deftest evil-test-operator-state-suppress-keymap ()
+ "Operator-Pending state should inherit suppression
+of `self-insert-command' from Normal state"
+ :tags '(evil state)
+ (evil-test-suppress-keymap 'operator))
+
+(ert-deftest evil-test-operator-state-shortcut-keymap ()
+ "Enable shortcut keymap in Operator-Pending state"
+ :tags '(evil state)
+ (evil-test-buffer
+ (ert-info ("Activate `evil-operator-shortcut-map' in \
+Operator-Pending state")
+ (evil-test-change-state 'operator)
+ (should (rassq evil-operator-shortcut-map
+ (evil-state-keymaps 'operator)))
+ (should (keymapp evil-operator-shortcut-map))
+ (should evil-operator-shortcut-mode)
+ (should (memq evil-operator-shortcut-map
+ (current-active-maps))))
+ (ert-info ("Deactivate `evil-operator-shortcut-map' \
+outside Operator-Pending state")
+ (evil-test-change-state 'emacs)
+ (should-not evil-operator-shortcut-mode)
+ (should-not (memq evil-operator-shortcut-map
+ (current-active-maps))))
+ (ert-info ("Reset `evil-operator-shortcut-map' \
+when entering Operator-Pending state")
+ (define-key evil-operator-shortcut-map "f" 'foo)
+ (should (eq (lookup-key evil-operator-shortcut-map "f")
+ 'foo))
+ (evil-test-change-state 'operator)
+ (should-not (eq (lookup-key evil-operator-shortcut-map "f")
+ 'foo)))
+ (ert-info ("Reset `evil-operator-shortcut-map' \
+when exiting Operator-Pending state")
+ (define-key evil-operator-shortcut-map "b" 'bar)
+ (should (eq (lookup-key evil-operator-shortcut-map "b")
+ 'bar))
+ (evil-test-change-state 'emacs)
+ (should-not (eq (lookup-key evil-operator-shortcut-map "b")
+ 'bar))))
+ (ert-info ("Compute shortcuts with original keymaps")
+ (evil-test-buffer "foo"
+ (define-key evil-normal-state-local-map (kbd "SPC x") #'evil-delete)
+ ;; evil-forward-char in motion map should not shadow the executed
+ ;; evil-delete binding above when populating shortcut map.
+ ((kbd "SPC x x"))
+ "")))
+
+(ert-deftest evil-test-auxiliary-maps ()
+ "Test auxiliary keymaps"
+ :tags '(evil state)
+ ;; `evil-define-key' can't be used on a lexically-scoped keymap var.
+ (defvar evil--map)
+ (let ((evil--map (make-sparse-keymap)) aux)
+ (ert-info ("Create a new auxiliary keymap")
+ (evil-define-key 'normal evil--map "f" 'foo)
+ (setq aux (evil-get-auxiliary-keymap evil--map 'normal))
+ (should (evil-auxiliary-keymap-p aux))
+ (should (eq (lookup-key aux "f") 'foo)))
+ (ert-info ("Add to auxiliary keymap")
+ (evil-define-key 'normal evil--map "b" 'bar)
+ (should (eq (lookup-key aux "f") 'foo))
+ (should (eq (lookup-key aux "b") 'bar)))))
+
+(ert-deftest evil-test-global-local-map-binding ()
+ "Test use of `evil-define-key' for binding in global maps."
+ :tags '(evil state)
+ (let ((evil-normal-state-map (copy-keymap evil-normal-state-map))
+ (evil-normal-state-local-map
+ (when (keymapp evil-normal-state-local-map)
+ (copy-keymap evil-normal-state-local-map)))
+ (global-map (copy-keymap global-map))
+ (orig-local-map
+ (when (keymapp (current-local-map))
+ (copy-keymap (current-local-map))))
+ (map (or (current-local-map) (make-sparse-keymap))))
+ (use-local-map map)
+ (ert-info ("Bind in a global state map")
+ (evil-define-key 'normal 'global "f" 'foo)
+ (should (eq (lookup-key evil-normal-state-map "f") 'foo)))
+ (ert-info ("Bind in a local state map")
+ (evil-define-key 'normal 'local "f" 'foo)
+ (should (eq (lookup-key evil-normal-state-local-map "f") 'foo)))
+ (ert-info ("Bind in the global map")
+ (evil-define-key nil 'global "b" 'bar)
+ (should (eq (lookup-key global-map "b") 'bar)))
+ (ert-info ("Bind in the local map")
+ (evil-define-key nil 'local "b" 'bar)
+ (should (eq (lookup-key (current-local-map) "b") 'bar)))
+ (use-local-map orig-local-map)))
+
+;;; Type system
+
+(ert-deftest evil-test-exclusive-type ()
+ "Expand and contract the `line' type"
+ :tags '(evil type)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (let* ((first-line 1)
+ (second-line (progn
+ (forward-line)
+ (point))))
+ (forward-line)
+ (ert-info ("Return the beginning and end unchanged \
+if they are the same")
+ (should (equal (evil-normalize 1 1 'exclusive)
+ (list 1 1 'exclusive))))
+ (ert-info ("expand to `inclusive' if the end position \
+is at the beginning of a line")
+ (should (equal (evil-normalize (1+ first-line) second-line 'exclusive)
+ (list (1+ first-line) (1- second-line) 'inclusive
+ :expanded t))))
+ (ert-info ("expand to `line' if both the beginning and end \
+are at the beginning of a line")
+ (should (equal (evil-normalize first-line second-line 'exclusive)
+ (list first-line second-line 'line
+ :expanded t))))
+ (ert-info ("Measure as the strict difference between the end \
+and the beginning")
+ (should (string= (evil-describe 1 1 'exclusive)
+ "0 characters"))
+ (should (string= (evil-describe 1 2 'exclusive)
+ "1 character"))
+ (should (string= (evil-describe 5 2 'exclusive)
+ "3 characters"))))))
+
+(ert-deftest evil-test-inclusive-type ()
+ "Expand and contract the `inclusive' type"
+ :tags '(evil type)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (ert-info ("Include the ending character")
+ (should (equal (evil-expand 1 1 'inclusive)
+ '(1 2 inclusive :expanded t))))
+ (ert-info ("Don't mind if positions are in wrong order")
+ (should (equal (evil-expand 5 2 'inclusive)
+ '(2 6 inclusive :expanded t))))
+ (ert-info ("Exclude the ending character when contracting")
+ (should (equal (evil-contract 1 2 'inclusive)
+ '(1 1 inclusive :expanded nil))))
+ (ert-info ("Don't mind positions' order when contracting")
+ (should (equal (evil-contract 6 2 'inclusive)
+ '(2 5 inclusive :expanded nil))))
+ (ert-info ("Measure as one more than the difference")
+ (should (string= (evil-describe 1 1 'inclusive)
+ "1 character"))
+ (should (string= (evil-describe 5 2 'inclusive)
+ "4 characters")))))
+
+(ert-deftest evil-test-line-type ()
+ "Expand the `line' type"
+ :tags '(evil type)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (let* ((first-line 1)
+ (second-line (progn
+ (forward-line)
+ (point)))
+ (third-line (progn
+ (forward-line)
+ (point))))
+ (ert-info ("Expand to the whole first line")
+ (should (equal (evil-expand first-line first-line 'line)
+ (list first-line second-line 'line :expanded t)))
+ (should (string= (evil-describe first-line first-line 'line)
+ "1 line")))
+ (ert-info ("Expand to the two first lines")
+ (should (equal (evil-expand first-line second-line 'line)
+ (list first-line third-line 'line :expanded t)))
+ (should (string= (evil-describe first-line second-line 'line)
+ "2 lines"))))))
+
+(ert-deftest evil-test-block-type ()
+ "Expand and contract the `block' type"
+ :tags '(evil type)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (let* ((first-line 1)
+ (second-line (progn
+ (forward-line)
+ (point)))
+ (third-line (progn
+ (forward-line)
+ (point))))
+ (ert-info ("Expand to a 1x1 block")
+ (should (equal (evil-expand 1 1 'block)
+ (list 1 2 'block :expanded t)))
+ (should (string= (evil-describe 1 1 'block)
+ "1 row and 1 column")))
+ (ert-info ("Expand to a 2x1 block")
+ (should (equal (evil-expand first-line second-line 'block)
+ (list first-line (1+ second-line) 'block :expanded t)))
+ (should (string= (evil-describe first-line second-line 'block)
+ "2 rows and 1 column")))
+ (ert-info ("Expand to a 3x2 block")
+ (should (equal (evil-expand first-line (1+ third-line) 'block)
+ (list first-line (1+ (1+ third-line))
+ 'block :expanded t)))
+ (should (string= (evil-describe first-line (1+ third-line) 'block)
+ "3 rows and 2 columns")))
+ (ert-info ("Contract to a 0x0 rectangle")
+ (should (equal (evil-contract 1 2 'block)
+ (list 1 1 'block :expanded nil))))
+ (ert-info ("Contract to a 2x0 rectangle")
+ (should (equal (evil-contract first-line (1+ second-line) 'block)
+ (list first-line second-line 'block :expanded nil))))
+ (ert-info ("Contract to a 3x1 rectangle")
+ (should (equal (evil-contract first-line (1+ (1+ third-line)) 'block)
+ (list first-line (1+ third-line)
+ 'block :expanded nil)))))))
+
+(ert-deftest evil-test-type-transform ()
+ "Test `evil-transform'"
+ :tags '(evil type)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (ert-info ("Return positions unchanged when passed nil \
+for TYPE or TRANSFORM")
+ (should (equal (evil-transform nil 1 2 'block)
+ '(1 2 block)))
+ (should (equal (evil-transform :expand 1 2 nil)
+ '(1 2)))
+ (should (equal (evil-transform nil 1 2 nil)
+ '(1 2))))
+ (ert-info ("Accept markers, but return positions")
+ (should (equal (evil-transform :expand
+ (move-marker (make-marker) 1) 1
+ 'inclusive)
+ '(1 2 inclusive :expanded t)))
+ (should (equal (evil-transform nil (move-marker (make-marker) 1) 2
+ nil)
+ '(1 2))))))
+
+(ert-deftest evil-test-type-modifiers ()
+ "Test type modifiers like \"dv}\""
+ :tags '(evil type)
+ (ert-info ("Change `inclusive' motions to `exclusive'")
+ (evil-test-buffer
+ "[A]bove some line"
+ ("dve")
+ "[e] some line"))
+ (ert-info ("Change `exclusive' motions to `inclusive'")
+ (evil-test-buffer
+ "Above [s]ome line
+
+Below some empty line"
+ ("dv}")
+ "Above[ ]
+Below some empty line"))
+ (ert-info ("Change type to `line'")
+ (evil-test-buffer
+ "Above [s]ome line
+
+Below some empty line"
+ ("dV}")
+ "Below [s]ome empty line")))
+
+;;; Insertion
+
+(ert-deftest evil-test-insert ()
+ "Test `evil-insert'"
+ :tags '(evil insert)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save"
+ ("ievil rulz " [escape])
+ ";; evil rulz[ ]This buffer is for notes you don't want to save"))
+
+(ert-deftest evil-test-append ()
+ "Test `evil-append'"
+ :tags '(evil insert)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save"
+ ("aevil rulz " [escape])
+ ";; Tevil rulz[ ]his buffer is for notes you don't want to save"))
+
+(ert-deftest evil-test-visual-insert ()
+ "Test `evil-insert' in Visual state."
+ :tags '(evil insert)
+ (ert-info ("Repeat insert over empty lines")
+ (evil-test-buffer :visual line "<\n\n[]>"
+ ("IX" [escape])
+ "X\nX\nX")))
+
+(ert-deftest evil-test-visual-append ()
+ "Test `evil-append' in Visual state."
+ :tags '(evil insert)
+ (evil-test-buffer "<fo[o]> bar"
+ ("A_evil rulz " [escape])
+ "foo_evil rulz[ ] bar"))
+
+(ert-deftest evil-test-open-above ()
+ "Test `evil-open-above'"
+ :tags '(evil insert)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save,
+\[;]; and for Lisp evaluation."
+ ("Oabc\ndef" [escape])
+ ";; This buffer is for notes you don't want to save,
+abc
+de[f]
+;; and for Lisp evaluation.")
+ (ert-info ("Open empty line")
+ (evil-test-buffer
+ "(let (var)\n [t]est)\n"
+ (emacs-lisp-mode)
+ ("O" [escape])
+ "(let (var)\n[\n] test)\n"))
+ (ert-info ("Open non-empty line")
+ (evil-test-buffer
+ "(let (var)\n [t]est)\n"
+ (emacs-lisp-mode)
+ ("Odo-it" [escape])
+ "(let (var)\n do-i[t]\n test)\n")))
+
+(ert-deftest evil-test-open-below ()
+ "Test `evil-open-below'"
+ :tags '(evil insert)
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("oabc\ndef" [escape])
+ ";; This buffer is for notes you don't want to save,
+abc
+de[f]
+;; and for Lisp evaluation.")
+ (ert-info ("Open empty line")
+ (evil-test-buffer
+ "[(]let (var)\n test)\n"
+ (emacs-lisp-mode)
+ ("o" [escape])
+ "(let (var)\n[\n] test)\n"))
+ (ert-info ("Open non-empty line")
+ (evil-test-buffer
+ "[(]let (var)\n test)\n"
+ (emacs-lisp-mode)
+ ("odo-it" [escape])
+ "(let (var)\n do-i[t]\n test)\n"))
+ (let ((evil-auto-indent t))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "[(]and a\n c)\n"
+ (emacs-lisp-mode)
+ ("3ob" [escape])
+ "(and a\n b\n b\n [b]\n c)\n"))))
+
+(ert-deftest evil-test-open-below-folded ()
+ "Test `evil-open-below' on folded lines"
+ :tags '(evil insert)
+ (evil-test-buffer
+ "[l]ine1\n\n(let ()\n var)\n\nlast line\n"
+ (emacs-lisp-mode)
+ (hs-minor-mode 1)
+ ("zm2joABC" [escape])
+ "line1\n\n(let ()\n var)\nAB[C]\n\nlast line\n"))
+
+(ert-deftest evil-test-insert-line ()
+ "Test `evil-insert-line'"
+ :tags '(evil insert)
+ (evil-test-buffer "foo [b]ar"
+ ("Ievil rulz " [escape])
+ "evil rulz[ ]foo bar")
+ (ert-info ("With count")
+ (evil-test-buffer "foo [b]ar"
+ ("2Ievil rulz " [escape])
+ "evil rulz evil rulz[ ]foo bar")))
+
+(ert-deftest evil-test-append-line ()
+ "Test `evil-append-line'"
+ :tags '(evil insert)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save"
+ ("Aevil rulz " [escape])
+ ";; This buffer is for notes you don't want to saveevil rulz[ ]"))
+
+(ert-deftest evil-test-insert-digraph ()
+ "Test `evil-insert-digraph'"
+ :tags '(evil insert)
+ (ert-info ("Predefined digraph")
+ (evil-test-buffer
+ ("i\C-kae")
+ "æ[]"))
+ (ert-info ("Custom digraph")
+ (let ((evil-digraphs-table-user '(((?a ?o) . ?å))))
+ (evil-test-buffer
+ ("i\C-kao")
+ "å[]")))
+ (ert-info ("Digraph in replace state")
+ (evil-test-buffer
+ "ab[c]defgh"
+ ("R\C-kc,")
+ "abç[d]efgh")
+ (ert-info ("with count")
+ (evil-test-buffer
+ "abc[d]efgh"
+ ("R\C-u3\C-kd*")
+ "abcδδδ[g]h"))))
+
+(ert-deftest evil-test-track-insertion ()
+ "Test that the text of the previous insertion is tracked."
+ (ert-info ("Moving the cursor starts a new insertion")
+ (evil-test-buffer
+ ("iabc" [left] "xxx" [escape] "o\C-a")
+ "abxxxc\nxxx"))
+ (ert-info ("Autoindentation should be excluded")
+ (evil-test-buffer "\(setq x"
+ (emacs-lisp-mode)
+ ("o0\)" [escape] "o\C-a")
+ "(setq x
+ 0)
+0\)")))
+
+;;; Repeat system
+
+(ert-deftest evil-test-normalize-repeat-info ()
+ "Test `evil-normalize-repeat-info'"
+ :tags '(evil repeat)
+ (ert-info ("Single array")
+ (should (equal (evil-normalize-repeat-info
+ '("abc"))
+ '([?a ?b ?c])))
+ (should (equal (evil-normalize-repeat-info
+ '("\M-f"))
+ (list (kbd "M-f")))))
+ (ert-info ("Single symbol")
+ (should (equal (evil-normalize-repeat-info
+ '(SYM))
+ '(SYM))))
+ (ert-info ("Arrays only")
+ (should (equal (evil-normalize-repeat-info
+ '("abc" [XX YY] "def"))
+ '([?a ?b ?c XX YY ?d ?e ?f]))))
+ (ert-info ("Several symbols")
+ (should (equal (evil-normalize-repeat-info
+ '(BEG MID END))
+ '(BEG MID END))))
+ (ert-info ("Arrays with symbol at the beginning")
+ (should (equal (evil-normalize-repeat-info
+ '(BEG "abc" [XX YY] "def"))
+ '(BEG [?a ?b ?c XX YY ?d ?e ?f]))))
+ (ert-info ("Arrays with symbol at the end")
+ (should (equal (evil-normalize-repeat-info
+ '("abc" [XX YY] "def" END))
+ '([?a ?b ?c XX YY ?d ?e ?f] END))))
+ (ert-info ("Arrays with symbol in the middle")
+ (should (equal (evil-normalize-repeat-info
+ '("abc" [XX YY] MID "def" ))
+ '([?a ?b ?c XX YY] MID [?d ?e ?f]))))
+ (ert-info ("Concatenate arrays with several symbols")
+ (should (equal (evil-normalize-repeat-info
+ '(BEG "abc" [XX YY] MID "def" END))
+ '(BEG [?a ?b ?c XX YY] MID [?d ?e ?f] END)))))
+
+(defun evil-test-repeat-info (keys &optional recorded)
+ "Execute a sequence of keys and verify that `evil-repeat-ring'
+records them correctly. KEYS is the sequence of keys to execute.
+RECORDED is the expected sequence of recorded events.
+If nil, KEYS is used."
+ (execute-kbd-macro keys)
+ (should (equal (evil-normalize-repeat-info (ring-ref evil-repeat-ring 0))
+ (list (vconcat (or recorded keys))))))
+
+(ert-deftest evil-test-normal-repeat-info-simple-command ()
+ "Save key-sequence after simple editing command in Normal state"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "[T]his is a test buffer"
+ (ert-info ("Call simple command without count")
+ (evil-test-repeat-info "x"))
+ (ert-info ("Call simple command with count 3")
+ (evil-test-repeat-info "3x"))))
+
+(ert-deftest evil-test-normal-repeat-info-char-command ()
+ "Save key-sequence after editing command with character in Normal state"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "[T]his is a test buffer"
+ (ert-info ("Call command with character argument without count")
+ (evil-test-repeat-info "r5"))
+ (ert-info ("Call command with character argument with count 12")
+ (evil-test-repeat-info "12rX"))))
+
+(ert-deftest evil-test-insert-repeat-info ()
+ "Save key-sequence after Insert state"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ (ert-info ("Insert text without count")
+ (evil-test-repeat-info (vconcat "iABC" [escape])))
+ (ert-info ("Insert text with count 42")
+ (evil-test-repeat-info (vconcat "42iABC" [escape])))))
+
+(ert-deftest evil-test-repeat ()
+ "Repeat several editing commands"
+ :tags '(evil repeat)
+ (ert-info ("Repeat replace")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save"
+ ("rX")
+ "[X]; This buffer is for notes you don't want to save"
+ ([right right] ".")
+ "X;[X]This buffer is for notes you don't want to save"))
+ (ert-info ("Repeat replace with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save"
+ ("2rX")
+ "X[X] This buffer is for notes you don't want to save"
+ ([right right] ".")
+ "XX X[X]is buffer is for notes you don't want to save"))
+ (ert-info ("Repeat replace without count with a new count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save"
+ ("rX")
+ "[X]; This buffer is for notes you don't want to save"
+ ([right right] "13.")
+ "X;XXXXXXXXXXXX[X]is for notes you don't want to save"))
+ (ert-info ("Repeat replace with count replacing original count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save"
+ ("10rX")
+ "XXXXXXXXX[X]ffer is for notes you don't want to save"
+ ([right right] "20.")
+ "XXXXXXXXXXfXXXXXXXXXXXXXXXXXXX[X] don't want to save"))
+ (ert-info ("Repeat movement in Insert state")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save"
+ ("i(\M-f)" [escape])
+ ";; (This[)] buffer is for notes you don't want to save"
+ ("w.")
+ ";; (This) (buffer[)] is for notes you don't want to save"))
+ (ert-info ("Repeat search motion with offset")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (evil-test-buffer
+ "[f]irst, second, third, fourth"
+ ("d/, /e" [return])
+ "[s]econd, third, fourth"
+ ("2.")
+ "[f]ourth")))
+
+(ert-deftest evil-test-repeat-register ()
+ "Test repeating a register command."
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4\n"
+ ("\"addyy\"aP")
+ "[l]ine 1\nline 2\nline 3\nline 4\n"
+ (".")
+ "[l]ine 1\nline 1\nline 2\nline 3\nline 4\n"))
+
+(ert-deftest evil-test-repeat-numeric-register ()
+ "Test repeating a command with a numeric register."
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4\nline 5\n"
+ ("dd...")
+ "[l]ine 5\n"
+ ("\"1P")
+ "[l]ine 4\nline 5\n"
+ (".")
+ "[l]ine 3\nline 4\nline 5\n"
+ (".")
+ "[l]ine 2\nline 3\nline 4\nline 5\n"
+ (".")
+ "[l]ine 1\nline 2\nline 3\nline 4\nline 5\n"))
+
+(ert-deftest evil-test-cmd-replace-char ()
+ "Calling `evil-replace-char' should replace characters"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save"
+ ("r5")
+ "[5]; This buffer is for notes you don't want to save"
+ ("3rX")
+ "XX[X]This buffer is for notes you don't want to save")
+ (ert-info ("Replace digraph")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save"
+ ("r e'")
+ "[é]; This buffer is for notes you don't want to save"
+ ("3r c*")
+ "ξξ[ξ]This buffer is for notes you don't want to save")
+ (ert-info ("Repeat replace digraph")
+ (evil-test-buffer
+ "ab[c]defghijkl"
+ ("r W*")
+ "ab[Ω]defghijkl"
+ ("fg" "2.")
+ "abΩdefΩ[Ω]ijkl")))
+ (ert-info ("Replacing \\n should insert only one newline")
+ (evil-test-buffer
+ "(setq var xxx [y]yy zzz)\n"
+ (emacs-lisp-mode)
+ (setq indent-tabs-mode nil)
+ ("2r\n")
+ "(setq var xxx \n [y] zzz)\n")))
+
+(ert-deftest evil-test-insert-with-count ()
+ "Test `evil-insert' with repeat count"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes"
+ ("2ievil rulz " [escape])
+ ";; evil rulz evil rulz[ ]This buffer is for notes"))
+
+(ert-deftest evil-test-repeat-insert ()
+ "Test repeating of `evil-insert'"
+ :tags '(evil repeat)
+ (ert-info ("Repeat insert")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("iABC" [escape])
+ "AB[C];; This buffer is for notes"
+ ("..")
+ "ABABAB[C]CC;; This buffer is for notes"))
+ (ert-info ("Repeat insert with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("2iABC" [escape])
+ "ABCAB[C];; This buffer is for notes"
+ ("..")
+ "ABCABABCABABCAB[C]CC;; This buffer is for notes"))
+ (ert-info ("Repeat insert with repeat count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("iABC" [escape])
+ "AB[C];; This buffer is for notes"
+ ("11.")
+ "ABABCABCABCABCABCABCABCABCABCABCAB[C]C;; This buffer is for notes"))
+ (ert-info ("Repeat insert with count with repeat with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("10iABC" [escape])
+ "ABCABCABCABCABCABCABCABCABCAB[C];; This buffer is for notes"
+ ("11.")
+ "ABCABCABCABCABCABCABCABCABCABABCABCABCABCABCABCABCABCABCABCAB[C]C;; \
+This buffer is for notes")))
+
+(ert-deftest evil-test-repeat-error ()
+ "Test whether repeat returns to normal state in case of an error."
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ ("ixxx" [down] [down] [left] [left] [left] "yyy" [escape])
+ "xxxline 1\nline 2\nyy[y]line 3\nline 4"
+ (should-error (execute-kbd-macro "j^."))
+ (should (evil-normal-state-p))
+ ("^")
+ "xxxline 1\nline 2\nyyyline 3\n[x]xxline 4"))
+
+(ert-deftest evil-test-quoted-insert ()
+ "Test evil-quoted-insert in replace state."
+ (ert-info ("Simple replace C-v")
+ (evil-test-buffer
+ "ab[c]defg"
+ ("R\C-vx")
+ "abx[d]efg"))
+ (ert-info ("Control char replace C-v")
+ (evil-test-buffer
+ "ab[c]defg"
+ ("R\C-v\C-g")
+ "ab[d]efg"))
+ (ert-info ("C-v with count")
+ (evil-test-buffer
+ "ab[c]defg"
+ ("R\C-u3\C-vx")
+ "abxxx[f]g"))
+ (ert-info ("C-v with count near eol")
+ (evil-test-buffer
+ "abcde[f]g"
+ ("R\C-u3\C-vx")
+ "abcdexxx[]"))
+ (ert-info ("C-v in replace can be backspaced")
+ (evil-test-buffer
+ "ab[c]defg"
+ ("R\C-u3\C-vx" [backspace])
+ "abxx[e]fg")))
+
+(ert-deftest evil-test-repeat-quoted-insert ()
+ "Test whether `quoted-insert' can be repeated."
+ (ert-info ("Insert C-v")
+ (evil-test-buffer
+ "lin[e] 1\nline 2\nline 3\n"
+ ("i\C-v\C-v" [escape])
+ "lin[]e 1\nline 2\nline 3\n"))
+ (ert-info ("Insert ESC")
+ (evil-test-buffer
+ "lin[e] 1\nline 2\nline 3\n"
+ ("i\C-v" [escape escape])
+ "lin[]e 1\nline 2\nline 3\n"))
+ (ert-info ("Block insert C-v")
+ (evil-test-buffer
+ "lin[e] 1\nline 2\nline 3\n"
+ ("gg\C-vGI\C-v\C-v" [escape])
+ "[]line 1\nline 2\nline 3\n")))
+
+(ert-deftest evil-test-insert-vcount ()
+ "Test `evil-insert' with vertical repeating"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+
+;; Below the empty line."
+ (define-key evil-normal-state-local-map "i"
+ #'(lambda (count)
+ (interactive "p")
+ (evil-insert count 5)))
+ ("2iABC" [escape])
+ "\
+;; ABCAB[C]This buffer is for notes you don't want to save.
+;; ABCABCIf you want to create a file, visit that file with C-x C-f,
+;; ABCABCthen enter the text in that file's own buffer.
+ ABCABC
+;; ABCABCBelow the empty line."))
+
+(ert-deftest evil-test-append-with-count ()
+ "Test `evil-append' with repeat count"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes"
+ ("2aevil rulz " [escape])
+ ";; Tevil rulz evil rulz[ ]his buffer is for notes"))
+
+(ert-deftest evil-test-repeat-append ()
+ "Test repeating of `evil-append'"
+ :tags '(evil repeat)
+ (ert-info ("Repeat insert")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("aABC" [escape])
+ ";AB[C]; This buffer is for notes"
+ ("..")
+ ";ABCABCAB[C]; This buffer is for notes"))
+ (ert-info ("Repeat insert with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("2aABC" [escape])
+ ";ABCAB[C]; This buffer is for notes"
+ ("..")
+ ";ABCABCABCABCABCAB[C]; This buffer is for notes"))
+ (ert-info ("Repeat insert with repeat count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("aABC" [escape])
+ ";AB[C]; This buffer is for notes"
+ ("11.")
+ ";ABCABCABCABCABCABCABCABCABCABCABCAB[C]; This buffer is for notes"))
+ (ert-info ("Repeat insert with count with repeat with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes"
+ ("10aABC" [escape])
+ ";ABCABCABCABCABCABCABCABCABCAB[C]; This buffer is for notes"
+ ("11.")
+ ";ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCAB[C]; \
+This buffer is for notes")))
+
+(ert-deftest evil-test-append-vcount ()
+ "Test `evil-append' with vertical repeating"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+
+;; Below the empty line."
+ (define-key evil-normal-state-local-map "a"
+ #'(lambda (count)
+ (interactive "p")
+ (evil-append count 5)))
+ ("2aABC" [escape])
+ "\
+;; TABCAB[C]his buffer is for notes you don't want to save.
+;; IABCABCf you want to create a file, visit that file with C-x C-f,
+;; tABCABChen enter the text in that file's own buffer.
+ ABCABC
+;; BABCABCelow the empty line."))
+
+(ert-deftest evil-test-open-above-with-count ()
+ "Test `evil-open-above' with repeat count"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save,
+\[;]; and for Lisp evaluation."
+ ("2Oevil\nrulz" [escape])
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation."))
+
+(ert-deftest evil-test-repeat-open-above ()
+ "Test repeating of `evil-open-above'"
+ :tags '(evil repeat)
+ (ert-info ("Repeat insert")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save."
+ ("Oevil\nrulz" [escape])
+ "evil\nrul[z]
+;; This buffer is for notes you don't want to save."
+ ("..")
+ "evil\nevil\nevil\nrul[z]\nrulz\nrulz
+;; This buffer is for notes you don't want to save."))
+ (ert-info ("Repeat insert with count")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save."
+ ("2Oevil\nrulz" [escape])
+ "evil\nrulz\nevil\nrul[z]
+;; This buffer is for notes you don't want to save."
+ ("..")
+ "evil\nrulz\nevil\nevil\nrulz\nevil\nevil\nrulz\nevil\nrul[z]\nrulz\nrulz
+;; This buffer is for notes you don't want to save."))
+ (ert-info ("Repeat insert with repeat count")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save."
+ ("Oevil\nrulz" [escape])
+ "evil\nrul[z]\n;; This buffer is for notes you don't want to save."
+ ("2.")
+ "evil\nevil\nrulz\nevil\nrul[z]\nrulz
+;; This buffer is for notes you don't want to save."))
+ (ert-info ("Repeat insert with count with repeat with count")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save."
+ ("2Oevil\nrulz" [escape])
+ "evil\nrulz\nevil\nrul[z]
+;; This buffer is for notes you don't want to save."
+ ("3.")
+ "evil\nrulz\nevil\nevil\nrulz\nevil\nrulz\nevil\nrul[z]\nrulz
+;; This buffer is for notes you don't want to save.")))
+
+(ert-deftest evil-test-open-below-with-count ()
+ "Test insertion of `evil-open-below' with repeat count"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2oevil\nrulz" [escape])
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation."))
+
+(ert-deftest evil-test-repeat-open-below ()
+ "Test repeating `evil-open-below'"
+ :tags '(evil repeat)
+ (ert-info ("Repeat insert")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("oevil\nrulz" [escape])
+ ";; This buffer is for notes you don't want to save,
+evil\nrul[z]\n;; and for Lisp evaluation."
+ ("..")
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation."))
+ (ert-info ("Repeat insert with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2oevil\nrulz" [escape])
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation."
+ ("..")
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrulz\nevil\nrulz\nevil\nrulz\nevil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation."))
+ (ert-info ("Repeat insert with repeat count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("oevil\nrulz" [escape])
+ ";; This buffer is for notes you don't want to save,
+evil\nrul[z]\n;; and for Lisp evaluation."
+ ("2.")
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation."))
+ (ert-info ("Repeat insert with count with repeat with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2oevil\nrulz" [escape])
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation."
+ ("3.")
+ ";; This buffer is for notes you don't want to save,
+evil\nrulz\nevil\nrulz\nevil\nrulz\nevil\nrulz\nevil\nrul[z]
+;; and for Lisp evaluation.")))
+
+(ert-deftest evil-test-repeat-insert-line ()
+ "Test repeating of `evil-insert-line'"
+ :tags '(evil repeat)
+ (ert-info ("Repeat insert")
+ (evil-test-buffer
+ ";; This buffer is for note[s]"
+ ("IABC" [escape])
+ "AB[C];; This buffer is for notes"
+ ("..")
+ "AB[C]ABCABC;; This buffer is for notes"))
+ (ert-info ("Repeat insert with count")
+ (evil-test-buffer
+ ";; This buffer is for note[s]"
+ ("2IABC" [escape])
+ "ABCAB[C];; This buffer is for notes"
+ ("..")
+ "ABCAB[C]ABCABCABCABC;; This buffer is for notes"))
+ (ert-info ("Repeat insert with repeat count")
+ (evil-test-buffer
+ ";; This buffer is for note[s]"
+ ("IABC" [escape])
+ "AB[C];; This buffer is for notes"
+ ("11.")
+ "ABCABCABCABCABCABCABCABCABCABCAB[C]ABC;; This buffer is for notes"))
+ (ert-info ("Repeat insert with count with repeat with count")
+ (evil-test-buffer
+ ";; This buffer is for note[s]"
+ ("10IABC" [escape])
+ "ABCABCABCABCABCABCABCABCABCAB[C];; This buffer is for notes"
+ ("11.")
+ "ABCABCABCABCABCABCABCABCABCABCAB[C]ABCABCABCABCABCABCABCABCABCABC;; This buffer is for notes")))
+
+(ert-deftest evil-test-insert-line-vcount ()
+ "Test `evil-insert-line' with vertical repeating"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "int[ ]main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ (define-key evil-normal-state-local-map "I"
+ #'(lambda (count)
+ (interactive "p")
+ (evil-insert-line count 4)))
+ ("2IABC" [escape])
+ "ABCABCint main(int argc, char** argv)
+ABCABC{
+ ABCABCprintf(\"Hello world\\n\");
+ ABCABCreturn EXIT_SUCCESS;
+}"))
+
+(ert-deftest evil-test-append-line-with-count ()
+ "Test `evil-append-line' with repeat count"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("2Aevil rulz " [escape])
+ ";; This buffer is for notes.evil rulz evil rulz[ ]"))
+
+(ert-deftest evil-test-repeat-append-line ()
+ "Test repeating of `evil-append-line'"
+ :tags '(evil repeat)
+ (ert-info ("Repeat insert")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("AABC" [escape])
+ ";; This buffer is for notes.AB[C]"
+ ("..")
+ ";; This buffer is for notes.ABCABCAB[C]"))
+ (ert-info ("Repeat insert with count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("2AABC" [escape])
+ ";; This buffer is for notes.ABCAB[C]"
+ ("..")
+ ";; This buffer is for notes.ABCABCABCABCABCAB[C]"))
+ (ert-info ("Repeat insert with repeat count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("AABC" [escape])
+ ";; This buffer is for notes.ABC"
+ ("11.")
+ ";; This buffer is for notes.ABCABCABCABCABCABCABCABCABCABCABCAB[C]"))
+ (ert-info ("Repeat insert with count with repeat with count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("10AABC" [escape])
+ ";; This buffer is for notes.ABCABCABCABCABCABCABCABCABCAB[C]"
+ ("11.")
+ ";; This buffer is for notes.ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCAB[C]"))
+ (ert-info ("Repeat append over empty lines")
+ (evil-test-buffer
+ ""
+ ("i" [return] [return] [return] [return] [return] [return] [escape] "gg\C-vGAX" [escape])
+ "X\nX\nX\nX\nX\nX\n")))
+
+(ert-deftest evil-test-append-line-vcount ()
+ "Test `evil-append-line' with vertical repeating"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "int[ ]main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ (define-key evil-normal-state-local-map "A"
+ #'(lambda (count)
+ (interactive "p")
+ (evil-append-line count 4)))
+ ("2AABC" [escape])
+ "int main(int argc, char** argv)ABCAB[C]
+{ABCABC
+ printf(\"Hello world\\n\");ABCABC
+ return EXIT_SUCCESS;ABCABC
+}"))
+
+(ert-deftest evil-test-repeat-by-change ()
+ "Test repeating by tracking changes for completion commands"
+ :tags '(evil repeat)
+ (let ((line-move-visual nil)
+ (change (evil-define-command nil ()
+ :repeat change
+ (interactive)
+ (delete-char 5)
+ (insert "BEGIN\n")
+ (save-excursion
+ (insert "\nEND\n")))))
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ (define-key evil-insert-state-local-map (kbd "C-c C-p") change)
+ ("iABC " (kbd "C-c C-p") "BODY" [escape])
+ ";; ABC BEGIN
+BOD[Y]
+END
+buffer is for notes."
+ (".")
+ ";; ABC BEGIN
+BODABC BEGIN
+BOD[Y]
+END
+
+buffer is for notes.")))
+
+(ert-deftest evil-test-repeat-kill-buffer ()
+ "Test safe-guard preventing buffers from being deleted
+when repeating a command"
+ :tags '(evil repeat)
+ (ert-info ("Test killing works for direct calls \
+to `evil-execute-repeat-info'")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ (ring-insert evil-repeat-ring '((kill-buffer nil)))
+ (evil-execute-repeat-info (ring-ref evil-repeat-ring 0))
+ (should-not (looking-at ";; This"))))
+ (ert-info ("Verify an error is raised when using \
+the `evil-repeat' command")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ (ring-insert evil-repeat-ring '((kill-buffer nil)))
+ (evil-execute-repeat-info (ring-ref evil-repeat-ring 0))
+ (should-error (call-interactively #'evil-repeat)))))
+
+(ert-deftest evil-test-repeat-pop ()
+ "Test `repeat-pop'."
+ :tags '(evil repeat)
+ (ert-info ("Test repeat-pop")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ ("iABC" [escape] "aXYZ" [escape])
+ ";; ABCXY[Z]This buffer is for notes."
+ (".")
+ ";; ABCXYZXY[Z]This buffer is for notes."))
+ (ert-info ("Test repeat-pop")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ ("iABC" [escape] "aXYZ" [escape])
+ ";; ABCXY[Z]This buffer is for notes."
+ ("." (kbd "C-."))
+ ";; ABCXYAB[C]ZThis buffer is for notes."))
+ (ert-info ("Test repeat-pop-next")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ ("iABC" [escape] "aXYZ" [escape])
+ ";; ABCXY[Z]This buffer is for notes."
+ ("." (kbd "C-.") (kbd "M-."))
+ ";; ABCXYZXY[Z]This buffer is for notes."))
+ (ert-info ("Test repeat-pop after non-change")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ ("iABC" [escape] "a" [escape] "aXYZ" [escape])
+ ";; ABCXY[Z]This buffer is for notes."
+ ("." (kbd "C-.") (kbd "C-."))
+ ";; ABCXYAB[C]ZThis buffer is for notes.")))
+
+(ert-deftest evil-test-ESC-repeat-normal-state ()
+ "Test if ESC is not been recorded in normal state."
+ :tags '(evil repeat)
+ (ert-info ("Test normal ESC")
+ (evil-test-buffer
+ ";;[ ]This buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ (should (= (ring-length evil-repeat-ring) 0))
+ ("aABC" [escape])
+ ";; AB[C]This buffer is for notes."
+ (should (= (ring-length evil-repeat-ring) 1))
+ (".")
+ ";; ABCAB[C]This buffer is for notes."
+ ([escape])
+ (should (= (ring-length evil-repeat-ring) 1))
+ (".")
+ ";; ABCABCAB[C]This buffer is for notes.")))
+
+(ert-deftest evil-test-abort-operator-repeat ()
+ "Test if ESC in operator-state cancels recording of repeation."
+ :tags '(evil repeat)
+ (let ((inhibit-quit t))
+ (ert-info ("Test ESC")
+ (evil-test-buffer
+ ";;[ ]This buffer is for notes."
+ (setq evil-repeat-ring (make-ring 10))
+ (should (= (ring-length evil-repeat-ring) 0))
+ ("aABC" [escape])
+ ";; AB[C]This buffer is for notes."
+ (should (= (ring-length evil-repeat-ring) 1))
+ (".")
+ ";; ABCAB[C]This buffer is for notes."
+ ("d" [escape])
+ (should (= (ring-length evil-repeat-ring) 1))
+ (".")
+ ";; ABCABCAB[C]This buffer is for notes."))))
+
+(ert-deftest evil-test-repeat-with-find-char ()
+ "Ensure that repeating find-char commands doesn't change `evil-last-find'"
+ :tags '(evil repeat)
+ (evil-test-buffer
+ "[b]ar baz bat"
+ ("dfa" "fb")
+ "r [b]az bat"
+ (".")
+ "r [z] bat"
+ (";")
+ "r z [b]at"))
+
+(ert-deftest evil-test-repeat-visual-char ()
+ "Test repeat of character visual mode command."
+ :tags '(evil repeat)
+ (ert-info ("Test repeat on same line")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("v3lcABC" [escape])
+ ";; AB[C] buffer is for notes."
+ ("ww.")
+ ";; ABC buffer AB[C]or notes."))
+ (ert-info ("Test repeat on several lines")
+ (evil-test-buffer
+ ";; This [b]uffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+"
+ ("vj^eerX")
+ ";; This XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXX[X] you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+"
+ ("2gg^3w.")
+ ";; This XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXX you want XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXX[X]en enter the text in that file's own buffer.
+")))
+
+(ert-deftest evil-test-repeat-visual-line ()
+ "Test repeat of linewise visual mode command."
+ :tags '(evil repeat)
+ (ert-info ("Test repeat on several lines")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter th[e] text in that file's own buffer.
+
+;; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+"
+ ("VkcNew Text" [escape])
+ ";; This buffer is for notes you don't want to save.
+New Tex[t]
+
+;; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+"
+ ("jj.")
+ ";; This buffer is for notes you don't want to save.
+New Text
+
+New Tex[t]
+;; then enter the text in that file's own buffer.
+")))
+
+(ert-deftest evil-test-repeat-visual-block ()
+ "Test repeat of block visual mode command."
+ :tags '(evil repeat)
+ (ert-info ("Test repeat on several lines")
+ (evil-test-buffer
+ ";; This [b]uffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+;; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+"
+ ((kbd "C-v") "3j2lrQ")
+ ";; This [Q]QQfer is for notes you don't want to save.
+;; If yoQQQant to create a file, visit that file with C-x C-f,
+;; then QQQer the text in that file's own buffer.
+;; This QQQfer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer.
+"
+ ("2j3w.")
+ ";; This QQQfer is for notes you don't want to save.
+;; If yoQQQant to create a file, visit that file with C-x C-f,
+;; then QQQer the text [Q]QQthat file's own buffer.
+;; This QQQfer is for nQQQs you don't want to save.
+;; If you want to creatQQQ file, visit that file with C-x C-f,
+;; then enter the text QQQthat file's own buffer.
+")))
+
+(ert-deftest evil-visual-block-append ()
+ "Test appending in visual block."
+ :tags '(evil visual insert)
+ (ert-info ("Simple append")
+ (evil-test-buffer
+ "l[i]ne 1\nline 2\nline 3\n"
+ ((kbd "C-v") "jjllAXXX" [escape])
+ "lineXX[X] 1\nlineXXX 2\nlineXXX 3\n"))
+ (ert-info ("Append after empty lines")
+ (evil-test-buffer
+ "line 1l[i]ne 1\nline 2\nline 3line 3\n"
+ (setq indent-tabs-mode nil)
+ ((kbd "C-v") "jjllAXXX" [escape])
+ "line 1lineXX[X] 1\nline 2 XXX\nline 3lineXXX 3\n"))
+ (ert-info ("Append after empty first line")
+ (evil-test-buffer
+ "l[i]ne 1line 1\nline 2\nline 3line 3line 3\n"
+ (setq indent-tabs-mode nil)
+ ((kbd "C-v") "jj3feAXXX" [escape])
+ "line 1line 1 XX[X]\nline 2 XXX\nline 3line 3lineXXX 3\n"))
+ (ert-info ("Append after end of lines")
+ (evil-test-buffer
+ "line 1l[i]ne 1line 1\nline 2\nline 3line 3\n"
+ (setq indent-tabs-mode nil)
+ ((kbd "C-v") "jj$AXXX" [escape])
+ "line 1line 1line 1XX[X]\nline 2XXX\nline 3line 3XXX\n")))
+
+(ert-deftest evil-visual-block-insert ()
+ "Test inserting (prepending) in visual block."
+ :tags '(evil visual insert)
+ (ert-info ("Prepend and repeat")
+ (evil-test-buffer
+ "[a]lpha\nbravo\ncharlie\ndelta\necho\nfoxtrot\ngolf"
+ ("\C-v" "jj" "I" "zulu" [escape])
+ "zul[u]alpha\nzulubravo\nzulucharlie\ndelta\necho\nfoxtrot\ngolf"
+ ("/delta" [return] ".")
+ "zulualpha\nzulubravo\nzulucharlie\nzul[u]delta\nzuluecho\nzulufoxtrot\ngolf")))
+
+(ert-deftest evil-test-repeat-digraph ()
+ "Test repeat of insertion of a digraph."
+ :tags '(evil digraph repeat)
+ (evil-test-buffer
+ "Line with ['] several apostrophes ', yeah."
+ ("s" (kbd "C-k") "'9" [escape])
+ "Line with [’] several apostrophes ', yeah."
+ ("f'.")
+ "Line with ’ several apostrophes [’], yeah."))
+
+;;; Operators
+
+(ert-deftest evil-test-indent ()
+ "Test `evil-indent'"
+ :tags '(evil visual operator)
+ (evil-test-buffer
+ :state visual
+ "< Line with too much indentation.>"
+ ("=")
+ "Line with too much indentation.")
+ (ert-info ("Can repeat evil-indent without errors")
+ (evil-test-buffer
+ "[ ]x\n x"
+ ("==j.")
+ "x\nx")))
+
+(ert-deftest evil-test-keypress-parser ()
+ "Test `evil-keypress-parser'"
+ :tags '(evil operator)
+ (evil-test-buffer
+ :state operator
+ (ert-info ("Read from the keyboard unless INPUT is given")
+ (evil-test-buffer
+ :state operator
+ (let ((unread-command-events '(?d)))
+ (should (equal (evil-keypress-parser)
+ '(evil-delete nil)))
+ (should (equal (evil-keypress-parser '(?d))
+ '(evil-delete nil))))))
+ (ert-info ("Read remainder from the keyboard if INPUT is incomplete")
+ (let ((unread-command-events '(?d)))
+ (should (equal (evil-keypress-parser '(?2))
+ '(evil-delete 2)))))
+ (ert-info ("Handle counts not starting with zero")
+ (should (equal (evil-keypress-parser '(?2 ?d))
+ '(evil-delete 2)))
+ (should (equal (evil-keypress-parser '(?2 ?0 ?d))
+ '(evil-delete 20)))
+ (should (equal (evil-keypress-parser '(?2 ?0 ?2 ?d))
+ '(evil-delete 202)))
+ (should (equal (evil-keypress-parser '(?4 ?0 ?4 ?g ??))
+ '(evil-rot13 404))))
+ (ert-info ("Treat 0 as a motion")
+ (should (equal
+ (evil-keypress-parser '(?0))
+ '(evil-beginning-of-line nil))))
+ (ert-info ("Handle keyboard macros")
+ (evil-test-buffer
+ (define-key evil-motion-state-local-map (kbd "W") (kbd "w"))
+ (should (equal (evil-keypress-parser '(?W))
+ '(evil-forward-word-begin nil)))))))
+
+(ert-deftest evil-test-invert-char ()
+ "Test `evil-invert-char'"
+ :tags '(evil operator)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("~")
+ ";; t[h]is buffer is for notes.")
+ (evil-test-buffer
+ ";; <[T]his> buffer is for notes."
+ ("~")
+ ";; [t]HIS buffer is for notes.")
+ (evil-test-buffer
+ :visual block
+ ";; <[T]his buffer is for notes,
+;; and >for Lisp evaluation."
+ ("~")
+ ";; [t]HIS buffer is for notes,
+;; AND for Lisp evaluation."))
+
+(ert-deftest evil-test-rot13 ()
+ "Test `evil-rot13'"
+ :tags '(evil operator)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("g?" [M-right])
+ ";; [G]uvf buffer is for notes you don't want to save."))
+
+(ert-deftest evil-test-rot13-with-count ()
+ "Test `evil-rot13' with count argument"
+ :tags '(evil operator)
+ (ert-info ("Count before operator")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("2g?" [M-right])
+ ";; [G]uvf ohssre is for notes you don't want to save."))
+ (ert-info ("Count before motion")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("g?2" [M-right])
+ ";; [G]uvf ohssre is for notes you don't want to save."))
+ (ert-info ("Count before operator and motion")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("3g?2" [M-right])
+ ";; [G]uvf ohssre vf sbe abgrf lbh don't want to save."))
+ (ert-info ("Count exceeding buffer boundaries")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("g?200" [right])
+ ";; [G]uvf ohssre vf sbe abgrf lbh qba'g jnag gb fnir.")))
+
+(ert-deftest evil-test-rot13-repeat ()
+ "Test repeating of `evil-rot13'"
+ :tags '(evil operator)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("g?" [M-right] [M-right])
+ ";; Guvf[ ]buffer is for notes you don't want to save."
+ (".")
+ ";; Guvf[ ]ohssre is for notes you don't want to save."))
+
+(ert-deftest evil-test-rot13-repeat-with-count ()
+ "Test repeating of `evil-rot13' with new count"
+ :tags '(evil operator)
+ (ert-info ("Count before operator")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("2g?" [M-right])
+ ";; [G]uvf ohssre is for notes you don't want to save."
+ ("3.")
+ ";; [T]his buffer vf for notes you don't want to save."))
+ (ert-info ("Count before motion")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("g?2" [M-right])
+ ";; [G]uvf ohssre is for notes you don't want to save."
+ ("3.")
+ ";; [T]his buffer vf for notes you don't want to save."))
+ (ert-info ("Count before operator and motion")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("3g?2" [M-right])
+ ";; [G]uvf ohssre vf sbe abgrf lbh don't want to save."
+ ("4.")
+ ";; [T]his buffer is for abgrf lbh don't want to save.")))
+
+(ert-deftest evil-test-operator-delete ()
+ "Test deleting text"
+ :tags '(evil operator)
+ (ert-info ("Delete characters")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("dl")
+ ";; [h]is buffer is for notes."
+ ("d1l")
+ ";; [i]s buffer is for notes."
+ ("1dl")
+ ";; [s] buffer is for notes."
+ ("1d1l")
+ ";; [ ]buffer is for notes."
+ ("d2l")
+ ";; [u]ffer is for notes."
+ ("2dl")
+ ";; [f]er is for notes."
+ ("d4l")
+ ";; [i]s for notes."
+ ("4dl")
+ ";; [o]r notes."
+ ("2d2l")
+ ";; [o]tes."))
+ (ert-info ("Delete current line")
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("dd")
+ ";; [a]nd for Lisp evaluation.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("d1d")
+ ";; [a]nd for Lisp evaluation.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("1dd")
+ ";; [a]nd for Lisp evaluation.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("1d1d")
+ ";; [a]nd for Lisp evaluation."))
+ (ert-info ("With `evil-start-of-line' `t'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("dd")
+ "[;]; and for Lisp evaluation.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("d1d")
+ "[;]; and for Lisp evaluation.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("1dd")
+ "[;]; and for Lisp evaluation.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("1d1d")
+ "[;]; and for Lisp evaluation."))))
+ (ert-info ("Delete two lines")
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("d2d")
+ ";; [t]hen enter the text in that file's own buffer.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2dd")
+ ";; [t]hen enter the text in that file's own buffer.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("dj")
+ ";; [t]hen enter the text in that file's own buffer.")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; [I]f you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("dk")
+ ";; [t]hen enter the text in that file's own buffer."))
+ (ert-info ("With `evil-start-of-line' `t'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("d2d")
+ "[;]; then enter the text in that file's own buffer.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2dd")
+ "[;]; then enter the text in that file's own buffer.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("dj")
+ "[;]; then enter the text in that file's own buffer.")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; [I]f you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("dk")
+ "[;]; then enter the text in that file's own buffer.")))))
+
+(evil-define-motion evil-test-square-motion (count)
+ "Test motion for selecting a square."
+ :type block
+ (let ((column (current-column)))
+ (forward-line (1- count))
+ (move-to-column (+ column count -1))))
+
+(ert-deftest evil-test-yank ()
+ "Test `evil-yank'"
+ :tags '(evil operator yank)
+ (ert-info ("Yank characters")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("y2e")
+ (should (string= (current-kill 0) "This buffer"))))
+ (ert-info ("Yank lines")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("yj")
+ (should (string= (current-kill 0)
+ (buffer-substring (point-min)
+ (1+ (line-end-position 2)))))
+ (should (eq (car-safe (get-text-property 0 'yank-handler
+ (current-kill 0)))
+ 'evil-yank-line-handler)))
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+\[;]; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("y5j")
+ (should
+ (string= (current-kill 0)
+ (concat (buffer-substring (line-beginning-position 1)
+ (point-max))
+ "\n")))
+ (should (eq (car-safe (get-text-property 0 'yank-handler
+ (current-kill 0)))
+ 'evil-yank-line-handler))))
+ (ert-info ("Yank rectangle")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y3s")
+ (should (string= (current-kill 0) "Thi\nIf \nthe"))
+ (should (eq (car-safe (get-text-property 0 'yank-handler
+ (current-kill 0)))
+ 'evil-yank-block-handler))))
+ (ert-info (":yank, then paste")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\n"
+ (":yank" [return] "p")
+ "a\nb\nb\nc\nd\n"))
+ (ert-info (":yank with COUNT")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\n"
+ (":yank 2" [return] "p")
+ "a\nb\nb\nc\nc\nd\n"))
+ (ert-info (":yank with COUNT in visual state")
+ (evil-test-buffer
+ "a\n<b\nc>\nd\ne\nf\n"
+ (":yank 3" [return] "p")
+ "a\nb\nc\nd\ne\nc\nd\ne\nf\n"))
+ (ert-info (":yank with REGISTER")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\n"
+ (":yank r") ;; yank into the 'r' register
+ "a\nb\nc\nd\n"
+ ;; check the 'r' register contains the yanked text
+ (should (string= (substring-no-properties (evil-get-register ?r)) "b\n"))))
+ (ert-info (":yank with REGISTER and COUNT")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\ne\nf\n"
+ (":yank r 3")
+ "a\nb\nc\nd\ne\nf\n"
+ (should (string= (substring-no-properties (evil-get-register ?r)) "b\nc\nd\n"))))
+ (ert-info (":yank with range yanks without moving point")
+ (evil-test-buffer
+ "[a]\nb\nc\nd\ne\n"
+ (":4y" [return] "p")
+ "a\n[d]\nb\nc\nd\ne\n")
+ (evil-test-buffer
+ "[a]\nb\nc\nd\ne\n"
+ (":+4y" [return] "p")
+ "a\n[e]\nb\nc\nd\ne\n")
+ (evil-test-buffer
+ "1\n2\n3\n4\n5\n6\n7\n8\n9\n1[0]"
+ (":-5,.y")
+ "1\n2\n3\n4\n5\n6\n7\n8\n9\n1[0]")
+ (evil-test-buffer
+ "1\n2\n3\n4\n[5]\n6\n7\n8\n9\n10"
+ ("my" "G" ":'y,.y")
+ "1\n2\n3\n4\n5\n6\n7\n8\n9\n[1]0")))
+
+(ert-deftest evil-test-yank-line ()
+ "Test `evil-yank-line'"
+ :tags '(evil operator)
+ (ert-info ("Yank line with eof being part of visual selection")
+ (evil-test-buffer
+ ";; This is line one
+;; This is lin[e] two
+;; This is line three"
+ ("v$Yjp")
+ ";; This is line one
+;; This is line two
+;; This is line three
+[;]; This is line two")))
+
+(ert-deftest evil-test-delete ()
+ "Test `evil-delete'"
+ :tags '(evil operator delete)
+ (ert-info ("Delete characters")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save[.]"
+ ("x")
+ ";; This buffer is for notes you don't want to sav[e]"
+ (goto-char 4)
+ ";; [T]his buffer is for notes you don't want to save"
+ ("d2e")
+ ";; [ ]is for notes you don't want to save"
+ (should (string= (current-kill 0) "This buffer"))
+ ("P")
+ ";; This buffe[r] is for notes you don't want to save"))
+ (ert-info ("Delete lines")
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2dd")
+ ";; [t]hen enter the text in that file's own buffer."
+ ("P")
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("With `evil-start-of-line' `t'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2dd")
+ "[;]; then enter the text in that file's own buffer."
+ ("P")
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))))
+ (ert-info ("Delete last line")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; [I]f you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2dd")
+ ";; [T]his buffer is for notes you don't want to save."))
+ (ert-info ("Delete last empty line")
+ (evil-test-buffer
+ "line 1\nline 2\n\n[]"
+ ("dd")
+ "line 1\nline 2\n[]"))
+ (ert-info ("Delete rectangle")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("d3s")
+ "[T]his buffer is for notes you don't want to save.
+If you want to create a file, visit that file with C-x C-f,
+then enter the text in that file's own buffer."))
+ (ert-info (":delete")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\n"
+ (":delete")
+ "a\nc\nd\n"))
+ (ert-info (":delete with COUNT")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\n"
+ (":delete 2")
+ "a\nd\n"))
+ (ert-info (":delete with COUNT in visual state")
+ (evil-test-buffer
+ "a\n<b\nc>\nd\ne\nf\n"
+ (":delete 3")
+ "a\nb\nf\n"))
+ (ert-info (":delete with REGISTER")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\n"
+ (":delete r") ;; delete into the 'r' register
+ "a\nc\nd\n"
+ ;; check the 'r' register contains the deleted text
+ (should (string= (substring-no-properties (evil-get-register ?r)) "b\n"))))
+ (ert-info (":delete with REGISTER and COUNT")
+ (evil-test-buffer
+ "a\n[b]\nc\nd\ne\nf\n"
+ (":delete r 3")
+ "a\ne\nf\n"
+ (should (string= (substring-no-properties (evil-get-register ?r)) "b\nc\nd\n"))))
+ (ert-info ("Charwise multiple whole line delete becomes linewise")
+ (evil-test-buffer
+ "1\n[2]\n3\n4"
+ ("d2w")
+ "1\n[4]")))
+
+(ert-deftest evil-test-delete-line ()
+ "Test `evil-delete-line'"
+ :tags '(evil operator)
+ (ert-info ("Delete to end of line")
+ (evil-test-buffer
+ ";; This buffer is for notes[ ]you don't want to save."
+ ("D")
+ ";; This buffer is for note[s]"))
+ (ert-info ("Act linewise on character selection")
+ (evil-test-buffer
+ ";; This <buffe[r]> is for notes,
+and for Lisp evaluation."
+ ("D")
+ "and for Lisp [e]valuation."))
+ (ert-info ("Act on each line of block selection")
+ (evil-test-buffer
+ :visual block
+ ";; This buffer is for <notes,
+;; and for Lisp evaluatio[n]>."
+ ("D")
+ ";; This buffer is for[ ]
+;; and for Lisp evalua"))
+ (ert-info ("Yank full block with block selection")
+ (evil-test-buffer
+ :visual block
+ "line1 l<ine1 line1 line1\nline2 line2\nline3 lin>e3 line3\n"
+ ("D")
+ "line1 [l]\nline2 l\nline3 l\n"
+ ("0P")
+ "ine1 line1 line1line1 l
+ine2 line2 l
+ine3 line3 line3 l\n"))
+ (ert-info ("Delete additional whole lines with count")
+ (evil-test-buffer
+ "a[a]a\nbbb\nc\n"
+ ("2D")
+ "a\nc\n"))
+ (ert-info ("Delete line with eof being part of visual selection")
+ (evil-test-buffer
+ ";; This is line one
+;; This is lin[e] two
+;; This is line three"
+ ("v$D")
+ ";; This is line one
+;; This is line three"))
+ (ert-info ("Deletion in normal state leaves point in the right place")
+ (evil-test-buffer
+ "alpha b[r]avo charlie\ndelta echo foxtrot\ngolf hotel india"
+ (should-not evil-start-of-line)
+ ("D")
+ "alpha [b]\ndelta echo foxtrot\ngolf hotel india"
+ ("/echo" [return] "C" "newtext" [escape])
+ "alpha b\ndelta newtex[t]\ngolf hotel india")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "alpha b[r]avo charlie\ndelta echo foxtrot\ngolf hotel india"
+ ("D")
+ "alpha [b]\ndelta echo foxtrot\ngolf hotel india"
+ ("/echo" [return] "C" "newtext" [escape])
+ "alpha b\ndelta newtex[t]\ngolf hotel india")))
+ (ert-info ("Line deletion in visual state leaves point in the right place")
+ (evil-test-buffer
+ "alpha [b]ravo charlie\ndelta echo foxtrot\ngolf hotel india"
+ (should-not evil-start-of-line)
+ ("vD")
+ "delta [e]cho foxtrot\ngolf hotel india"
+ ("vX")
+ "golf h[o]tel india")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "alpha [b]ravo charlie\ndelta echo foxtrot\ngolf hotel india"
+ ("vD")
+ "[d]elta echo foxtrot\ngolf hotel india"
+ ("vX")
+ "[g]olf hotel india"))))
+
+(ert-deftest evil-test-delete-folded ()
+ "Test `evil-delete' on folded lines."
+ :tags '(evil operator)
+ (ert-info ("Delete folded lines")
+ (evil-test-buffer
+ "[l]ine1\n\n(let ()\n var)\n\n(let ()\n var2)\n"
+ (emacs-lisp-mode)
+ (hs-minor-mode 1)
+ ("zm2jdd")
+ "line1\n\n[\n](let ()\n var2)\n"))
+ (ert-info ("Delete folded lines with count")
+ (evil-test-buffer
+ "[l]ine1\n\n(let ()\n var)\n\n(let ()\n var2)\n\nlast line\n"
+ (emacs-lisp-mode)
+ (hs-minor-mode 1)
+ ("zm2j3dd")
+ "line1\n\n[\n]last line\n")))
+
+(ert-deftest evil-test-delete-backward-word ()
+ "Test `evil-delete-backward-word' in insert & replace states, and ex command-line."
+ :tags '(evil)
+ (ert-info ("evil-delete-backward-word in insert state")
+ (let ((evil-backspace-join-lines t))
+ (evil-test-buffer
+ "abc def\n ghi j[k]l\n"
+ ("i" (kbd "C-w"))
+ "abc def\n ghi [k]l\n"
+ ((kbd "C-w"))
+ "abc def\n [k]l\n"
+ ((kbd "C-w"))
+ "abc def\n[k]l\n"
+ ((kbd "C-w"))
+ "abc def[k]l\n"))
+ (let (evil-backspace-join-lines)
+ (evil-test-buffer
+ "abc def\n[k]l\n"
+ (should-error (execute-kbd-macro (concat "i" (kbd "C-w"))))
+ "abc def\n[k]l\n")))
+ (ert-info ("evil-delete-backward-word in replace state")
+ (evil-test-buffer
+ "alpha bravo [c]harlie delta"
+ ("R" "one two")
+ "alpha bravo one two[ ]delta"
+ ("\C-w")
+ "alpha bravo one [l]ie delta"
+ ("\C-w")
+ "alpha bravo [c]harlie delta"
+ ("\C-w")
+ "alpha [b]ravo charlie delta"))
+ (ert-info ("evil-delete-backward-word in ex command-line")
+ (evil-test-buffer
+ "[ ]"
+ (":normal i" "one-two" (kbd "C-w") (kbd "C-w") [return])
+ "on[e]")))
+
+(ert-deftest evil-test-visual-X ()
+ "Test `X' in visual state."
+ :tags '(evil)
+ (evil-test-buffer
+ "This is line one\nThis is lin[e] two\nThis is line three"
+ ("v$oX")
+ "This is line one\nThis is lin[e] three"))
+
+(ert-deftest evil-test-delete-back-to-indentation ()
+ "Test `evil-delete-back-to-indentation' in insert & replace states."
+ :tags '(evil)
+ (let ((evil-backspace-join-lines t))
+ (evil-test-buffer
+ "abc def\n ghi j[k]l\n"
+ ("i" (call-interactively #'evil-delete-back-to-indentation))
+ "abc def\n [k]l\n"
+ (left-char 2)
+ "abc def\n [ ] kl\n"
+ (call-interactively #'evil-delete-back-to-indentation)
+ "abc def\n[ ] kl\n"
+ (call-interactively #'evil-delete-back-to-indentation)
+ "abc def[ ] kl\n"))
+ (let (evil-backspace-join-lines)
+ (evil-test-buffer
+ "abc def\n[k]l\n"
+ (should-error
+ (progn
+ (execute-kbd-macro "i")
+ (call-interactively #'evil-delete-back-to-indentation)))
+ "abc def\n[k]l\n"))
+ (ert-info ("Delete back to indentation in replace state")
+ (evil-test-buffer
+ " alpha [b]ravo charlie"
+ ("R" "delta")
+ " alpha delta[ ]charlie"
+ (evil-delete-back-to-indentation)
+ " [a]lpha bravo charlie")))
+
+(ert-deftest evil-test-change ()
+ "Test `evil-change'"
+ :tags '(evil operator)
+ (ert-info ("Change characters")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("c2eABC" [escape])
+ ";; AB[C] is for notes you don't want to save."
+ (should (string= (current-kill 0) "This buffer"))
+ ("p")
+ ";; ABCThis buffe[r] is for notes you don't want to save."))
+ (ert-info ("Change lines")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2ccABCLINE\nDEFLINE" [escape])
+ "ABCLINE
+DEFLIN[E]
+;; then enter the text in that file's own buffer."
+ ("p")
+ "ABCLINE
+DEFLINE
+\[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Change last line")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; [I]f you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2ccABC" [escape])
+ ";; This buffer is for notes you don't want to save.
+AB[C]"))
+ (ert-info ("C changes whole line in visual characterwise and linewise states")
+ (evil-test-buffer
+ "Two lines [s]hould suffice
+for this test."
+ ("veC" "all gone!")
+ "all gone![]
+for this test.")
+ (evil-test-buffer
+ "Two lines [w]ill be fine
+for this test too."
+ ("VjC" "all gone!")
+ "all gone![]"))
+ (ert-info ("C clears the visual blockwise selection, and all text to the right")
+ (evil-test-buffer
+ "Two [l]ines will be fine for
+the tests here as well."
+ ("\C-vjeC")
+ "Two []
+the "))
+ (ert-info ("S clears the whole line in normal mode, and all lines touched by visual selection")
+ (evil-test-buffer
+ "Two lines [s]hould suffice
+for this test."
+ ("S" "all gone!")
+ "all gone![]
+for this test.")
+ (evil-test-buffer
+ "Two lines [s]hould suffice
+for this test."
+ ("vS" "all gone!")
+ "all gone![]
+for this test.")
+ (evil-test-buffer
+ "Two lines [s]hould suffice
+for this test."
+ ("VjS" "all gone!")
+ "all gone![]")
+ (evil-test-buffer
+ "Two lines [s]hould suffice
+for this test."
+ ("\C-VjS" "all gone!")
+ "all gone![]"))
+ (ert-info ("R behaves the same as S in visual modes")
+ (evil-test-buffer
+ "Two lines [s]hould suffice
+for this test."
+ ("vR" "all gone!")
+ "all gone![]
+for this test."))
+ (ert-info ("Change rectangle")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("c3sABC" [escape])
+ "AB[C]This buffer is for notes you don't want to save.
+ABCIf you want to create a file, visit that file with C-x C-f,
+ABCthen enter the text in that file's own buffer.")))
+
+(ert-deftest evil-maybe-remove-spaces-test ()
+ "Test maybe removing (indentation) spaces after some commands when making a clear line."
+ :tags '(evil operator)
+ (ert-info ("changing the line and returning to normal mode removes spaces")
+ (evil-test-buffer
+ (emacs-lisp-mode)
+ ("i(one two" [return] "three" [return] "four" [return] "five" [escape] "?three" [return])
+ "(one two
+ [t]hree
+ four
+ five"
+ ("cc" "new line" [escape] "+")
+ "(one two
+ new line
+ [f]our
+ five"
+ ("cc" [escape])
+ "(one two
+ new line
+[]
+ five")))
+
+(ert-deftest evil-test-change-line ()
+ "Test `evil-change-line'"
+ :tags '(evil operator)
+ (ert-info ("Change line with eof being part of visual selection")
+ (evil-test-buffer
+ "This is line one
+This is lin[e] two
+This is line three"
+ ("v$C")
+ "This is line one
+[]
+This is line three")))
+
+(ert-deftest evil-test-change-word ()
+ "Test changing words"
+ :tags '(evil operator)
+ (ert-info ("Non-word")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("cwABC" [escape])
+ "AB[C] This buffer is for notes."))
+ (ert-info ("Word")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("cwABC" [escape])
+ ";; AB[C] buffer is for notes."))
+ (ert-info ("Single character")
+ (evil-test-buffer
+ "[;] This buffer is for notes."
+ ("cwABC" [escape])
+ "AB[C] This buffer is for notes."))
+ (ert-info ("Whitespace")
+ (evil-test-buffer
+ "This[ ]is a test\n"
+ ("cwABC" [escape])
+ "ThisAB[C]is a test\n")))
+
+(ert-deftest evil-test-join ()
+ "Test `evil-join'"
+ :tags '(evil join operator)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f."
+ ("J")
+ ";; This buffer is for notes you don't want to save.[ ]\
+;; If you want to create a file, visit that file with C-x C-f."))
+ (ert-info ("Visual")
+ (evil-test-buffer
+ :visual line
+ "<;; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f.>"
+ ("J")
+ ";; This buffer is for notes you don't want to save.[ ]\
+;; If you want to create a file, visit that file with C-x C-f."))
+ (ert-info ("Join with count")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":join 3")
+ "line 1 line 2 line 3\nline 4"))
+ (ert-info ("Join with bang and count")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":join! 3")
+ "line 1line 2line 3\nline 4"))
+ (ert-info ("Join with bang and count, exceeding end-of-buffer")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":join! 10")
+ "line 1line 2line 3line 4"))
+ (ert-info ("Join with count 1 should be the same as without count")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":join 1")
+ "line 1 line 2\nline 3\nline 4"))
+ (ert-info ("Join with count 2 should be the same as with count 1")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":join 2")
+ "line 1 line 2\nline 3\nline 4"))
+ (ert-info ("Join with count and single line range")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":2join 3")
+ "line 1\nline 2 line 3 line 4"))
+ (ert-info ("Join with count and range")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":1,2join 3")
+ "line 1\nline 2 line 3 line 4"))
+ (ert-info ("Join with count, range and bang")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":1,2join! 3")
+ "line 1\nline 2line 3line 4"))
+ (ert-info ("Join with range")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (":1,3join")
+ "line 1 line 2 line 3\nline 4"))
+ (ert-info ("Join blank line")
+ (evil-test-buffer
+ "(when foo\n[]\n bar)"
+ (emacs-lisp-mode)
+ ("J")
+ "(when foo\n [b]ar)")))
+
+(ert-deftest evil-test-substitute ()
+ "Test `evil-substitute'"
+ :tags '(evil operator)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("5sABC" [escape])
+ ";; AB[C]buffer is for notes."))
+ (ert-info ("On empty line")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ ("5sABC" [escape])
+ "Above some line
+AB[C]
+Below some empty line")))
+
+(ert-deftest evil-test-shift ()
+ "Test `evil-shift-right' and `evil-shift-left'."
+ :tags '(evil operator)
+ (let ((evil-shift-width 4)
+ indent-tabs-mode)
+ (ert-info ("Shift linewise")
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\n"
+ ("Vj>")
+ "[ ] line 1\n line 2\nline 3\n"))
+ (ert-info ("With `evil-start-of-line' `t'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\n"
+ ("Vj>")
+ " [l]ine 1\n line 2\nline 3\n"))))
+ (ert-info ("Shift char selection on whole line")
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\n"
+ ("v$>")
+ " line [1]\nline 2\nline 3\n"))
+ (ert-info ("With `evil-start-of-line' `t'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\n"
+ ("v$>")
+ " [l]ine 1\nline 2\nline 3\n"))))
+ (ert-info ("Shift visual with count")
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\n"
+ ("Vj3>")
+ "[ ] line 1\n line 2\nline 3\n"
+ ("Vj2<")
+ "[ ] line 1\n line 2\nline 3\n"))
+ (ert-info ("With `evil-start-of-line' `t'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\n"
+ ("Vj3>")
+ " [l]ine 1\n line 2\nline 3\n"
+ ("Vj2<")
+ " [l]ine 1\n line 2\nline 3\n"))))
+ (ert-info ("Shift in insert state")
+ (evil-test-buffer
+ "line 1\nl[i]ne 2\nline 3\n"
+ ("i\C-t\C-t")
+ "line 1\n l[i]ne 2\nline 3\n"
+ ("\C-d")
+ "line 1\n l[i]ne 2\nline 3\n"))
+ (ert-info ("Delete all indentation in insert state")
+ (evil-test-buffer
+ "line1\n sometext[ ]"
+ ("a" "somemore" "0\C-d")
+ "line1\nsometext somemore[]"))))
+
+(ert-deftest evil-test-operator-set-marks ()
+ "Test `[ and `] are set by operators."
+ :tags '(evil operator)
+ (ert-info ("Can go to end of last operated text")
+ (evil-test-buffer
+ "alpha br[a]vo charlie"
+ ("gUiw")
+ "alpha [B]RAVO charlie"
+ ("`]")
+ "alpha BRAV[O] charlie"))
+ (ert-info ("Can go to end of last operated text")
+ (evil-test-buffer
+ "alpha br[a]vo charlie"
+ ("g?iw$")
+ "alpha oenib charli[e]"
+ ("`[")
+ "alpha [o]enib charlie"))
+ (ert-info ("Marks are correct after deletion")
+ (evil-test-buffer
+ "alpha br[a]vo charlie"
+ ("daw^")
+ "[a]lpha charlie"
+ ("`]")
+ "alpha [c]harlie"
+ ("^`[")
+ "alpha [c]harlie")
+ (evil-test-buffer
+ "alpha br[a]vo charlie"
+ ("D^")
+ "[a]lpha br"
+ ("`]")
+ "alpha b[r]"
+ ("^`[")
+ "alpha b[r]")))
+
+(ert-deftest evil-test-operator-save-state-for-motion ()
+ "Test that `evil-operator-range' restores state after executing motion."
+ (evil-test-buffer "abc"
+ ("dfbix" [escape])
+ "xc"))
+
+;;; Paste
+
+(ert-deftest evil-test-paste-before ()
+ "Test `evil-paste-before'"
+ :tags '(evil paste)
+ (ert-info ("Paste characters")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("y2ej0")
+ ";; This buffer is for notes you don't want to save,
+\[;]; and for Lisp evaluation."
+ ("P")
+ ";; This buffer is for notes you don't want to save,
+This buffe[r];; and for Lisp evaluation."))
+ (ert-info ("Paste characters with count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("y2ej0")
+ ";; This buffer is for notes you don't want to save,
+\[;]; and for Lisp evaluation."
+ ("3P")
+ ";; This buffer is for notes you don't want to save,
+This bufferThis bufferThis buffe[r];; and for Lisp evaluation."))
+ (ert-info ("Paste characters at end-of-buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("y2eG$")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation[.]"
+ ("2P")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluationThis bufferThis buffe[r]."))
+ (ert-info ("Paste lines")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2yyP")
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."))
+ (ert-info ("Paste lines with count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2yy2P")
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."))
+ (ert-info ("Paste lines at end-of-buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2yyG$")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation[.]"
+ ("2P")
+ ";; This buffer is for notes you don't want to save,
+\[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; and for Lisp evaluation."))
+ (ert-info ("Paste block")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ysP")
+ "[;]; ;; This buffer is for notes you don't want to save.
+;; ;; If you want to create a file, visit that file with C-x C-f,
+;; ;; then enter the text in that file's own buffer."))
+ (ert-info ("Paste block with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ys2P")
+ "[;]; ;; ;; This buffer is for notes you don't want to save.
+;; ;; ;; If you want to create a file, visit that file with C-x C-f,
+;; ;; ;; then enter the text in that file's own buffer."))
+ (ert-info ("Paste block with empty line")
+ (evil-test-buffer
+ "[;]; Above some line
+
+;; Below some empty line"
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ys2P")
+ "[;]; ;; ;; Above some line
+ \n\
+;; ;; ;; Below some empty line"))
+ (ert-info ("Paste block crossing end of buffer")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ysj")
+ ";; This buffer is for notes you don't want to save.
+\[;]; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("P")
+ ";; This buffer is for notes you don't want to save.
+\[;]; ;; If you want to create a file, visit that file with C-x C-f,
+;; ;; then enter the text in that file's own buffer.
+;;"))
+ (ert-info ("Paste block at end-of-line")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ys$")
+ ";; This buffer is for notes you don't want to save[.]
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("p")
+ ";; This buffer is for notes you don't want to save.[;];
+;; If you want to create a file, visit that file wi;; th C-x C-f,
+;; then enter the text in that file's own buffer. ;;"))
+ (ert-info ("Don't mutate register when stripping test props")
+ (let (indent-tabs-mode)
+ (evil-test-buffer
+ "[a]aaaaaaaaaaaa
+bbbbbbbb
+cccc"
+ ("\C-vG$yA " "\C-r\"" [escape] "up")
+ "aaaaaaaaaaaaa[a]aaaaaaaaaaaa
+bbbbbbbb bbbbbbbb
+cccc cccc"))))
+
+(ert-deftest evil-test-paste-after ()
+ "Test `evil-paste-after'"
+ :tags '(evil paste)
+ (ert-info ("Paste characters")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("y2ej0")
+ ";; This buffer is for notes you don't want to save,
+\[;]; and for Lisp evaluation."
+ ("p")
+ ";; This buffer is for notes you don't want to save,
+;This buffe[r]; and for Lisp evaluation."))
+ (ert-info ("Paste characters with count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("y2ej0")
+ ";; This buffer is for notes you don't want to save,
+\[;]; and for Lisp evaluation."
+ ("3p")
+ ";; This buffer is for notes you don't want to save,
+;This bufferThis bufferThis buffe[r]; and for Lisp evaluation."))
+ (ert-info ("Paste characters at end-of-buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("y2eG$")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation[.]"
+ ("2p")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.This bufferThis buffe[r]"))
+ (ert-info ("Paste lines")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2yyp")
+ ";; This buffer is for notes you don't want to save,
+\[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; and for Lisp evaluation."))
+ (ert-info ("Paste lines with count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2yy2p")
+ ";; This buffer is for notes you don't want to save,
+\[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; and for Lisp evaluation."))
+ (ert-info ("Paste lines at end-of-buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("2yyG$")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation[.]"
+ ("2p")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+\[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation.
+;; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation."))
+ (ert-info ("Paste block")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ysp")
+ ";[;]; ; This buffer is for notes you don't want to save.
+;;; ; If you want to create a file, visit that file with C-x C-f,
+;;; ; then enter the text in that file's own buffer."))
+ (ert-info ("Paste block with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ys2p")
+ ";[;]; ;; ; This buffer is for notes you don't want to save.
+;;; ;; ; If you want to create a file, visit that file with C-x C-f,
+;;; ;; ; then enter the text in that file's own buffer."))
+ (ert-info ("Paste block with empty line")
+ (evil-test-buffer
+ "[;]; Above some line
+
+;; Below some empty line"
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ys2p")
+ ";;; ;; ; Above some line
+
+;;; ;; ; Below some empty line"))
+ (ert-info ("Paste block crossing end of buffer")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ysj")
+ ";; This buffer is for notes you don't want to save.
+\[;]; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("p")
+ ";; This buffer is for notes you don't want to save.
+;;; ; If you want to create a file, visit that file with C-x C-f,
+;;; ; then enter the text in that file's own buffer.
+ ;;"))
+ (ert-info ("Paste block at end-of-line")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("3ys$")
+ ";; This buffer is for notes you don't want to save[.]
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("p")
+ ";; This buffer is for notes you don't want to save.;;
+;; If you want to create a file, visit that file wi;; th C-x C-f,
+;; then enter the text in that file's own buffer. ;;"))
+ (ert-info ("Paste preserves preceding text properties")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (put-text-property (point) (line-end-position) 'font-lock-face 'warning)
+ ("yyp")
+ ";; This buffer is for notes you don't want to save.
+[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (should (equal (get-text-property (point-min) 'font-lock-face) 'warning)))))
+
+(ert-deftest evil-test-paste-pop-before ()
+ "Test `evil-paste-pop' after `evil-paste-before'"
+ :tags '(evil paste)
+ (ert-info ("Paste")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sj")
+ ";; This buffer is for notes you don't want to save.
+\[;]; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("P")
+ ";; This buffer is for notes you don't want to save.
+\[;]; ;; If you want to create a file, visit that file with C-x C-f,
+;; ;; then enter the text in that file's own buffer.
+;;"))
+ (ert-info ("Single pop")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjP\C-p")
+ ";; This buffer is for notes you don't want to save.
+\[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Two pops")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjP\C-p\C-p")
+ ";; This buffer is for notes you don't want to save.
+;; Thi[s];; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Pop with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjP2\C-p")
+ ";; This buffer is for notes you don't want to save.
+;; Thi[s];; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Single pop-next")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjP2\C-p\C-n")
+ ";; This buffer is for notes you don't want to save.
+\[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Pop-next with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjP\C-p\C-p2\C-n")
+ ";; This buffer is for notes you don't want to save.
+\[;]; ;; If you want to create a file, visit that file with C-x C-f,
+;; ;; then enter the text in that file's own buffer.
+;;")))
+
+(ert-deftest evil-test-paste-pop-after ()
+ "Test `evil-paste-pop' after `evil-paste-after'"
+ :tags '(evil paste)
+ (ert-info ("Paste")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sj")
+ ";; This buffer is for notes you don't want to save.
+\[;]; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("p")
+ ";; This buffer is for notes you don't want to save.
+;[;]; ; If you want to create a file, visit that file with C-x C-f,
+;;; ; then enter the text in that file's own buffer.
+ ;;"))
+ (ert-info ("Single pop")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjp\C-p")
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+\[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Two pops")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjp\C-p\C-p")
+ ";; This buffer is for notes you don't want to save.
+;;; Thi[s]; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Pop with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjp2\C-p")
+ ";; This buffer is for notes you don't want to save.
+;;; Thi[s]; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Single pop-next")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjp2\C-p\C-n")
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+\[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Pop-next with count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjp\C-p\C-p2\C-n")
+ ";; This buffer is for notes you don't want to save.
+;[;]; ; If you want to create a file, visit that file with C-x C-f,
+;;; ; then enter the text in that file's own buffer.
+ ;;")))
+
+(ert-deftest evil-test-paste-pop-without-undo ()
+ "Test `evil-paste-pop' with undo disabled"
+ :tags '(evil paste)
+ (ert-info ("Pop-next with count without undo")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (setq buffer-undo-list t)
+ (define-key evil-operator-state-local-map "s" #'evil-test-square-motion)
+ ("y2e2yyy3sjP\C-p\C-p2\C-n")
+ ";; This buffer is for notes you don't want to save.
+\[;]; ;; If you want to create a file, visit that file with C-x C-f,
+;; ;; then enter the text in that file's own buffer.
+;;")))
+
+(ert-deftest evil-test-visual-paste ()
+ "Test `evil-paste-before' and `evil-paste-after' in Visual state"
+ :tags '(evil paste)
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; [I]f you want to create a file, visit that file with C-x C-f."
+ ("yyk")
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f."
+ ("VP")
+ "[;]; If you want to create a file, visit that file with C-x C-f.
+;; If you want to create a file, visit that file with C-x C-f.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f."
+ ("yyj")
+ ";; This buffer is for notes you don't want to save.
+;; [I]f you want to create a file, visit that file with C-x C-f."
+ ("Vp")
+ ";; This buffer is for notes you don't want to save.
+\[;]; This buffer is for notes you don't want to save.")
+ (ert-info ("Visual-paste from register 3")
+ ;; This behaviour deviates from vim, which populates registers 1-9 with
+ ;; deleted text only, not yanked text. This is an aspect of `evil-yank's
+ ;; use of the emacs kill-ring, so is consistent with non-visual paste.
+ (evil-test-buffer
+ "[w]ord1a word1b word1c word1d
+word2a word2b word2c word2d"
+ ("yiwwyiwwyiw")
+ "word1a word1b [w]ord1c word1d
+word2a word2b word2c word2d"
+ ("+viw\"3p")
+ "word1a word1b word1c word1d
+word1[a] word2b word2c word2d"))
+ (ert-info ("Visual-paste respects `evil-kill-on-visual-paste'")
+ (evil-test-buffer
+ "[w]ord1 word2 word3"
+ (setq evil-kill-on-visual-paste nil)
+ ("yewyew")
+ "word1 word2 [w]ord3"
+ ("ve\"2p")
+ "word1 word2 word[1]"
+ ("o\C-r\"")
+ "word1 word2 word1
+word2[]")
+ (evil-test-buffer
+ "[w]ord1 word2 word3"
+ (setq evil-kill-on-visual-paste t)
+ ("yewyew")
+ "word1 word2 [w]ord3"
+ ("ve\"2p")
+ "word1 word2 word[1]"
+ ("o\C-r\"")
+ "word1 word2 word1
+word3[]"))
+ (ert-info ("Visual-paste from `=' register")
+ (evil-test-buffer
+ "foo"
+ ("viw" "\"=p(* 6 7)" [return])
+ "4[2]"))
+ (ert-info ("Blockwise visual paste (of charwise text) with count")
+ (evil-test-buffer
+ "[a]bc\n123\n123\n123"
+ ("ye" "jl" "\C-vG" "2p")
+ "abc\n1[a]bcabc3\n1abcabc3\n1abcabc3"
+ ("gv") ;; Test point & mark are stored correctly
+ "abc\n1<abcabc3\n1abcabc3\n1abcab[c]>3"))
+ (ert-info ("Blockwise visual paste of linewise text")
+ (evil-test-buffer "[a]bc\n123\n123"
+ ("yy" "jl" "\C-vj" "p")
+ "abc\n13\n13\nabc"))
+ (ert-info ("Blockwise visual paste of blockwise text")
+ (evil-test-buffer "xy\n[z]\n123\n123"
+ ("\C-vkly2jl\C-vjp")
+ "xy\nz\n1xy3\n1z 3")))
+
+(ert-deftest evil-test-visual-paste-pop ()
+ "Test `evil-paste-pop' after visual paste."
+ :tags '(evil paste)
+ (ert-info ("Visual-char paste, char paste")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^jw")
+ "word1a word1b word1c\nword2a [w]ord2b\nword3a word3b word3c word3d\n"
+ ("viwp")
+ "word1a word1b word1c\nword2a word1[b]\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-char paste, char paste, line pop")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^jw")
+ "word1a word1b word1c\nword2a [w]ord2b\nword3a word3b word3c word3d\n"
+ ("viwp\C-p")
+ "word1a word1b word1c\nword2a \n[w]ord1a word1b word1c\n\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-char paste, char paste, line pop, char pop")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^jw")
+ "word1a word1b word1c\nword2a [w]ord2b\nword3a word3b word3c word3d\n"
+ ("viwp\C-p\C-p")
+ "word1a word1b word1c\nword2a word1[a]\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-line paste, char paste")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^j")
+ "word1a word1b word1c\n[w]ord2a word2b\nword3a word3b word3c word3d\n"
+ ("Vp")
+ "word1a word1b word1c\nword1[b]\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-line paste, char paste, line pop")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^j")
+ "word1a word1b word1c\n[w]ord2a word2b\nword3a word3b word3c word3d\n"
+ ("Vp\C-p")
+ "word1a word1b word1c\n[w]ord1a word1b word1c\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-line paste, char paste, line pop, char pop")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^j")
+ "word1a word1b word1c\n[w]ord2a word2b\nword3a word3b word3c word3d\n"
+ ("Vp\C-p\C-p")
+ "word1a word1b word1c\nword1[a]\nword3a word3b word3c word3d\n")))
+
+(ert-deftest evil-test-register ()
+ "Test yanking and pasting to and from register."
+ :tags '(evil yank paste)
+ (ert-info ("simple lower case register")
+ (evil-test-buffer
+ "[f]oo\n"
+ ("\"ayw\"aP")
+ "fo[o]foo\n"
+ ("\"ayy\"aP")
+ "[f]oofoo\nfoofoo\n"))
+ (ert-info ("upper case register")
+ (evil-test-buffer
+ "[f]oo\n"
+ ("\"ayw\"Ayw\"aP")
+ "foofo[o]foo\n"
+ ("\"ayy\"Ayy\"aP")
+ "[f]oofoofoo\nfoofoofoo\nfoofoofoo\n"))
+ (ert-info ("upper case register and lines")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4\n"
+ ("\"a2Yjj\"A2Y\"aP")
+ "line 1\nline 2\n[l]ine 1\nline 2\nline 3\nline 4\nline 3\nline 4\n"
+ ("8G\"ap")
+ "line 1\nline 2\nline 1\nline 2\nline 3\nline 4\nline 3\nline 4\n[l]ine 1\nline 2\nline 3\nline 4\n"))
+ (ert-info ("yank with count")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\n"
+ ("\"a2yw\"aP")
+ "line [1]line 1\nline 2\nline 3\n"
+ ("\"a2yy\"aP")
+ "[l]ine 1line 1\nline 2\nline 1line 1\nline 2\nline 3\n"))
+ (dolist (module '(evil-search isearch))
+ (evil-select-search-module 'evil-search-module module)
+ (ert-info ((format "special register / (module: %s)" module))
+ (evil-test-buffer
+ "[f]oo bar\n"
+ ("/bar" [return] "0i\C-r/")
+ "bar[f]oo bar\n")))
+ (ert-info ("special register :")
+ (evil-test-buffer
+ "[f]oo bar\n"
+ (":noh\ni\C-r:")))
+ (ert-info ("Paste from register during change to register")
+ (evil-test-buffer
+ "[a]lpha beta"
+ ("\"ayiw" "w" "\"bciw" "\C-ra")
+ "alpha alpha[]"))
+ (ert-info ("Paste from register in replace state")
+ (evil-test-buffer
+ "[a]lpha bravo charlie"
+ ("yiw" "w" "R" "\C-r0")
+ "alpha alpha[ ]charlie"
+ ([backspace] [backspace] [backspace])
+ "alpha al[a]vo charlie"))
+ (ert-info ("Normal delete after visual delete doesn't clobber register")
+ (evil-test-buffer
+ "[a]lpha bravo charlie delta"
+ ("vf \"xd" "dw" ";\"xp")
+ "charlie alpha delta"))
+ (ert-info ("Choosing register keeps eol anchoring")
+ (evil-test-buffer
+ "[a]aaaaa\nbbbbb\ncccc"
+ ("\C-v" "2j" "$" "\"xy" "G" "o" [escape] "\"xp")
+ "aaaaaa\nbbbbb\ncccc\n[a]aaaaa\nbbbbb\ncccc")))
+
+(ert-deftest evil-test-last-insert-register ()
+ "Test last insertion register."
+ (evil-test-buffer
+ "[l]ine 1\n"
+ ("GiABC" [escape])
+ "line 1\nAB[C]"
+ ("go\".P")
+ "AB[C]line 1\nABC"))
+
+(ert-deftest evil-test-zero-register ()
+ "\"0 contains the last text that was yanked without specificying a register."
+ (evil-test-buffer
+ "[l]ine 1\nline 2\n"
+ ("yy\"0p")
+ "line 1\n[l]ine 1\nline 2\n"
+ ("j\"ayy\"0p")
+ "line 1\nline 1\nline 2\n[l]ine 1\n" ; yanked line 2 to "a, so "0 is still line 1
+ ("kdd\"0p")
+ "line 1\nline 1\nline 1\n[l]ine 1\n"))
+
+(ert-deftest evil-test-=-register ()
+ "\"= is not really a register . It inserts the result of evaluating some elisp"
+ (ert-info ("Can eval elisp, and can fetch default (last) result")
+ (evil-test-buffer
+ :state insert
+ "8x8= []"
+ ("\C-r=(* 8 8)" [return])
+ "8x8= 64"
+ ([return] "16x4= \C-r=" [return])
+ "8x8= 64
+16x4= 64"))
+
+ (ert-info ("Can eval infix math, and can use register at prompt")
+ (evil-test-buffer
+ "[5]0/10 * 100 = "
+ ("\"nyt=" "A\C-r=" "\C-rn" [return])
+ "50/10 * 100 = 500")))
+
+(ert-deftest evil-test-gp-gP ()
+ (ert-info ("gp and gP are just like p and P but move the cursor forward")
+ (evil-test-buffer
+ "[a]lpha bravo charlie"
+ ("ye" "2f " "gp")
+ "alpha bravo alpha[c]harlie"
+ ("2F " "gP")
+ "alphaalpha[ ]bravo alphacharlie"
+ ("l" "ve" "gp")
+ "alphaalpha alpha[ ]alphacharlie"))
+ (ert-info ("gp linewise")
+ (evil-test-buffer
+ "[a]lpha line\nbravo line\ncharlie line\ndelta line\necho line"
+ ("2yy" "2j")
+ "alpha line\nbravo line\n[c]harlie line\ndelta line\necho line"
+ ("gp")
+ "alpha line\nbravo line\ncharlie line\nalpha line\nbravo line\n[d]elta line\necho line"
+ (".")
+ "alpha line\nbravo line\ncharlie line\nalpha line\nbravo line\ndelta line\nalpha line\nbravo line\necho line")))
+
+(ert-deftest evil-test-ex-put ()
+ "evil-ex-put inserts text linewise, regardless of yank-handler"
+ (ert-info ("Can put linewise text from default register, by line number")
+ (evil-test-buffer
+ "[L]orem ipsum dolor sit amet
+consectetur adipiscing elit
+sed do eiusmod tempor incididunt"
+ ("yy:2put" [return])
+ "Lorem ipsum dolor sit amet
+consectetur adipiscing elit
+[L]orem ipsum dolor sit amet
+sed do eiusmod tempor incididunt"))
+
+ (ert-info ("Can put blockwise text from letter register, backwards")
+ (evil-test-buffer
+ "Lorem ipsum [d]olor sit amet
+consectetur adipiscing elit
+sed do eiusmod tempor incididunt"
+ ("\C-vje\"xy" "bye" "Vj" ":put! x" [return])
+ "Lorem ipsum dolor sit amet
+dolor sit
+[a]dipiscing
+consectetur adipiscing elit
+sed do eiusmod tempor incididunt"))
+
+ (ert-info ("Can supply args and put from = register")
+ (evil-test-buffer
+ "[L]ine one."
+ (":put = (* 6 7)" [return])
+ "Line one.
+[4]2")))
+
+(ert-deftest evil-test-align ()
+ "Test `evil-align-left', `evil-align-right' and `evil-align-center'."
+ :tags '(evil operator)
+ (evil-without-display
+ (let ((fill-column 70)
+ indent-tabs-mode)
+ (evil-test-buffer
+ "before\n[l]ine 1\nthis is line number 2\nline number 3\nafter\n"
+ (":.,+2ri" [return] (kbd "M-x") "untabify" [return])
+ "before\n [l]ine 1\n this is line number 2\n line number 3\nafter\n"
+ (":.,+2ri 60" [return] (kbd "M-x") "untabify" [return])
+ "before\n [l]ine 1\n this is line number 2\n line number 3\nafter\n"
+ (":.,+2le" [return] (kbd "M-x") "untabify" [return])
+ "before\n[l]ine 1\nthis is line number 2\nline number 3\nafter\n"
+ (":.,+2le 10" [return])
+ "before\n [l]ine 1\n this is line number 2\n line number 3\nafter\n"
+ (":.,+2ce" [return] (kbd "M-x") "untabify" [return])
+ "before\n [l]ine 1\n this is line number 2\n line number 3\nafter\n"
+ (":.,+2ce 40" [return] (kbd "M-x") "untabify" [return])
+ "before\n [l]ine 1\n this is line number 2\n line number 3\nafter\n"))))
+
+;;; Motions
+
+(ert-deftest evil-test-forward-char ()
+ "Test `evil-forward-char' motion"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("l")
+ ";[;] This buffer is for notes."))
+ (ert-info ("End of line")
+ (let ((evil-cross-lines t)
+ (evil-move-beyond-eol nil))
+ (evil-test-buffer
+ ";; This buffer is for notes[,]
+;; and for Lisp evaluation."
+ ("l")
+ ";; This buffer is for notes,
+\[;]; and for Lisp evaluation.")))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("12l")
+ ";; This buff[e]r is for notes."))
+ (ert-info ("End of line")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ (error end-of-line "l")
+ (error end-of-line "10l")))
+ (ert-info ("Until end-of-line")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ (error end-of-line "100l")
+ ";; This buffer is for notes[.]"))
+ (ert-info ("On empty line")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ (should-error (execute-kbd-macro "l"))
+ (should-error (execute-kbd-macro "42l")))))
+
+(ert-deftest evil-test-backward-char ()
+ "Test `evil-backward-char' motion"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; This[ ]buffer is for notes."
+ ("h")
+ ";; Thi[s] buffer is for notes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; This[ ]buffer is for notes."
+ ("3h")
+ ";; T[h]is buffer is for notes."))
+ (ert-info ("Beginning of line")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ (should-error (execute-kbd-macro "h"))
+ (should-error (execute-kbd-macro "10h"))))
+ (ert-info ("Until beginning-of-line")
+ (evil-test-buffer
+ ";; This[ ]buffer is for notes."
+ (error beginning-of-line "100h")
+ "[;]; This buffer is for notes."))
+ (ert-info ("On empty line")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ (should-error (execute-kbd-macro "h"))
+ (should-error (execute-kbd-macro "42h")))))
+
+(ert-deftest evil-test-previous-line ()
+ "Test `evil-previous-line' motion"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save,
+;; [a]nd for Lisp evaluation."
+ ("k")
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; [t]hen enter the text in that file's own buffer."
+ ("2k")
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("Until beginning of buffer")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; [t]hen enter the text in that file's own buffer."
+ ("100k")
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."))
+ (ert-info ("At beginning of buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ (should-error (execute-kbd-macro "k"))
+ (should-error (execute-kbd-macro "42k")))))
+
+(ert-deftest evil-test-next-line ()
+ "Test `evil-next-line' motion"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("j")
+ ";; This buffer is for notes you don't want to save,
+;; [a]nd for Lisp evaluation."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("2j")
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; [t]hen enter the text in that file's own buffer."))
+ (ert-info ("Until end of buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("100j")
+ ";; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; [t]hen enter the text in that file's own buffer."))
+ (ert-info ("At end of buffer")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to [s]ave."
+ (should-error (execute-kbd-macro "j"))
+ (should-error (execute-kbd-macro "42j")))))
+
+(ert-deftest evil-test-next+previous-preserve-column ()
+ "Test `evil-previous-line' and `evil-next-line' preserve the column."
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "ab[c]\nabcdef\n\nabcd\n"
+ ("j")
+ "abc\nab[c]def\n\nabcd\n")
+ (evil-test-buffer
+ "ab[c]\nabcdef\n\nabcd\n"
+ ("jj")
+ "abc\nabcdef\n[\n]abcd\n")
+ (evil-test-buffer
+ "ab[c]\nabcdef\n\nabcd\n"
+ ("jjj")
+ "abc\nabcdef\n\nab[c]d\n")
+ (evil-test-buffer
+ "ab[c]\nabcdef\n\nabcd\n"
+ ("jjjk")
+ "abc\nabcdef\n[\n]abcd\n")
+ (evil-test-buffer
+ "ab[c]\nabcdef\n\nabcd\n"
+ ("jjjkk")
+ "abc\nab[c]def\n\nabcd\n")))
+
+(ert-deftest evil-test-logical-visual-next-line ()
+ "Test alternating between logical and visual next/previous line motions."
+ :tags '(evil motion)
+ (skip-unless (and (not noninteractive) (> (window-width) 2)))
+ (evil-test-buffer "[x]\nyy\n"
+ (insert (make-string (window-width) ?x)) ; Make first line soft-wrap
+ (goto-char (point-min))
+ ("gjj")
+ (should (= (current-column) 1))
+ ("Gkgk")
+ (should-not (bolp))))
+
+(ert-deftest evil-test-eol-anchoring-with-visual-line-movement ()
+ "Test gj and gk once the cursor is anchored at eol with $."
+ :tags '(evil motion)
+ (skip-unless (and (not noninteractive) (> (window-width) 13)))
+ (evil-test-buffer
+ "Short [l]ine\nA longer line\nThird line"
+ ("$gj")
+ "Short line\nA longer lin[e]\nThird line"))
+
+(ert-deftest evil-test-other-commands-preserve-column ()
+ "Test other comamnds preserve the column, when appropriate."
+ :tags '(evil motion)
+ (ert-info ("evil-goto-line can preserve column")
+ (let ((evil-start-of-line nil))
+ (evil-test-buffer
+ "Shor[t] line
+Average line
+The longest line"
+ ("2G")
+ "Short line
+Aver[a]ge line
+The longest line"
+ ("$G")
+ "Short line
+Average line
+The longest lin[e]"
+ ("hgg")
+ "Short lin[e]
+Average line
+The longest line")))
+
+ (ert-info ("evil-goto-line respects evil-start-of-line")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "foo\n[b]ar"
+ ("$ggj")
+ "foo\n[b]ar")))
+
+ (ert-info ("N% (`evil-jump-item' with count) can preserve column")
+ (let ((evil-start-of-line nil))
+ (evil-test-buffer
+ "Short line
+Average line
+The lo[n]gest line"
+ ("5%")
+ "Short [l]ine
+Average line
+The longest line"
+ ("$90%")
+ "Short line
+Average line
+The longest lin[e]"))))
+
+(ert-deftest evil-test-beginning-of-line ()
+ "Test `evil-beginning-of-line' motion"
+ :tags '(evil motion)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("0")
+ "[;]; This buffer is for notes you don't want to save."
+ ("0")
+ "[;]; This buffer is for notes you don't want to save."))
+
+(ert-deftest evil-test-end-of-line ()
+ "Test `evil-end-of-line' motion"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save."
+ ("$")
+ ";; This buffer is for notes you don't want to save[.]"
+ ("$")
+ ";; This buffer is for notes you don't want to save[.]"))
+ (ert-info ("Don't delete blank lines")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ ("d$")
+ "Above some line
+\[]
+Below some empty line"))
+ (ert-info ("Visual state")
+ (evil-test-buffer
+ "f[o]o\nbar"
+ ("v$")
+ "f<oo\n>bar")
+ (let ((evil-v$-excludes-newline t))
+ (evil-test-buffer
+ "f[o]o\nbar"
+ ("v$")
+ "f<oo>\nbar"))))
+
+(ert-deftest evil-test-percentage-of-line ()
+ "Test `evil-percentage-of-line' motion"
+ :tags '(evil motion)
+ (evil-test-buffer
+ "[0]123456789"
+ ("gM")
+ "01234[5]6789"
+ ("10gM")
+ "0[1]23456789"
+ ("85gM")
+ "01234567[8]9"))
+
+(ert-deftest evil-test-first-non-blank ()
+ "Test `evil-first-non-blank' motion"
+ :tags '(evil motion)
+ (evil-test-buffer
+ "\
+ printf(\"Hello world\\n\")[;]
+ return EXIT_SUCCESS;"
+ ("^")
+ "\
+ [p]rintf(\"Hello world\\n\");
+ return EXIT_SUCCESS;"
+ ("j^")
+ "\
+ printf(\"Hello world\\n\");
+ [r]eturn EXIT_SUCCESS;"))
+
+(ert-deftest evil-test-last-non-blank ()
+ "Test `evil-last-non-blank' motion"
+ :tags '(evil motion)
+ (evil-test-buffer
+ "[i]nt main(int argc, char** argv) \n\
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("g_")
+ "int main(int argc, char** argv[)] \n\
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("jjg_")
+ "int main(int argc, char** argv) \n\
+{
+ printf(\"Hello world\\n\")[;]
+ return EXIT_SUCCESS;
+}"))
+
+(ert-deftest evil-test-goto-first-line ()
+ "Test `evil-goto-first-line' motion"
+ :tags '(evil motion)
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ "[i]nt main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("3gg")
+ "int main(int argc, char** argv)
+{
+[ ] printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("gg")
+ "[i]nt main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("100gg")
+ "int main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+\[}]"))
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "[i]nt main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("3gg")
+ "int main(int argc, char** argv)
+{
+ [p]rintf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("gg")
+ "[i]nt main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("100gg")
+ "int main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+\[}]"))))
+
+(ert-deftest evil-test-goto-line ()
+ "Test `evil-goto-line' motion"
+ :tags '(evil motion)
+ (ert-info ("With `evil-start-of-line' `t'")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ "[i]nt main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("G")
+ "int main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+\[}]"
+ ("3G")
+ "int main(int argc, char** argv)
+{
+ [p]rintf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("100G")
+ "int main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+\[}]")))
+ (ert-info ("With `evil-start-of-line' `nil'")
+ (evil-test-buffer
+ "[i]nt main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("G")
+ "int main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+\[}]"
+ ("3G")
+ "int main(int argc, char** argv)
+{
+[ ] printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("100G")
+ "int main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+\[}]")))
+
+(ert-deftest evil-test-goto-char ()
+ "Test `evil-goto-char' motion and ex command."
+ :tags '(evil motion ex)
+ (evil-test-buffer
+ "[W]e only need a short buffer for this test"
+ (":goto 9")
+ "We only [n]eed a short buffer for this test"
+ (":goto")
+ "[W]e only need a short buffer for this test"
+ ("16go")
+ "We only need a [s]hort buffer for this test"
+ ("go")
+ "[W]e only need a short buffer for this test"
+ (evil-goto-char 24)
+ "We only need a short bu[f]fer for this test"
+ ("v29go")
+ "We only need a short bu<ffer [f]>or this test"))
+
+(ert-deftest evil-test-operator-0 ()
+ "Test motion \"0\" with an operator."
+ :tags '(evil motion)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("d0")
+ "[T]his buffer is for notes."))
+
+(ert-deftest evil-test-forward-not-word ()
+ "Test `evil-forward-not-thing'"
+ :tags '(evil motion)
+ (evil-test-buffer
+ "[ ] aa,,"
+ (evil-forward-not-thing 'evil-word)
+ " [a]a,,"))
+
+;; TODO: test Visual motions and window motions
+(ert-deftest evil-test-forward-word-begin ()
+ "Test `evil-forward-word-begin'"
+ :tags '(evil motion)
+ (ert-info ("Non-word")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("w")
+ ";; [T]his buffer is for notes."))
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("w")
+ ";; This [b]uffer is for notes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("3w")
+ ";; This buffer is [f]or notes."))
+ (ert-info ("With count on whitespace")
+ (evil-test-buffer
+ ";;[ ]This buffer is for notes."
+ ("3w")
+ ";; This buffer [i]s for notes."))
+ (ert-info ("Empty line")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ ("w")
+ "Above some line
+
+\[B]elow some empty line")
+ (evil-test-buffer
+ "[A]bove
+
+Below some empty line"
+ ("dw")
+ "[]
+
+Below some empty line"
+ ("dw")
+ "[]
+Below some empty line"
+ ("dw")
+ "[B]elow some empty line")
+ (evil-test-buffer
+ "[A]bove
+
+ Below some empty line with leading whitespace"
+ ("dw")
+ "[]
+
+ Below some empty line with leading whitespace"
+ ("dw")
+ "[]
+ Below some empty line with leading whitespace"
+ ("dw")
+ " [B]elow some empty line")
+ (evil-test-buffer
+ "Some line with trailing whitespace [ ] \n next line\n"
+ ("dw")
+ "Some line with trailing whitespace [ ]\n next line\n")
+ (evil-test-buffer
+ "[A]\n"
+ ("dw")
+ "[]\n"))
+ (ert-info ("End of buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("100w")
+ ";; This buffer is for notes[.]"
+ (should-error (execute-kbd-macro "w"))
+ (should-error (execute-kbd-macro "10w"))))
+ (ert-info ("Before last character in buffer")
+ (evil-test-buffer
+ "fo[o]."
+ ("w")
+ "foo[.]")
+ (evil-test-buffer
+ "fo[o] "
+ ("w")
+ "foo[ ]")
+ (evil-test-buffer
+ "[ ]e"
+ ("w")
+ " [e]")))
+
+(ert-deftest evil-test-forward-word-end ()
+ "Test `evil-forward-word-end'"
+ :tags '(evil motion)
+ (ert-info ("Non-word")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("e")
+ ";[;] This buffer is for notes."))
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("e")
+ ";; Thi[s] buffer is for notes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("3e")
+ ";; This buffer i[s] for notes."))
+ (ert-info ("With count on whitespace")
+ (evil-test-buffer
+ ";;[ ]This buffer is for notes."
+ ("3e")
+ ";; This buffer i[s] for notes."))
+ (ert-info ("Delete")
+ (evil-test-buffer
+ ";; This[-]buffer-is-for-notes."
+ ("de")
+ ";; This[-]is-for-notes."))
+ (ert-info ("Empty line")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ ("e")
+ "Above some line
+
+Belo[w] some empty line"))
+ (ert-info ("End of buffer")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("100e")
+ ";; This buffer is for notes[.]"
+ (should-error (execute-kbd-macro "e"))
+ (should-error (execute-kbd-macro "10e"))))
+ ;; In Vim, "de" may delete two words rather than one
+ ;; if the first word is only one letter. In Evil,
+ ;; "de" always deletes one word.
+ (ert-info ("Delete a single-letter word")
+ (evil-test-buffer
+ "a [b] c"
+ ("de")
+ "a [ ]c")))
+
+(ert-deftest evil-test-backward-word-begin ()
+ "Test `evil-backward-word-begin'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("b")
+ ";; This buffer is for [n]otes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("2b")
+ ";; This buffer is [f]or notes."))
+ (ert-info ("Empty line")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ ("b")
+ "Above some [l]ine
+
+Below some empty line"))
+ (ert-info ("With count on whitespace")
+ (evil-test-buffer
+ ";; This buffer is for[ ]notes."
+ ("2b")
+ ";; This buffer [i]s for notes."))
+ (ert-info ("Beginning of buffer")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("100b")
+ "[;]; This buffer is for notes."
+ (should-error (execute-kbd-macro "b"))
+ (should-error (execute-kbd-macro "10b")))))
+
+(ert-deftest evil-test-backward-word-end ()
+ "Test `evil-backward-word-end'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("ge")
+ ";; This buffer is for note[s]."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("2ge")
+ ";; This buffer is fo[r] notes."))
+ (ert-info ("Empty line")
+ (evil-test-buffer
+ "Above some line
+\[]
+Below some empty line"
+ ("ge")
+ "Above some lin[e]
+
+Below some empty line"))
+ (ert-info ("With count on whitespace")
+ (evil-test-buffer
+ ";; This buffer is for[ ]notes."
+ ("2ge")
+ ";; This buffer i[s] for notes."))
+ (ert-info ("Beginning of buffer")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("100ge")
+ "[;]; This buffer is for notes."
+ (should-error (execute-kbd-macro "ge"))
+ (should-error (execute-kbd-macro "10ge")))))
+
+(ert-deftest evil-test-forward-word-begin-cjk ()
+ "Test `evil-forward-word-begin' on CJK words"
+ :tags '(evil motion cjk)
+ (ert-info ("Latin / numeric")
+ (evil-test-buffer
+ "[a]bcd1234"
+ ("w")
+ "abcd123[4]"))
+ (ert-info ("Latin / Kanji")
+ (evil-test-buffer
+ "[a]bcd漢字"
+ ("w")
+ "abcd[漢]字"))
+ (ert-info ("Latin / Hiragana")
+ (evil-test-buffer
+ "[a]bcdひらがな"
+ ("w")
+ "abcd[ひ]らがな"))
+ (ert-info ("Latin / Katakana")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("w")
+ "abcd[カ]タカナ"))
+ (ert-info ("Latin / half-width Katakana")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("w")
+ "abcdカタカ[ナ]"))
+ (ert-info ("Latin / full-width alphabet")
+ (evil-test-buffer
+ "[a]bcdABC"
+ ("w")
+ "abcdAB[C]"))
+ (ert-info ("Latin / full-width numeric")
+ (evil-test-buffer
+ "[a]bcd123"
+ ("w")
+ "abcd12[3]"))
+ (ert-info ("Latin / Hangul")
+ (evil-test-buffer
+ "[a]bcd한글"
+ ("w")
+ "abcd[한]글"))
+ (ert-info ("numeric / Latin")
+ (evil-test-buffer
+ "[1]234abcd"
+ ("w")
+ "1234abc[d]"))
+ (ert-info ("numeric / Kanji")
+ (evil-test-buffer
+ "[1]234漢字"
+ ("w")
+ "1234[漢]字"))
+ (ert-info ("numeric / Hiragana")
+ (evil-test-buffer
+ "[1]234ひらがな"
+ ("w")
+ "1234[ひ]らがな"))
+ (ert-info ("numeric / Katakana")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("w")
+ "1234[カ]タカナ"))
+ (ert-info ("numeric / half-width Katakana")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("w")
+ "1234カタカ[ナ]"))
+ (ert-info ("numeric / full-width alphabet")
+ (evil-test-buffer
+ "[1]234ABC"
+ ("w")
+ "1234AB[C]"))
+ (ert-info ("numeric / full-width numeric")
+ (evil-test-buffer
+ "[1]234123"
+ ("w")
+ "123412[3]"))
+ (ert-info ("numeric / Hangul")
+ (evil-test-buffer
+ "[1]234한글"
+ ("w")
+ "1234[한]글"))
+ (ert-info ("Kanji / Latin")
+ (evil-test-buffer
+ "[漢]字abcd"
+ ("w")
+ "漢字[a]bcd"))
+ (ert-info ("Kanji / numeric")
+ (evil-test-buffer
+ "[漢]字1234"
+ ("w")
+ "漢字[1]234"))
+ (ert-info ("Kanji / Hiragana")
+ (evil-test-buffer
+ "[漢]字ひらがな"
+ ("w")
+ "漢字[ひ]らがな"))
+ (ert-info ("Kanji / Katakana")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("w")
+ "漢字[カ]タカナ"))
+ (ert-info ("Kanji / half-width Katakana")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("w")
+ "漢字[カ]タカナ"))
+ (ert-info ("Kanji / full-width alphabet")
+ (evil-test-buffer
+ "[漢]字ABC"
+ ("w")
+ "漢字[A]BC"))
+ (ert-info ("Kanji / full-width numeric")
+ (evil-test-buffer
+ "[漢]字123"
+ ("w")
+ "漢字[1]23"))
+ (ert-info ("Kanji / Hangul")
+ (evil-test-buffer
+ "[漢]字한글"
+ ("w")
+ "漢字[한]글"))
+ (ert-info ("Hiragana / Latin")
+ (evil-test-buffer
+ "[ひ]らがなabcd"
+ ("w")
+ "ひらがな[a]bcd"))
+ (ert-info ("Hiragana / numeric")
+ (evil-test-buffer
+ "[ひ]らがな1234"
+ ("w")
+ "ひらがな[1]234"))
+ (ert-info ("Hiragana / Kanji")
+ (evil-test-buffer
+ "[ひ]らがな漢字"
+ ("w")
+ "ひらがな[漢]字"))
+ (ert-info ("Hiragana / Katakana")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("w")
+ "ひらがな[カ]タカナ"))
+ (ert-info ("Hiragana / half-width Katakana")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("w")
+ "ひらがな[カ]タカナ"))
+ (ert-info ("Hiragana / full-width alphabet")
+ (evil-test-buffer
+ "[ひ]らがなABC"
+ ("w")
+ "ひらがな[A]BC"))
+ (ert-info ("Hiragana / full-width numeric")
+ (evil-test-buffer
+ "[ひ]らがな123"
+ ("w")
+ "ひらがな[1]23"))
+ (ert-info ("Hiragana / Hangul")
+ (evil-test-buffer
+ "[ひ]らがな한글"
+ ("w")
+ "ひらがな[한]글"))
+ (ert-info ("Katakana / Latin")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("w")
+ "カタカナ[a]bcd"))
+ (ert-info ("Katakana / numeric")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("w")
+ "カタカナ[1]234"))
+ (ert-info ("Katakana / Kanji")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("w")
+ "カタカナ[漢]字"))
+ (ert-info ("Katakana / Hiragana")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("w")
+ "カタカナ[ひ]らがな"))
+ (ert-info ("Katakana / half-width Katakana")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("w")
+ "カタカナ[カ]タカナ"))
+ (ert-info ("Katakana / full-width alphabet")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("w")
+ "カタカナ[A]BC"))
+ (ert-info ("Katakana / full-width numeric")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("w")
+ "カタカナ[1]23"))
+ (ert-info ("Katakana / Hangul")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("w")
+ "カタカナ[한]글"))
+ (ert-info ("half-width Katakana / Latin")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("w")
+ "カタカナabc[d]"))
+ (ert-info ("half-width Katakana / numeric")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("w")
+ "カタカナ123[4]"))
+ (ert-info ("half-width Katakana / Kanji")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("w")
+ "カタカナ[漢]字"))
+ (ert-info ("half-width Katakana / Hiragana")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("w")
+ "カタカナ[ひ]らがな"))
+ (ert-info ("half-width Katakana / Katakana")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("w")
+ "カタカナ[カ]タカナ"))
+ (ert-info ("half-width Katakana / full-width alphabet")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("w")
+ "カタカナAB[C]"))
+ (ert-info ("half-width Katakana / full-width numeric")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("w")
+ "カタカナ12[3]"))
+ (ert-info ("half-width Katakana / Hangul")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("w")
+ "カタカナ[한]글"))
+ (ert-info ("full-width alphabet / Latin")
+ (evil-test-buffer
+ "[A]BCabcd"
+ ("w")
+ "ABCabc[d]"))
+ (ert-info ("full-width alphabet / numeric")
+ (evil-test-buffer
+ "[A]BC1234"
+ ("w")
+ "ABC123[4]"))
+ (ert-info ("full-width alphabet / Kanji")
+ (evil-test-buffer
+ "[A]BC漢字"
+ ("w")
+ "ABC[漢]字"))
+ (ert-info ("full-width alphabet / Hiragana")
+ (evil-test-buffer
+ "[A]BCひらがな"
+ ("w")
+ "ABC[ひ]らがな"))
+ (ert-info ("full-width alphabet / Katakana")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("w")
+ "ABC[カ]タカナ"))
+ (ert-info ("full-width alphabet / half-width Katakana")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("w")
+ "ABCカタカ[ナ]"))
+ (ert-info ("full-width alphabet / full-width numeric")
+ (evil-test-buffer
+ "[A]BC123"
+ ("w")
+ "ABC12[3]"))
+ (ert-info ("full-width alphabet / Hangul")
+ (evil-test-buffer
+ "[A]BC한글"
+ ("w")
+ "ABC[한]글"))
+ (ert-info ("full-width numeric / Latin")
+ (evil-test-buffer
+ "[1]23abcd"
+ ("w")
+ "123abc[d]"))
+ (ert-info ("full-width numeric / numeric")
+ (evil-test-buffer
+ "[1]231234"
+ ("w")
+ "123123[4]"))
+ (ert-info ("full-width numeric / Kanji")
+ (evil-test-buffer
+ "[1]23漢字"
+ ("w")
+ "123[漢]字"))
+ (ert-info ("full-width numeric / Hiragana")
+ (evil-test-buffer
+ "[1]23ひらがな"
+ ("w")
+ "123[ひ]らがな"))
+ (ert-info ("full-width numeric / Katakana")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("w")
+ "123[カ]タカナ"))
+ (ert-info ("full-width numeric / half-width Katakana")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("w")
+ "123カタカ[ナ]"))
+ (ert-info ("full-width numeric / full-width alphabet")
+ (evil-test-buffer
+ "[1]23ABC"
+ ("w")
+ "123AB[C]"))
+ (ert-info ("full-width numeric / Hangul")
+ (evil-test-buffer
+ "[1]23한글"
+ ("w")
+ "123[한]글"))
+ (ert-info ("Hangul / Latin")
+ (evil-test-buffer
+ "[한]글abcd"
+ ("w")
+ "한글[a]bcd"))
+ (ert-info ("Hangul / numeric")
+ (evil-test-buffer
+ "[한]글1234"
+ ("w")
+ "한글[1]234"))
+ (ert-info ("Hangul / Kanji")
+ (evil-test-buffer
+ "[한]글漢字"
+ ("w")
+ "한글[漢]字"))
+ (ert-info ("Hangul / Hiragana")
+ (evil-test-buffer
+ "[한]글ひらがな"
+ ("w")
+ "한글[ひ]らがな"))
+ (ert-info ("Hangul / Katakana")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("w")
+ "한글[カ]タカナ"))
+ (ert-info ("Hangul / half-width Katakana")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("w")
+ "한글[カ]タカナ"))
+ (ert-info ("Hangul / full-width alphabet")
+ (evil-test-buffer
+ "[한]글ABC"
+ ("w")
+ "한글[A]BC"))
+ (ert-info ("Hangul / full-width numeric")
+ (evil-test-buffer
+ "[한]글123"
+ ("w")
+ "한글[1]23")))
+
+(ert-deftest evil-test-forward-word-end-cjk ()
+ "Test `evil-forward-word-end' on CJK words"
+ :tags '(evil motion cjk)
+ (ert-info ("Latin / numeric")
+ (evil-test-buffer
+ "[a]bcd1234"
+ ("e")
+ "abcd123[4]"))
+ (ert-info ("Latin / Kanji")
+ (evil-test-buffer
+ "[a]bcd漢字"
+ ("e")
+ "abc[d]漢字"))
+ (ert-info ("Latin / Hiragana")
+ (evil-test-buffer
+ "[a]bcdひらがな"
+ ("e")
+ "abc[d]ひらがな"))
+ (ert-info ("Latin / Katakana")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("e")
+ "abc[d]カタカナ"))
+ (ert-info ("Latin / half-width Katakana")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("e")
+ "abcdカタカ[ナ]"))
+ (ert-info ("Latin / full-width alphabet")
+ (evil-test-buffer
+ "[a]bcdABC"
+ ("e")
+ "abcdAB[C]"))
+ (ert-info ("Latin / full-width numeric")
+ (evil-test-buffer
+ "[a]bcd123"
+ ("e")
+ "abcd12[3]"))
+ (ert-info ("Latin / Hangul")
+ (evil-test-buffer
+ "[a]bcd한글"
+ ("e")
+ "abc[d]한글"))
+ (ert-info ("numeric / Latin")
+ (evil-test-buffer
+ "[1]234abcd"
+ ("e")
+ "1234abc[d]"))
+ (ert-info ("numeric / Kanji")
+ (evil-test-buffer
+ "[1]234漢字"
+ ("e")
+ "123[4]漢字"))
+ (ert-info ("numeric / Hiragana")
+ (evil-test-buffer
+ "[1]234ひらがな"
+ ("e")
+ "123[4]ひらがな"))
+ (ert-info ("numeric / Katakana")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("e")
+ "123[4]カタカナ"))
+ (ert-info ("numeric / half-width Katakana")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("e")
+ "1234カタカ[ナ]"))
+ (ert-info ("numeric / full-width alphabet")
+ (evil-test-buffer
+ "[1]234ABC"
+ ("e")
+ "1234AB[C]"))
+ (ert-info ("numeric / full-width numeric")
+ (evil-test-buffer
+ "[1]234123"
+ ("e")
+ "123412[3]"))
+ (ert-info ("numeric / Hangul")
+ (evil-test-buffer
+ "[1]234한글"
+ ("e")
+ "123[4]한글"))
+ (ert-info ("Kanji / Latin")
+ (evil-test-buffer
+ "[漢]字abcd"
+ ("e")
+ "漢[字]abcd"))
+ (ert-info ("Kanji / numeric")
+ (evil-test-buffer
+ "[漢]字1234"
+ ("e")
+ "漢[字]1234"))
+ (ert-info ("Kanji / Hiragana")
+ (evil-test-buffer
+ "[漢]字ひらがな"
+ ("e")
+ "漢[字]ひらがな"))
+ (ert-info ("Kanji / Katakana")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("e")
+ "漢[字]カタカナ"))
+ (ert-info ("Kanji / half-width Katakana")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("e")
+ "漢[字]カタカナ"))
+ (ert-info ("Kanji / full-width alphabet")
+ (evil-test-buffer
+ "[漢]字ABC"
+ ("e")
+ "漢[字]ABC"))
+ (ert-info ("Kanji / full-width numeric")
+ (evil-test-buffer
+ "[漢]字123"
+ ("e")
+ "漢[字]123"))
+ (ert-info ("Kanji / Hangul")
+ (evil-test-buffer
+ "[漢]字한글"
+ ("e")
+ "漢[字]한글"))
+ (ert-info ("Hiragana / Latin")
+ (evil-test-buffer
+ "[ひ]らがなabcd"
+ ("e")
+ "ひらが[な]abcd"))
+ (ert-info ("Hiragana / numeric")
+ (evil-test-buffer
+ "[ひ]らがな1234"
+ ("e")
+ "ひらが[な]1234"))
+ (ert-info ("Hiragana / Kanji")
+ (evil-test-buffer
+ "[ひ]らがな漢字"
+ ("e")
+ "ひらが[な]漢字"))
+ (ert-info ("Hiragana / Katakana")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("e")
+ "ひらが[な]カタカナ"))
+ (ert-info ("Hiragana / half-width Katakana")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("e")
+ "ひらが[な]カタカナ"))
+ (ert-info ("Hiragana / full-width alphabet")
+ (evil-test-buffer
+ "[ひ]らがなABC"
+ ("e")
+ "ひらが[な]ABC"))
+ (ert-info ("Hiragana / full-width numeric")
+ (evil-test-buffer
+ "[ひ]らがな123"
+ ("e")
+ "ひらが[な]123"))
+ (ert-info ("Hiragana / Hangul")
+ (evil-test-buffer
+ "[ひ]らがな한글"
+ ("e")
+ "ひらが[な]한글"))
+ (ert-info ("Katakana / Latin")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("e")
+ "カタカ[ナ]abcd"))
+ (ert-info ("Katakana / numeric")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("e")
+ "カタカ[ナ]1234"))
+ (ert-info ("Katakana / Kanji")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("e")
+ "カタカ[ナ]漢字"))
+ (ert-info ("Katakana / Hiragana")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("e")
+ "カタカ[ナ]ひらがな"))
+ (ert-info ("Katakana / half-width Katakana")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("e")
+ "カタカ[ナ]カタカナ"))
+ (ert-info ("Katakana / full-width alphabet")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("e")
+ "カタカ[ナ]ABC"))
+ (ert-info ("Katakana / full-width numeric")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("e")
+ "カタカ[ナ]123"))
+ (ert-info ("Katakana / Hangul")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("e")
+ "カタカ[ナ]한글"))
+ (ert-info ("half-width Katakana / Latin")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("e")
+ "カタカナabc[d]"))
+ (ert-info ("half-width Katakana / numeric")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("e")
+ "カタカナ123[4]"))
+ (ert-info ("half-width Katakana / Kanji")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("e")
+ "カタカ[ナ]漢字"))
+ (ert-info ("half-width Katakana / Hiragana")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("e")
+ "カタカ[ナ]ひらがな"))
+ (ert-info ("half-width Katakana / Katakana")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("e")
+ "カタカ[ナ]カタカナ"))
+ (ert-info ("half-width Katakana / full-width alphabet")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("e")
+ "カタカナAB[C]"))
+ (ert-info ("half-width Katakana / full-width numeric")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("e")
+ "カタカナ12[3]"))
+ (ert-info ("half-width Katakana / Hangul")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("e")
+ "カタカ[ナ]한글"))
+ (ert-info ("full-width alphabet / Latin")
+ (evil-test-buffer
+ "[A]BCabcd"
+ ("e")
+ "ABCabc[d]"))
+ (ert-info ("full-width alphabet / numeric")
+ (evil-test-buffer
+ "[A]BC1234"
+ ("e")
+ "ABC123[4]"))
+ (ert-info ("full-width alphabet / Kanji")
+ (evil-test-buffer
+ "[A]BC漢字"
+ ("e")
+ "AB[C]漢字"))
+ (ert-info ("full-width alphabet / Hiragana")
+ (evil-test-buffer
+ "[A]BCひらがな"
+ ("e")
+ "AB[C]ひらがな"))
+ (ert-info ("full-width alphabet / Katakana")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("e")
+ "AB[C]カタカナ"))
+ (ert-info ("full-width alphabet / half-width Katakana")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("e")
+ "ABCカタカ[ナ]"))
+ (ert-info ("full-width alphabet / full-width numeric")
+ (evil-test-buffer
+ "[A]BC123"
+ ("e")
+ "ABC12[3]"))
+ (ert-info ("full-width alphabet / Hangul")
+ (evil-test-buffer
+ "[A]BC한글"
+ ("e")
+ "AB[C]한글"))
+ (ert-info ("full-width numeric / Latin")
+ (evil-test-buffer
+ "[1]23abcd"
+ ("e")
+ "123abc[d]"))
+ (ert-info ("full-width numeric / numeric")
+ (evil-test-buffer
+ "[1]231234"
+ ("e")
+ "123123[4]"))
+ (ert-info ("full-width numeric / Kanji")
+ (evil-test-buffer
+ "[1]23漢字"
+ ("e")
+ "12[3]漢字"))
+ (ert-info ("full-width numeric / Hiragana")
+ (evil-test-buffer
+ "[1]23ひらがな"
+ ("e")
+ "12[3]ひらがな"))
+ (ert-info ("full-width numeric / Katakana")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("e")
+ "12[3]カタカナ"))
+ (ert-info ("full-width numeric / half-width Katakana")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("e")
+ "123カタカ[ナ]"))
+ (ert-info ("full-width numeric / full-width alphabet")
+ (evil-test-buffer
+ "[1]23ABC"
+ ("e")
+ "123AB[C]"))
+ (ert-info ("full-width numeric / Hangul")
+ (evil-test-buffer
+ "[1]23한글"
+ ("e")
+ "12[3]한글"))
+ (ert-info ("Hangul / Latin")
+ (evil-test-buffer
+ "[한]글abcd"
+ ("e")
+ "한[글]abcd"))
+ (ert-info ("Hangul / numeric")
+ (evil-test-buffer
+ "[한]글1234"
+ ("e")
+ "한[글]1234"))
+ (ert-info ("Hangul / Kanji")
+ (evil-test-buffer
+ "[한]글漢字"
+ ("e")
+ "한[글]漢字"))
+ (ert-info ("Hangul / Hiragana")
+ (evil-test-buffer
+ "[한]글ひらがな"
+ ("e")
+ "한[글]ひらがな"))
+ (ert-info ("Hangul / Katakana")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("e")
+ "한[글]カタカナ"))
+ (ert-info ("Hangul / half-width Katakana")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("e")
+ "한[글]カタカナ"))
+ (ert-info ("Hangul / full-width alphabet")
+ (evil-test-buffer
+ "[한]글ABC"
+ ("e")
+ "한[글]ABC"))
+ (ert-info ("Hangul / full-width numeric")
+ (evil-test-buffer
+ "[한]글123"
+ ("e")
+ "한[글]123")))
+
+(ert-deftest evil-test-backword-word-begin-cjk ()
+ "Test `evil-backward-word-begin' on CJK words"
+ :tags '(evil motion cjk)
+ (ert-info ("Latin / numeric")
+ (evil-test-buffer
+ "abcd123[4]"
+ ("b")
+ "[a]bcd1234"))
+ (ert-info ("Latin / Kanji")
+ (evil-test-buffer
+ "abcd漢[字]"
+ ("b")
+ "abcd[漢]字"))
+ (ert-info ("Latin / Hiragana")
+ (evil-test-buffer
+ "abcdひらが[な]"
+ ("b")
+ "abcd[ひ]らがな"))
+ (ert-info ("Latin / Katakana")
+ (evil-test-buffer
+ "abcdカタカ[ナ]"
+ ("b")
+ "abcd[カ]タカナ"))
+ (ert-info ("Latin / half-width Katakana")
+ (evil-test-buffer
+ "abcdカタカ[ナ]"
+ ("b")
+ "[a]bcdカタカナ"))
+ (ert-info ("Latin / full-width alphabet")
+ (evil-test-buffer
+ "abcdAB[C]"
+ ("b")
+ "[a]bcdABC"))
+ (ert-info ("Latin / full-width numeric")
+ (evil-test-buffer
+ "abcd12[3]"
+ ("b")
+ "[a]bcd123"))
+ (ert-info ("Latin / Hangul")
+ (evil-test-buffer
+ "abcd한[글]"
+ ("b")
+ "abcd[한]글"))
+ (ert-info ("numeric / Latin")
+ (evil-test-buffer
+ "1234abc[d]"
+ ("b")
+ "[1]234abcd"))
+ (ert-info ("numeric / Kanji")
+ (evil-test-buffer
+ "1234漢[字]"
+ ("b")
+ "1234[漢]字"))
+ (ert-info ("numeric / Hiragana")
+ (evil-test-buffer
+ "1234ひらが[な]"
+ ("b")
+ "1234[ひ]らがな"))
+ (ert-info ("numeric / Katakana")
+ (evil-test-buffer
+ "1234カタカ[ナ]"
+ ("b")
+ "1234[カ]タカナ"))
+ (ert-info ("numeric / half-width Katakana")
+ (evil-test-buffer
+ "1234カタカ[ナ]"
+ ("b")
+ "[1]234カタカナ"))
+ (ert-info ("numeric / full-width alphabet")
+ (evil-test-buffer
+ "1234AB[C]"
+ ("b")
+ "[1]234ABC"))
+ (ert-info ("numeric / full-width numeric")
+ (evil-test-buffer
+ "123412[3]"
+ ("b")
+ "[1]234123"))
+ (ert-info ("numeric / Hangul")
+ (evil-test-buffer
+ "1234한[글]"
+ ("b")
+ "1234[한]글"))
+ (ert-info ("Kanji / Latin")
+ (evil-test-buffer
+ "漢字abc[d]"
+ ("b")
+ "漢字[a]bcd"))
+ (ert-info ("Kanji / numeric")
+ (evil-test-buffer
+ "漢字123[4]"
+ ("b")
+ "漢字[1]234"))
+ (ert-info ("Kanji / Hiragana")
+ (evil-test-buffer
+ "漢字ひらが[な]"
+ ("b")
+ "漢字[ひ]らがな"))
+ (ert-info ("Kanji / Katakana")
+ (evil-test-buffer
+ "漢字カタカ[ナ]"
+ ("b")
+ "漢字[カ]タカナ"))
+ (ert-info ("Kanji / half-width Katakana")
+ (evil-test-buffer
+ "漢字カタカ[ナ]"
+ ("b")
+ "漢字[カ]タカナ"))
+ (ert-info ("Kanji / full-width alphabet")
+ (evil-test-buffer
+ "漢字AB[C]"
+ ("b")
+ "漢字[A]BC"))
+ (ert-info ("Kanji / full-width numeric")
+ (evil-test-buffer
+ "漢字12[3]"
+ ("b")
+ "漢字[1]23"))
+ (ert-info ("Kanji / Hangul")
+ (evil-test-buffer
+ "漢字한[글]"
+ ("b")
+ "漢字[한]글"))
+ (ert-info ("Hiragana / Latin")
+ (evil-test-buffer
+ "ひらがなabc[d]"
+ ("b")
+ "ひらがな[a]bcd"))
+ (ert-info ("Hiragana / numeric")
+ (evil-test-buffer
+ "ひらがな123[4]"
+ ("b")
+ "ひらがな[1]234"))
+ (ert-info ("Hiragana / Kanji")
+ (evil-test-buffer
+ "ひらがな漢[字]"
+ ("b")
+ "ひらがな[漢]字"))
+ (ert-info ("Hiragana / Katakana")
+ (evil-test-buffer
+ "ひらがなカタカ[ナ]"
+ ("b")
+ "ひらがな[カ]タカナ"))
+ (ert-info ("Hiragana / half-width Katakana")
+ (evil-test-buffer
+ "ひらがなカタカ[ナ]"
+ ("b")
+ "ひらがな[カ]タカナ"))
+ (ert-info ("Hiragana / full-width alphabet")
+ (evil-test-buffer
+ "ひらがなAB[C]"
+ ("b")
+ "ひらがな[A]BC"))
+ (ert-info ("Hiragana / full-width numeric")
+ (evil-test-buffer
+ "ひらがな12[3]"
+ ("b")
+ "ひらがな[1]23"))
+ (ert-info ("Hiragana / Hangul")
+ (evil-test-buffer
+ "ひらがな한[글]"
+ ("b")
+ "ひらがな[한]글"))
+ (ert-info ("Katakana / Latin")
+ (evil-test-buffer
+ "カタカナabc[d]"
+ ("b")
+ "カタカナ[a]bcd"))
+ (ert-info ("Katakana / numeric")
+ (evil-test-buffer
+ "カタカナ123[4]"
+ ("b")
+ "カタカナ[1]234"))
+ (ert-info ("Katakana / Kanji")
+ (evil-test-buffer
+ "カタカナ漢[字]"
+ ("b")
+ "カタカナ[漢]字"))
+ (ert-info ("Katakana / Hiragana")
+ (evil-test-buffer
+ "カタカナひらが[な]"
+ ("b")
+ "カタカナ[ひ]らがな"))
+ (ert-info ("Katakana / half-width Katakana")
+ (evil-test-buffer
+ "カタカナカタカ[ナ]"
+ ("b")
+ "カタカナ[カ]タカナ"))
+ (ert-info ("Katakana / full-width alphabet")
+ (evil-test-buffer
+ "カタカナAB[C]"
+ ("b")
+ "カタカナ[A]BC"))
+ (ert-info ("Katakana / full-width numeric")
+ (evil-test-buffer
+ "カタカナ12[3]"
+ ("b")
+ "カタカナ[1]23"))
+ (ert-info ("Katakana / Hangul")
+ (evil-test-buffer
+ "カタカナ한[글]"
+ ("b")
+ "カタカナ[한]글"))
+ (ert-info ("half-width Katakana / Latin")
+ (evil-test-buffer
+ "カタカナabc[d]"
+ ("b")
+ "[カ]タカナabcd"))
+ (ert-info ("half-width Katakana / numeric")
+ (evil-test-buffer
+ "カタカナ123[4]"
+ ("b")
+ "[カ]タカナ1234"))
+ (ert-info ("half-width Katakana / Kanji")
+ (evil-test-buffer
+ "カタカナ漢[字]"
+ ("b")
+ "カタカナ[漢]字"))
+ (ert-info ("half-width Katakana / Hiragana")
+ (evil-test-buffer
+ "カタカナひらが[な]"
+ ("b")
+ "カタカナ[ひ]らがな"))
+ (ert-info ("half-width Katakana / Katakana")
+ (evil-test-buffer
+ "カタカナカタカ[ナ]"
+ ("b")
+ "カタカナ[カ]タカナ"))
+ (ert-info ("half-width Katakana / full-width alphabet")
+ (evil-test-buffer
+ "カタカナAB[C]"
+ ("b")
+ "[カ]タカナABC"))
+ (ert-info ("half-width Katakana / full-width numeric")
+ (evil-test-buffer
+ "カタカナ12[3]"
+ ("b")
+ "[カ]タカナ123"))
+ (ert-info ("half-width Katakana / Hangul")
+ (evil-test-buffer
+ "カタカナ한[글]"
+ ("b")
+ "カタカナ[한]글"))
+ (ert-info ("full-width alphabet / Latin")
+ (evil-test-buffer
+ "ABCabc[d]"
+ ("b")
+ "[A]BCabcd"))
+ (ert-info ("full-width alphabet / numeric")
+ (evil-test-buffer
+ "ABC123[4]"
+ ("b")
+ "[A]BC1234"))
+ (ert-info ("full-width alphabet / Kanji")
+ (evil-test-buffer
+ "ABC漢[字]"
+ ("b")
+ "ABC[漢]字"))
+ (ert-info ("full-width alphabet / Hiragana")
+ (evil-test-buffer
+ "ABCひらが[な]"
+ ("b")
+ "ABC[ひ]らがな"))
+ (ert-info ("full-width alphabet / Katakana")
+ (evil-test-buffer
+ "ABCカタカ[ナ]"
+ ("b")
+ "ABC[カ]タカナ"))
+ (ert-info ("full-width alphabet / half-width Katakana")
+ (evil-test-buffer
+ "ABCカタカ[ナ]"
+ ("b")
+ "[A]BCカタカナ"))
+ (ert-info ("full-width alphabet / full-width numeric")
+ (evil-test-buffer
+ "ABC12[3]"
+ ("b")
+ "[A]BC123"))
+ (ert-info ("full-width alphabet / Hangul")
+ (evil-test-buffer
+ "ABC한[글]"
+ ("b")
+ "ABC[한]글"))
+ (ert-info ("full-width numeric / Latin")
+ (evil-test-buffer
+ "123abc[d]"
+ ("b")
+ "[1]23abcd"))
+ (ert-info ("full-width numeric / numeric")
+ (evil-test-buffer
+ "123123[4]"
+ ("b")
+ "[1]231234"))
+ (ert-info ("full-width numeric / Kanji")
+ (evil-test-buffer
+ "123漢[字]"
+ ("b")
+ "123[漢]字"))
+ (ert-info ("full-width numeric / Hiragana")
+ (evil-test-buffer
+ "123ひらが[な]"
+ ("b")
+ "123[ひ]らがな"))
+ (ert-info ("full-width numeric / Katakana")
+ (evil-test-buffer
+ "123カタカ[ナ]"
+ ("b")
+ "123[カ]タカナ"))
+ (ert-info ("full-width numeric / half-width Katakana")
+ (evil-test-buffer
+ "123カタカ[ナ]"
+ ("b")
+ "[1]23カタカナ"))
+ (ert-info ("full-width numeric / full-width alphabet")
+ (evil-test-buffer
+ "123AB[C]"
+ ("b")
+ "[1]23ABC"))
+ (ert-info ("full-width numeric / Hangul")
+ (evil-test-buffer
+ "123한[글]"
+ ("b")
+ "123[한]글"))
+ (ert-info ("Hangul / Latin")
+ (evil-test-buffer
+ "한글abc[d]"
+ ("b")
+ "한글[a]bcd"))
+ (ert-info ("Hangul / numeric")
+ (evil-test-buffer
+ "한글123[4]"
+ ("b")
+ "한글[1]234"))
+ (ert-info ("Hangul / Kanji")
+ (evil-test-buffer
+ "한글漢[字]"
+ ("b")
+ "한글[漢]字"))
+ (ert-info ("Hangul / Hiragana")
+ (evil-test-buffer
+ "한글ひらが[な]"
+ ("b")
+ "한글[ひ]らがな"))
+ (ert-info ("Hangul / Katakana")
+ (evil-test-buffer
+ "한글カタカ[ナ]"
+ ("b")
+ "한글[カ]タカナ"))
+ (ert-info ("Hangul / half-width Katakana")
+ (evil-test-buffer
+ "한글カタカ[ナ]"
+ ("b")
+ "한글[カ]タカナ"))
+ (ert-info ("Hangul / full-width alphabet")
+ (evil-test-buffer
+ "한글AB[C]"
+ ("b")
+ "한글[A]BC"))
+ (ert-info ("Hangul / full-width numeric")
+ (evil-test-buffer
+ "한글12[3]"
+ ("b")
+ "한글[1]23")))
+
+(ert-deftest evil-test-backword-word-end-cjk ()
+ "Test `evil-backward-word-end' on CJK words"
+ :tags '(evil motion cjk)
+ (ert-info ("Latin / numeric")
+ (evil-test-buffer
+ "abcd123[4]"
+ ("ge")
+ "[a]bcd1234"))
+ (ert-info ("Latin / Kanji")
+ (evil-test-buffer
+ "abcd漢[字]"
+ ("ge")
+ "abc[d]漢字"))
+ (ert-info ("Latin / Hiragana")
+ (evil-test-buffer
+ "abcdひらが[な]"
+ ("ge")
+ "abc[d]ひらがな"))
+ (ert-info ("Latin / Katakana")
+ (evil-test-buffer
+ "abcdカタカ[ナ]"
+ ("ge")
+ "abc[d]カタカナ"))
+ (ert-info ("Latin / half-width Katakana")
+ (evil-test-buffer
+ "abcdカタカ[ナ]"
+ ("ge")
+ "[a]bcdカタカナ"))
+ (ert-info ("Latin / full-width alphabet")
+ (evil-test-buffer
+ "abcdAB[C]"
+ ("ge")
+ "[a]bcdABC"))
+ (ert-info ("Latin / full-width numeric")
+ (evil-test-buffer
+ "abcd12[3]"
+ ("ge")
+ "[a]bcd123"))
+ (ert-info ("Latin / Hangul")
+ (evil-test-buffer
+ "abcd한[글]"
+ ("ge")
+ "abc[d]한글"))
+ (ert-info ("numeric / Latin")
+ (evil-test-buffer
+ "1234abc[d]"
+ ("ge")
+ "[1]234abcd"))
+ (ert-info ("numeric / Kanji")
+ (evil-test-buffer
+ "1234漢[字]"
+ ("ge")
+ "123[4]漢字"))
+ (ert-info ("numeric / Hiragana")
+ (evil-test-buffer
+ "1234ひらが[な]"
+ ("ge")
+ "123[4]ひらがな"))
+ (ert-info ("numeric / Katakana")
+ (evil-test-buffer
+ "1234カタカ[ナ]"
+ ("ge")
+ "123[4]カタカナ"))
+ (ert-info ("numeric / half-width Katakana")
+ (evil-test-buffer
+ "1234カタカ[ナ]"
+ ("ge")
+ "[1]234カタカナ"))
+ (ert-info ("numeric / full-width alphabet")
+ (evil-test-buffer
+ "1234AB[C]"
+ ("ge")
+ "[1]234ABC"))
+ (ert-info ("numeric / full-width numeric")
+ (evil-test-buffer
+ "123412[3]"
+ ("ge")
+ "[1]234123"))
+ (ert-info ("numeric / Hangul")
+ (evil-test-buffer
+ "1234한[글]"
+ ("ge")
+ "123[4]한글"))
+ (ert-info ("Kanji / Latin")
+ (evil-test-buffer
+ "漢字abc[d]"
+ ("ge")
+ "漢[字]abcd"))
+ (ert-info ("Kanji / numeric")
+ (evil-test-buffer
+ "漢字123[4]"
+ ("ge")
+ "漢[字]1234"))
+ (ert-info ("Kanji / Hiragana")
+ (evil-test-buffer
+ "漢字ひらが[な]"
+ ("ge")
+ "漢[字]ひらがな"))
+ (ert-info ("Kanji / Katakana")
+ (evil-test-buffer
+ "漢字カタカ[ナ]"
+ ("ge")
+ "漢[字]カタカナ"))
+ (ert-info ("Kanji / half-width Katakana")
+ (evil-test-buffer
+ "漢字カタカ[ナ]"
+ ("ge")
+ "漢[字]カタカナ"))
+ (ert-info ("Kanji / full-width alphabet")
+ (evil-test-buffer
+ "漢字AB[C]"
+ ("ge")
+ "漢[字]ABC"))
+ (ert-info ("Kanji / full-width numeric")
+ (evil-test-buffer
+ "漢字12[3]"
+ ("ge")
+ "漢[字]123"))
+ (ert-info ("Kanji / Hangul")
+ (evil-test-buffer
+ "漢字한[글]"
+ ("ge")
+ "漢[字]한글"))
+ (ert-info ("Hiragana / Latin")
+ (evil-test-buffer
+ "ひらがなabc[d]"
+ ("ge")
+ "ひらが[な]abcd"))
+ (ert-info ("Hiragana / numeric")
+ (evil-test-buffer
+ "ひらがな123[4]"
+ ("ge")
+ "ひらが[な]1234"))
+ (ert-info ("Hiragana / Kanji")
+ (evil-test-buffer
+ "ひらがな漢[字]"
+ ("ge")
+ "ひらが[な]漢字"))
+ (ert-info ("Hiragana / Katakana")
+ (evil-test-buffer
+ "ひらがなカタカ[ナ]"
+ ("ge")
+ "ひらが[な]カタカナ"))
+ (ert-info ("Hiragana / half-width Katakana")
+ (evil-test-buffer
+ "ひらがなカタカ[ナ]"
+ ("ge")
+ "ひらが[な]カタカナ"))
+ (ert-info ("Hiragana / full-width alphabet")
+ (evil-test-buffer
+ "ひらがなAB[C]"
+ ("ge")
+ "ひらが[な]ABC"))
+ (ert-info ("Hiragana / full-width numeric")
+ (evil-test-buffer
+ "ひらがな12[3]"
+ ("ge")
+ "ひらが[な]123"))
+ (ert-info ("Hiragana / Hangul")
+ (evil-test-buffer
+ "ひらがな한[글]"
+ ("ge")
+ "ひらが[な]한글"))
+ (ert-info ("Katakana / Latin")
+ (evil-test-buffer
+ "カタカナabc[d]"
+ ("ge")
+ "カタカ[ナ]abcd"))
+ (ert-info ("Katakana / numeric")
+ (evil-test-buffer
+ "カタカナ123[4]"
+ ("ge")
+ "カタカ[ナ]1234"))
+ (ert-info ("Katakana / Kanji")
+ (evil-test-buffer
+ "カタカナ漢[字]"
+ ("ge")
+ "カタカ[ナ]漢字"))
+ (ert-info ("Katakana / Hiragana")
+ (evil-test-buffer
+ "カタカナひらが[な]"
+ ("ge")
+ "カタカ[ナ]ひらがな"))
+ (ert-info ("Katakana / half-width Katakana")
+ (evil-test-buffer
+ "カタカナカタカ[ナ]"
+ ("ge")
+ "カタカ[ナ]カタカナ"))
+ (ert-info ("Katakana / full-width alphabet")
+ (evil-test-buffer
+ "カタカナAB[C]"
+ ("ge")
+ "カタカ[ナ]ABC"))
+ (ert-info ("Katakana / full-width numeric")
+ (evil-test-buffer
+ "カタカナ12[3]"
+ ("ge")
+ "カタカ[ナ]123"))
+ (ert-info ("Katakana / Hangul")
+ (evil-test-buffer
+ "カタカナ한[글]"
+ ("ge")
+ "カタカ[ナ]한글"))
+ (ert-info ("half-width Katakana / Latin")
+ (evil-test-buffer
+ "カタカナabc[d]"
+ ("ge")
+ "[カ]タカナabcd"))
+ (ert-info ("half-width Katakana / numeric")
+ (evil-test-buffer
+ "カタカナ123[4]"
+ ("ge")
+ "[カ]タカナ1234"))
+ (ert-info ("half-width Katakana / Kanji")
+ (evil-test-buffer
+ "カタカナ漢[字]"
+ ("ge")
+ "カタカ[ナ]漢字"))
+ (ert-info ("half-width Katakana / Hiragana")
+ (evil-test-buffer
+ "カタカナひらが[な]"
+ ("ge")
+ "カタカ[ナ]ひらがな"))
+ (ert-info ("half-width Katakana / Katakana")
+ (evil-test-buffer
+ "カタカナカタカ[ナ]"
+ ("ge")
+ "カタカ[ナ]カタカナ"))
+ (ert-info ("half-width Katakana / full-width alphabet")
+ (evil-test-buffer
+ "カタカナAB[C]"
+ ("ge")
+ "[カ]タカナABC"))
+ (ert-info ("half-width Katakana / full-width numeric")
+ (evil-test-buffer
+ "カタカナ12[3]"
+ ("ge")
+ "[カ]タカナ123"))
+ (ert-info ("half-width Katakana / Hangul")
+ (evil-test-buffer
+ "カタカナ한[글]"
+ ("ge")
+ "カタカ[ナ]한글"))
+ (ert-info ("full-width alphabet / Latin")
+ (evil-test-buffer
+ "ABCabc[d]"
+ ("ge")
+ "[A]BCabcd"))
+ (ert-info ("full-width alphabet / numeric")
+ (evil-test-buffer
+ "ABC123[4]"
+ ("ge")
+ "[A]BC1234"))
+ (ert-info ("full-width alphabet / Kanji")
+ (evil-test-buffer
+ "ABC漢[字]"
+ ("ge")
+ "AB[C]漢字"))
+ (ert-info ("full-width alphabet / Hiragana")
+ (evil-test-buffer
+ "ABCひらが[な]"
+ ("ge")
+ "AB[C]ひらがな"))
+ (ert-info ("full-width alphabet / Katakana")
+ (evil-test-buffer
+ "ABCカタカ[ナ]"
+ ("ge")
+ "AB[C]カタカナ"))
+ (ert-info ("full-width alphabet / half-width Katakana")
+ (evil-test-buffer
+ "ABCカタカ[ナ]"
+ ("ge")
+ "[A]BCカタカナ"))
+ (ert-info ("full-width alphabet / full-width numeric")
+ (evil-test-buffer
+ "ABC12[3]"
+ ("ge")
+ "[A]BC123"))
+ (ert-info ("full-width alphabet / Hangul")
+ (evil-test-buffer
+ "ABC한[글]"
+ ("ge")
+ "AB[C]한글"))
+ (ert-info ("full-width numeric / Latin")
+ (evil-test-buffer
+ "123abc[d]"
+ ("ge")
+ "[1]23abcd"))
+ (ert-info ("full-width numeric / numeric")
+ (evil-test-buffer
+ "123123[4]"
+ ("ge")
+ "[1]231234"))
+ (ert-info ("full-width numeric / Kanji")
+ (evil-test-buffer
+ "123漢[字]"
+ ("ge")
+ "12[3]漢字"))
+ (ert-info ("full-width numeric / Hiragana")
+ (evil-test-buffer
+ "123ひらが[な]"
+ ("ge")
+ "12[3]ひらがな"))
+ (ert-info ("full-width numeric / Katakana")
+ (evil-test-buffer
+ "123カタカ[ナ]"
+ ("ge")
+ "12[3]カタカナ"))
+ (ert-info ("full-width numeric / half-width Katakana")
+ (evil-test-buffer
+ "123カタカ[ナ]"
+ ("ge")
+ "[1]23カタカナ"))
+ (ert-info ("full-width numeric / full-width alphabet")
+ (evil-test-buffer
+ "123AB[C]"
+ ("ge")
+ "[1]23ABC"))
+ (ert-info ("full-width numeric / Hangul")
+ (evil-test-buffer
+ "123한[글]"
+ ("ge")
+ "12[3]한글"))
+ (ert-info ("Hangul / Latin")
+ (evil-test-buffer
+ "한글abc[d]"
+ ("ge")
+ "한[글]abcd"))
+ (ert-info ("Hangul / numeric")
+ (evil-test-buffer
+ "한글123[4]"
+ ("ge")
+ "한[글]1234"))
+ (ert-info ("Hangul / Kanji")
+ (evil-test-buffer
+ "한글漢[字]"
+ ("ge")
+ "한[글]漢字"))
+ (ert-info ("Hangul / Hiragana")
+ (evil-test-buffer
+ "한글ひらが[な]"
+ ("ge")
+ "한[글]ひらがな"))
+ (ert-info ("Hangul / Katakana")
+ (evil-test-buffer
+ "한글カタカ[ナ]"
+ ("ge")
+ "한[글]カタカナ"))
+ (ert-info ("Hangul / half-width Katakana")
+ (evil-test-buffer
+ "한글カタカ[ナ]"
+ ("ge")
+ "한[글]カタカナ"))
+ (ert-info ("Hangul / full-width alphabet")
+ (evil-test-buffer
+ "한글AB[C]"
+ ("ge")
+ "한[글]ABC"))
+ (ert-info ("Hangul / full-width numeric")
+ (evil-test-buffer
+ "한글12[3]"
+ ("ge")
+ "한[글]123")))
+
+(ert-deftest evil-test-forward-paragraph ()
+ "Test `evil-forward-paragraph'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "[A]bove some line
+
+Below some empty line"
+ ("}")
+ "Above some line
+\[]
+Below some empty line"))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "[A]bove some line
+
+Below some empty line"
+ ("2}")
+ "Above some line
+
+Below some empty lin[e]"))
+ (ert-info ("End of buffer")
+ (evil-test-buffer
+ "[B]elow some empty line"
+ ("100}")
+ "Below some empty lin[e]"
+ (should-error (execute-kbd-macro "}"))
+ (should-error (execute-kbd-macro "42}"))))
+ (ert-info ("End of buffer with newline")
+ (evil-test-buffer
+ "[B]elow some empty line\n\n"
+ ("100}")
+ "Below some empty line\n\n[]"
+ (should-error (execute-kbd-macro "}"))
+ (should-error (execute-kbd-macro "42}")))))
+
+(ert-deftest evil-test-backward-paragraph ()
+ "Test `evil-backward-paragraph'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "Above some line
+
+Below some empty lin[e]"
+ ("{")
+ "Above some line
+\[]
+Below some empty line"))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "Above some line
+
+Below some empty lin[e]"
+ ("2{")
+ "[A]bove some line
+
+Below some empty line"))
+ (ert-info ("Beginning of buffer")
+ (evil-test-buffer
+ "Above some line
+
+Below some empty lin[e]"
+ ("100{")
+ "[A]bove some line
+
+Below some empty line"
+ (should-error (execute-kbd-macro "{"))
+ (should-error (execute-kbd-macro "42{"))))
+ (ert-info ("Beginning of buffer with newlines")
+ (evil-test-buffer
+ "\n\nAbove some line
+
+Below some empty lin[e]"
+ ("100{")
+ "[]\n\nAbove some line
+
+Below some empty line"
+ (should-error (execute-kbd-macro "{"))
+ (should-error (execute-kbd-macro "42{")))))
+
+(ert-deftest evil-test-forward-sentence ()
+ "Test `evil-forward-sentence'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line."
+ (")")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. [I]f you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line."
+ (")")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+\[]
+Below some empty line."
+ (")")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+\[B]elow some empty line."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line."
+ ("2)")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+\[]
+Below some empty line."
+ ("2)")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line[.]"))
+ (ert-info ("End of buffer")
+ (evil-test-buffer
+ "[B]elow some empty line."
+ ("100)")
+ "Below some empty line[.]"
+ (should-error (execute-kbd-macro ")"))
+ (should-error (execute-kbd-macro "42)"))))
+ (ert-info ("End of buffer with newline")
+ (evil-test-buffer
+ "[B]elow some empty line.\n\n"
+ (")")
+ "Below some empty line.\n[\n]"
+ (")")
+ "Below some empty line.\n\n[]"
+ (should-error (execute-kbd-macro ")"))
+ (should-error (execute-kbd-macro "42)")))))
+
+(ert-deftest evil-test-backward-sentence ()
+ "Test `evil-backward-sentence'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line[.]"
+ ("(")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+\[B]elow some empty line."
+ ("(")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+\[]
+Below some empty line."
+ ("(")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. [I]f you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line."
+ ("(")
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line[.]"
+ ("2(")
+ ";; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+\[]
+Below some empty line."
+ ("2(")
+ "[;]; This buffer is for notes you don't want to save,
+;; and for Lisp evaluation. If you want to create a file,
+;; visit that file with C-x C-f.
+
+Below some empty line."))
+ (ert-info ("Beginning of buffer")
+ (evil-test-buffer
+ ";; This buffer is for notes you don't want to save[.]"
+ ("100(")
+ "[;]; This buffer is for notes you don't want to save."
+ (should-error (execute-kbd-macro "("))
+ (should-error (execute-kbd-macro "42("))))
+ (ert-info ("Beginning of buffer with newlines")
+ (evil-test-buffer
+ "\n\n;; This buffer is for notes you don't want to save[.]"
+ ("100(")
+ "[]\n\n;; This buffer is for notes you don't want to save."
+ (should-error (execute-kbd-macro "("))
+ (should-error (execute-kbd-macro "42(")))))
+
+(ert-deftest evil-test-find-char ()
+ "Test `evil-find-char'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("fT")
+ ";; [T]his buffer is for notes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("2fe")
+ ";; This buffer is for not[e]s."))
+ (ert-info ("Repeat")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("fe;")
+ ";; This buffer is for not[e]s."))
+ (ert-info ("Repeat backward")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("2fe,")
+ ";; This buff[e]r is for notes."))
+ (ert-info ("No match")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ (should-error (execute-kbd-macro "fL"))))
+ (ert-info ("End of line")
+ (let ((evil-cross-lines t))
+ (evil-test-buffer
+ "[;]; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("fL")
+ ";; This buffer is for notes,
+;; and for [L]isp evaluation.")))
+ (ert-info ("Empty line")
+ (evil-test-buffer
+ "[]
+This buffer is for notes."
+ (should-error (execute-kbd-macro "fT")))))
+
+(ert-deftest evil-test-find-char-backward ()
+ "Test `evil-find-char-backward'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("FT")
+ ";; [T]his buffer is for notes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("2Fe")
+ ";; This buff[e]r is for notes."))
+ (ert-info ("Repeat")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("Fe;")
+ ";; This buff[e]r is for notes."))
+ (ert-info ("Repeat backward")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("2Fe,")
+ ";; This buffer is for not[e]s."))
+ (ert-info ("No match")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ (should-error (execute-kbd-macro "FL"))))
+ (ert-info ("End of line")
+ (let ((evil-cross-lines t))
+ (evil-test-buffer
+ ";; This buffer is for notes,
+;; and for Lisp evaluation[.]"
+ ("FT")
+ ";; [T]his buffer is for notes,
+;; and for Lisp evaluation."))))
+
+(ert-deftest evil-test-find-digraph-char ()
+ "Test evil-read-digraph-char while finding char."
+ :tags '(evil motion)
+ (ert-info ("Find digraph char")
+ (evil-test-buffer
+ "a[b]cde∀g"
+ ("f\C-kFA")
+ "abcde[∀]g")))
+
+(ert-deftest evil-test-find-char-to ()
+ "Test `evil-find-char-to'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("tT")
+ ";;[ ]This buffer is for notes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("2te")
+ ";; This buffer is for no[t]es."))
+ (ert-info ("Repeat")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("tel;")
+ ";; This buffer is for no[t]es."))
+ (ert-info ("Repeat backward")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ ("2te,")
+ ";; This buffe[r] is for notes."))
+ (ert-info ("Repeat should skip adjacent character")
+ (let ((evil-repeat-find-to-skip-next t))
+ (evil-test-buffer
+ "[a]aaxaaaxaaaxaaa"
+ ("tx;")
+ "aaaxaa[a]xaaaxaaa"
+ (";")
+ "aaaxaaaxaa[a]xaaa"
+ (",")
+ "aaaxaaax[a]aaxaaa"
+ (",")
+ "aaax[a]aaxaaaxaaa")))
+ (ert-info ("Repeat should NOT skip adjacent character")
+ (let ((evil-repeat-find-to-skip-next nil))
+ (evil-test-buffer
+ "[a]aaxaaaxaaaxaaa"
+ ("tx;")
+ "aa[a]xaaaxaaaxaaa")))
+ (ert-info ("No match")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ (should-error (execute-kbd-macro "tL"))))
+ (ert-info ("End of line")
+ (let ((evil-cross-lines t))
+ (evil-test-buffer
+ "[;]; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("tL")
+ ";; This buffer is for notes,
+;; and for[ ]Lisp evaluation."))))
+
+(ert-deftest evil-test-find-char-to-backward ()
+ "Test `evil-find-char-to-backward'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("TT")
+ ";; T[h]is buffer is for notes."))
+ (ert-info ("With count")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("2Te")
+ ";; This buffe[r] is for notes."))
+ (ert-info ("Repeat")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("Teh;")
+ ";; This buffe[r] is for notes."))
+ (ert-info ("Repeat backward")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ ("2Te,")
+ ";; This buffer is for no[t]es."))
+ (ert-info ("Repeat should skip adjacent character")
+ (let ((evil-repeat-find-to-skip-next t))
+ (evil-test-buffer
+ "aaaxaaaxaaaxaa[a]"
+ ("Tx;")
+ "aaaxaaax[a]aaxaaa"
+ (";")
+ "aaax[a]aaxaaaxaaa"
+ (",")
+ "aaaxaa[a]xaaaxaaa"
+ (",")
+ "aaaxaaaxaa[a]xaaa")))
+ (ert-info ("Repeat should NOT skip adjacent character")
+ (let ((evil-repeat-find-to-skip-next nil))
+ (evil-test-buffer
+ "aaaxaaaxaaaxaa[a]"
+ ("Tx;")
+ "aaaxaaaxaaax[a]aa")))
+ (ert-info ("No match")
+ (evil-test-buffer
+ ";; This buffer is for notes[.]"
+ (should-error (execute-kbd-macro "TL"))))
+ (ert-info ("End of line")
+ (let ((evil-cross-lines t))
+ (evil-test-buffer
+ ";; This buffer is for notes,
+;; and for Lisp evaluation[.]"
+ ("TT")
+ ";; T[h]is buffer is for notes,
+;; and for Lisp evaluation."))))
+
+(ert-deftest evil-test-jump-item ()
+ "Test `evil-jump-item'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "int main[(]int argc, char** argv)"
+ ("%")
+ "int main(int argc, char** argv[)]"
+ ("%")
+ "int main[(]int argc, char** argv)"))
+ (ert-info ("Before parenthesis")
+ (evil-test-buffer
+ "[i]nt main(int argc, char** argv)"
+ ("%")
+ "int main(int argc, char** argv[)]"
+ ("5h")
+ "int main(int argc, char**[ ]argv)"
+ ("%")
+ "int main[(]int argc, char** argv)"))
+ (ert-info ("Over several lines")
+ (evil-test-buffer
+ "int main(int argc, char** argv)
+\[{]
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+}"
+ ("%")
+ "int main(int argc, char** argv)
+{
+ printf(\"Hello world\\n\");
+ return EXIT_SUCCESS;
+\[}]"))
+ (ert-info ("On line without parenthesis")
+ (evil-test-buffer
+ "[#]include <stdio.h>"
+ (should-error (execute-kbd-macro "%"))))
+ (ert-info ("Before unmatched opening parenthesies")
+ (evil-test-buffer
+ "x[x]xx ( yyyyy () zzzz"
+ (should-error (execute-kbd-macro "%"))
+ "x[x]xx ( yyyyy () zzzz"))
+ (ert-info ("Before unmatched closing parenthesies")
+ (evil-test-buffer
+ "x[x]xx ) yyyyy () zzzz"
+ (should-error (execute-kbd-macro "%"))
+ "x[x]xx ) yyyyy () zzzz"))
+
+ (ert-info ("At the end of the line")
+ (evil-test-buffer
+ "[p]ublic void foo(String bar) {\n blabla;\n}\n"
+ ("v$%")
+ "public void foo(String bar) {\n blabla;\n[}]\n")))
+
+(ert-deftest evil-test-unmatched-paren ()
+ "Test `evil-previous-open-paren' and `evil-next-close-paren'"
+ :tags '(evil motion)
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "foo ( { ( [b]ar ) baz } )"
+ ("[(")
+ "foo ( { [(] bar ) baz } )"
+ ("])")
+ "foo ( { ( bar [)] baz } )"
+ ("[(")
+ "foo ( { [(] bar ) baz } )"
+ ("[(")
+ "foo [(] { ( bar ) baz } )"
+ ("f)])")
+ "foo ( { ( bar ) baz } [)]"))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "foo ( { ( [b]ar ) baz } )"
+ ("2[(")
+ "foo [(] { ( bar ) baz } )")
+ (evil-test-buffer
+ "foo ( { ( [b]ar ) baz } )"
+ ("2])")
+ "foo ( { ( bar ) baz } [)]")))
+
+(ert-deftest evil-test-paren-jump-from-string ()
+ "Test jump to next/prev paren from a string"
+ :tags '(evil motion)
+ (evil-test-buffer
+ "{
+ fun(a, \"T[]est\", test());
+}
+"
+ ("[(")
+ "{
+ fun[(]a, \"Test\", test());
+}
+"
+ ("])")
+ "{
+ fun(a, \"Test\", test()[)];
+}
+")
+ (evil-test-buffer
+ "{
+ fun(a, \"T[]est\", test());
+}
+"
+ ("])")
+ "{
+ fun(a, \"Test\", test()[)];
+}
+"
+ ("[(")
+ "{
+ fun[(]a, \"Test\", test());
+}
+")
+ (evil-test-buffer
+ "{
+ fun(a, \"T[]est\", test());
+}
+"
+ ("[{")
+ "[{]
+ fun(a, \"Test\", test());
+}
+")
+ (evil-test-buffer
+ "{
+ fun(a, \"T[]est\", test());
+}
+"
+ ("]}")
+ "{
+ fun(a, \"Test\", test());
+[}]
+"))
+
+(ert-deftest evil-test-paren-jump-inside-string-from-string ()
+ "Test jump to next/prev paren inside string from a string"
+ :tags '(evil motion)
+ (evil-test-buffer
+ "{ (\"Test with paren (inside multi (l[e]vel))\", test()); } "
+ ("[(")
+ "{ (\"Test with paren (inside multi [(]level))\", test()); } "
+ ("[(")
+ "{ (\"Test with paren [(]inside multi (level))\", test()); } ")
+ (evil-test-buffer
+ "{ (\"Test with paren (inside multi (l[e]vel))\", test()); } "
+ ("])")
+ "{ (\"Test with paren (inside multi (level[)])\", test()); } "
+ ("])")
+ "{ (\"Test with paren (inside multi (level)[)]\", test()); } ")
+ (evil-test-buffer
+ "{ (\"Test with paren {inside multi {l[e]vel}}\", test()); } "
+ ("[{")
+ "{ (\"Test with paren {inside multi [{]level}}\", test()); } "
+ ("[{")
+ "{ (\"Test with paren [{]inside multi {level}}\", test()); } ")
+ (evil-test-buffer
+ "{ (\"Test with paren {inside multi {l[e]vel}}\", test()); } "
+ ("]}")
+ "{ (\"Test with paren {inside multi {level[}]}\", test()); } "
+ ("]}")
+ "{ (\"Test with paren {inside multi {level}[}]\", test()); } "))
+
+(ert-deftest evil-test-insert-resume ()
+ "Test `evil-insert-resume'"
+ :tags '(evil motion)
+ (ert-info ("Can move to last insert location and take a count")
+ (evil-test-buffer
+ "alpha bravo [ ]delta echo"
+ ("i" "charlie" [escape] "^")
+ "[a]lpha bravo charlie delta echo"
+ ("2gi" " zulu" [escape])
+ "alpha bravo charlie zulu zul[u] delta echo"))
+ (ert-info ("Can move to `^' marker in visual line state")
+ (evil-test-buffer
+ "alpha [b]ravo\ncharlie delta\necho foxtrot"
+ ("i" [escape] "/foxtrot" [return])
+ "alpha bravo\ncharlie delta\necho [f]oxtrot"
+ ("Vk")
+ "alpha bravo\ncharl[i]e delta\necho foxtrot"
+ ("gi")
+ "alpha [b]ravo\ncharlie delta\necho foxtrot"
+ ("vd")
+ "alpha [o]xtrot")))
+
+(ert-deftest evil-test-next-mark ()
+ "Test `evil-next-mark', `evil-previous-mark'"
+ :tags '(evil motion)
+ (ert-info ("Can move to next mark, next mark line,
+previous mark and previous mark line")
+ (evil-test-buffer
+ "[a]lpha bravo
+charlie delta echo
+foxtrot golf hotel
+india juliet"
+ ("ma" "w" "mb" "w"
+ "mc" "w" "md" "w" "me" "w"
+ "mf" "w" "mg" "w" "mh" "w"
+ "mi" "w" "mj")
+ "alpha bravo
+charlie delta echo
+foxtrot golf hotel
+india [j]uliet"
+ ("3]`")
+ "alpha bravo
+[c]harlie delta echo
+foxtrot golf hotel
+india juliet"
+ ("]'")
+ "alpha bravo
+charlie delta echo
+[f]oxtrot golf hotel
+india juliet"
+ ("[`")
+ "alpha bravo
+charlie delta [e]cho
+foxtrot golf hotel
+india juliet"
+ ("2['")
+ "alpha bravo
+charlie delta echo
+foxtrot golf hotel
+[i]ndia juliet")))
+
+(ert-deftest evil-set-col-0-mark-test ()
+ "Test `evil-set-col-0-mark' ex command"
+ :tags '(evil ex)
+ (evil-test-buffer
+ "Lin[e] 1
+Line 2"
+ (":mark k" [return] "G" "`k")
+ "[L]ine 1
+Line 2"))
+
+(ert-deftest evil-delete-marks-test ()
+ "Test `evil-delete-marks' ex command"
+ :tags '(evil ex)
+ (ert-info ("Can delete marks")
+ (evil-test-buffer
+ "[O]ne line is enough if we use backtick to navigate"
+ ("mO" "w" "ml" "w" "mi" "$b" "m4")
+ "One line is enough if we use backtick to [n]avigate"
+ ("`O")
+ "[O]ne line is enough if we use backtick to navigate"
+ (":delm O" [return] "`i")
+ "One line [i]s enough if we use backtick to navigate"
+ (error user-error "`O")
+ "One line [i]s enough if we use backtick to navigate"
+ ("`4")
+ "One line is enough if we use backtick to [n]avigate"
+ (":delm h-m" [return])
+ (error user-error "`i")
+ "One line is enough if we use backtick to [n]avigate")))
+
+(ert-deftest evil-automatic-marks-test ()
+ "Test that certain commands automatically set mark(er)s"
+ :tags '(evil)
+ (ert-info ("Visual selection sets angle-bracket marks")
+ (evil-test-buffer
+ "alpha br[a]vo charlie"
+ ("viw" [escape] "$")
+ "alpha bravo charli[e]"
+ ("`>")
+ "alpha brav[o] charlie"
+ ("`<")
+ "alpha [b]ravo charlie")))
+
+(ert-deftest evil-test-flyspell-motions ()
+ "Test flyspell motions"
+ :tags '(evil motion)
+ (skip-unless (condition-case _ (progn (ispell-check-version) t) (error)))
+ (ert-info ("Simple")
+ (evil-test-buffer
+ "[I] cannt tpye for lyfe"
+ (flyspell-mode)
+ (flyspell-buffer)
+ ("]s")
+ "I [c]annt tpye for lyfe"
+ ("]s")
+ "I cannt [t]pye for lyfe"
+ ("]s")
+ "I cannt tpye for [l]yfe"
+ ("]s")
+ "I [c]annt tpye for lyfe"
+ ("[s")
+ "I cannt tpye for [l]yfe"
+ ("[s")
+ "I cannt [t]pye for lyfe")
+ (evil-test-buffer
+ "[o]en otw thre"
+ (flyspell-mode)
+ (flyspell-buffer)
+ ("]s")
+ "oen [o]tw thre"
+ ("]s")
+ "oen otw [t]hre"
+ ("]s")
+ "[o]en otw thre"))
+ (ert-info ("With count")
+ (evil-test-buffer
+ "[I] cannt tpye for lyfe"
+ (flyspell-mode)
+ (flyspell-buffer)
+ ("2]s")
+ "I cannt [t]pye for lyfe"
+ ("2]s")
+ "I [c]annt tpye for lyfe"
+ ("2[s")
+ "I cannt [t]pye for lyfe"
+ ("2[s")
+ "I cannt tpye for [l]yfe"))
+ (ert-info ("With evil-search-wrap disabled")
+ (let (evil-search-wrap)
+ (evil-test-buffer
+ "[I] cannt tpye for lyfe"
+ (flyspell-mode)
+ (flyspell-buffer)
+ ("]s")
+ "I [c]annt tpye for lyfe"
+ ("]s")
+ "I cannt [t]pye for lyfe"
+ ("]s")
+ "I cannt tpye for [l]yfe"
+ (error search-failed "]s"))))
+ (ert-info ("One mistake")
+ (evil-test-buffer
+ "[I]'m almst there..."
+ (flyspell-mode)
+ (flyspell-buffer)
+ ("]s")
+ "I'm [a]lmst there..."
+ ("]s")
+ "I'm [a]lmst there..."))
+ (ert-info ("No mistakes")
+ (evil-test-buffer
+ "[I]'ve learned to type!"
+ (flyspell-mode)
+ (flyspell-buffer)
+ (error search-failed "]s")
+ (error search-failed "[s"))))
+
+;;; Text objects
+
+(ert-deftest evil-test-text-object ()
+ "Test `evil-define-text-object'"
+ :tags '(evil text-object)
+ (let ((object (evil-define-text-object nil (count &optional beg end _type)
+ (let ((sel (and beg end (evil-range beg end))))
+ (when (and sel (> count 0)) (forward-char 1))
+ (let ((range (if (< count 0)
+ (list (- (point) 3) (point))
+ (list (point) (+ (point) 3)))))
+ (if sel
+ (evil-range-union range sel)
+ range))))))
+ (ert-info ("Select three characters after point")
+ (evil-test-buffer
+ :state operator
+ ";; [T]his buffer is for notes."
+ (should (equal (funcall object 1) '(4 7 inclusive)))))
+ (ert-info ("Select three characters before point")
+ (evil-test-buffer
+ :state operator
+ ";; [T]his buffer is for notes."
+ (should (equal (funcall object -1) '(1 4 inclusive)))))
+ (ert-info ("Select three characters after selection")
+ (evil-test-buffer
+ ";; <Thi[s]> buffer is for notes."
+ (call-interactively object)
+ ";; <This b[u]>ffer is for notes."))
+ (ert-info ("Select three characters before selection")
+ (evil-test-buffer
+ ";; <[T]his> buffer is for notes."
+ (call-interactively object)
+ "<[;]; This> buffer is for notes."))
+ (ert-info ("Delete three characters after point")
+ (evil-test-buffer
+ "[;]; This buffer is for notes."
+ (define-key evil-operator-state-local-map "io" object)
+ ("dio")
+ "[T]his buffer is for notes."))))
+
+(ert-deftest evil-test-word-objects ()
+ "Test `evil-inner-word' and `evil-a-word'"
+ :tags '(evil text-object)
+ (ert-info ("Select a word")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("viw")
+ ";; <Thi[s]> buffer is for notes.")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ ("vaw")
+ ";; <This[ ]>buffer is for notes.")
+ (evil-test-buffer
+ ";; Thi[s] buffer is for notes."
+ ("viw")
+ ";; <Thi[s]> buffer is for notes.")
+ (evil-test-buffer
+ ";; Thi[s] buffer is for notes."
+ ("vaw")
+ ";; <This[ ]>buffer is for notes."))
+ (ert-info ("Select two words")
+ (ert-info ("Include whitespace on this side")
+ (evil-test-buffer
+ ";;< Thi[s]> buffer is for notes."
+ ("aw")
+ ";;< This buffe[r]> is for notes.")
+ (evil-test-buffer
+ ";; This <[b]uffer >is for notes."
+ ("aw")
+ ";; <[T]his buffer >is for notes."))
+ (ert-info ("Include whitespace on the other side")
+ (evil-test-buffer
+ ";; <This[ ]>buffer is for notes."
+ ("aw")
+ ";; <This buffer[ ]>is for notes.")
+ (evil-test-buffer
+ ";; This<[ ]buffer> is for notes."
+ ("aw")
+ ";;<[ ]This buffer> is for notes.")))
+ (ert-info ("select first visual word")
+ (evil-test-buffer
+ "([a])"
+ ("viw")
+ "(<[a]>)"))
+ (ert-info ("Deleting whitespace is confined to the line")
+ (evil-test-buffer
+ "foo\n [ ] bar"
+ ("diw")
+ "foo\n[b]ar")
+ (evil-test-buffer
+ "foo\n [ ] bar"
+ ("diW")
+ "foo\n[b]ar")
+ (evil-test-buffer
+ "fo[o]\nbar"
+ ("diW")
+ "[\n]bar")
+ (evil-test-buffer
+ "foo\n [ ] bar"
+ ("daw")
+ "foo\n[]")
+ (evil-test-buffer
+ "foo\n [ ] bar"
+ ("daW")
+ "foo\n[]"))
+ (ert-info ("Deleting the only word on a line doesn't delete indentation")
+ (evil-test-buffer
+ " [b]ar"
+ ("daw")
+ " [ ]")
+ (evil-test-buffer
+ " [b]ar"
+ ("daW")
+ " [ ]")
+ (ert-info ("But deleting the final word of many behaves as normal")
+ (evil-test-buffer
+ " foo [b]ar"
+ ("daw")
+ " fo[o]")))
+ (ert-info ("Deleting whitespace on whitepsace only line")
+ (evil-test-buffer
+ "foo\n[ ]\nbar"
+ ("diw")
+ "foo\n[]\nbar")
+ (evil-test-buffer
+ "foo\n[ ]\nbar"
+ ("daw")
+ "foo\n[]\nbar")))
+
+(ert-deftest evil-test-word-objects-cjk ()
+ "Test `evil-inner-word' and `evil-a-word' on CJK words"
+ :tags '(evil text-object cjk)
+ (ert-info ("Select a word")
+ (evil-test-buffer
+ "[a]bcd1234"
+ ("viw")
+ "<abcd123[4]>")
+ (evil-test-buffer
+ "[a]bcd1234"
+ ("vaw")
+ "<abcd123[4]>")
+ (evil-test-buffer
+ "[a]bcd漢字"
+ ("viw")
+ "<abc[d]>漢字")
+ (evil-test-buffer
+ "[a]bcd漢字"
+ ("vaw")
+ "<abc[d]>漢字")
+ (evil-test-buffer
+ "[a]bcdひらがな"
+ ("viw")
+ "<abc[d]>ひらがな")
+ (evil-test-buffer
+ "[a]bcdひらがな"
+ ("vaw")
+ "<abc[d]>ひらがな")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("viw")
+ "<abc[d]>カタカナ")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("vaw")
+ "<abc[d]>カタカナ")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("viw")
+ "<abcdカタカ[ナ]>")
+ (evil-test-buffer
+ "[a]bcdカタカナ"
+ ("vaw")
+ "<abcdカタカ[ナ]>")
+ (evil-test-buffer
+ "[a]bcdABC"
+ ("viw")
+ "<abcdAB[C]>")
+ (evil-test-buffer
+ "[a]bcdABC"
+ ("vaw")
+ "<abcdAB[C]>")
+ (evil-test-buffer
+ "[a]bcd123"
+ ("viw")
+ "<abcd12[3]>")
+ (evil-test-buffer
+ "[a]bcd123"
+ ("vaw")
+ "<abcd12[3]>")
+ (evil-test-buffer
+ "[a]bcd한글"
+ ("viw")
+ "<abc[d]>한글")
+ (evil-test-buffer
+ "[a]bcd한글"
+ ("vaw")
+ "<abc[d]>한글")
+ (evil-test-buffer
+ "[1]234abcd"
+ ("viw")
+ "<1234abc[d]>")
+ (evil-test-buffer
+ "[1]234abcd"
+ ("vaw")
+ "<1234abc[d]>")
+ (evil-test-buffer
+ "[1]234漢字"
+ ("viw")
+ "<123[4]>漢字")
+ (evil-test-buffer
+ "[1]234漢字"
+ ("vaw")
+ "<123[4]>漢字")
+ (evil-test-buffer
+ "[1]234ひらがな"
+ ("viw")
+ "<123[4]>ひらがな")
+ (evil-test-buffer
+ "[1]234ひらがな"
+ ("vaw")
+ "<123[4]>ひらがな")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("viw")
+ "<123[4]>カタカナ")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("vaw")
+ "<123[4]>カタカナ")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("viw")
+ "<1234カタカ[ナ]>")
+ (evil-test-buffer
+ "[1]234カタカナ"
+ ("vaw")
+ "<1234カタカ[ナ]>")
+ (evil-test-buffer
+ "[1]234ABC"
+ ("viw")
+ "<1234AB[C]>")
+ (evil-test-buffer
+ "[1]234ABC"
+ ("vaw")
+ "<1234AB[C]>")
+ (evil-test-buffer
+ "[1]234123"
+ ("viw")
+ "<123412[3]>")
+ (evil-test-buffer
+ "[1]234123"
+ ("vaw")
+ "<123412[3]>")
+ (evil-test-buffer
+ "[1]234한글"
+ ("viw")
+ "<123[4]>한글")
+ (evil-test-buffer
+ "[1]234한글"
+ ("vaw")
+ "<123[4]>한글")
+ (evil-test-buffer
+ "[漢]字abcd"
+ ("viw")
+ "<漢[字]>abcd")
+ (evil-test-buffer
+ "[漢]字abcd"
+ ("vaw")
+ "<漢[字]>abcd")
+ (evil-test-buffer
+ "[漢]字1234"
+ ("viw")
+ "<漢[字]>1234")
+ (evil-test-buffer
+ "[漢]字1234"
+ ("vaw")
+ "<漢[字]>1234")
+ (evil-test-buffer
+ "[漢]字ひらがな"
+ ("viw")
+ "<漢[字]>ひらがな")
+ (evil-test-buffer
+ "[漢]字ひらがな"
+ ("vaw")
+ "<漢[字]>ひらがな")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("viw")
+ "<漢[字]>カタカナ")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("vaw")
+ "<漢[字]>カタカナ")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("viw")
+ "<漢[字]>カタカナ")
+ (evil-test-buffer
+ "[漢]字カタカナ"
+ ("vaw")
+ "<漢[字]>カタカナ")
+ (evil-test-buffer
+ "[漢]字ABC"
+ ("viw")
+ "<漢[字]>ABC")
+ (evil-test-buffer
+ "[漢]字ABC"
+ ("vaw")
+ "<漢[字]>ABC")
+ (evil-test-buffer
+ "[漢]字123"
+ ("viw")
+ "<漢[字]>123")
+ (evil-test-buffer
+ "[漢]字123"
+ ("vaw")
+ "<漢[字]>123")
+ (evil-test-buffer
+ "[漢]字한글"
+ ("viw")
+ "<漢[字]>한글")
+ (evil-test-buffer
+ "[漢]字한글"
+ ("vaw")
+ "<漢[字]>한글")
+ (evil-test-buffer
+ "[ひ]らがなabcd"
+ ("viw")
+ "<ひらが[な]>abcd")
+ (evil-test-buffer
+ "[ひ]らがなabcd"
+ ("vaw")
+ "<ひらが[な]>abcd")
+ (evil-test-buffer
+ "[ひ]らがな1234"
+ ("viw")
+ "<ひらが[な]>1234")
+ (evil-test-buffer
+ "[ひ]らがな1234"
+ ("vaw")
+ "<ひらが[な]>1234")
+ (evil-test-buffer
+ "[ひ]らがな漢字"
+ ("viw")
+ "<ひらが[な]>漢字")
+ (evil-test-buffer
+ "[ひ]らがな漢字"
+ ("vaw")
+ "<ひらが[な]>漢字")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("viw")
+ "<ひらが[な]>カタカナ")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("vaw")
+ "<ひらが[な]>カタカナ")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("viw")
+ "<ひらが[な]>カタカナ")
+ (evil-test-buffer
+ "[ひ]らがなカタカナ"
+ ("vaw")
+ "<ひらが[な]>カタカナ")
+ (evil-test-buffer
+ "[ひ]らがなABC"
+ ("viw")
+ "<ひらが[な]>ABC")
+ (evil-test-buffer
+ "[ひ]らがなABC"
+ ("vaw")
+ "<ひらが[な]>ABC")
+ (evil-test-buffer
+ "[ひ]らがな123"
+ ("viw")
+ "<ひらが[な]>123")
+ (evil-test-buffer
+ "[ひ]らがな123"
+ ("vaw")
+ "<ひらが[な]>123")
+ (evil-test-buffer
+ "[ひ]らがな한글"
+ ("viw")
+ "<ひらが[な]>한글")
+ (evil-test-buffer
+ "[ひ]らがな한글"
+ ("vaw")
+ "<ひらが[な]>한글")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("viw")
+ "<カタカ[ナ]>abcd")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("vaw")
+ "<カタカ[ナ]>abcd")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("viw")
+ "<カタカ[ナ]>1234")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("vaw")
+ "<カタカ[ナ]>1234")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("viw")
+ "<カタカ[ナ]>漢字")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("vaw")
+ "<カタカ[ナ]>漢字")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("viw")
+ "<カタカ[ナ]>ひらがな")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("vaw")
+ "<カタカ[ナ]>ひらがな")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("viw")
+ "<カタカ[ナ]>カタカナ")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("vaw")
+ "<カタカ[ナ]>カタカナ")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("viw")
+ "<カタカ[ナ]>ABC")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("vaw")
+ "<カタカ[ナ]>ABC")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("viw")
+ "<カタカ[ナ]>123")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("vaw")
+ "<カタカ[ナ]>123")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("viw")
+ "<カタカ[ナ]>한글")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("vaw")
+ "<カタカ[ナ]>한글")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("viw")
+ "<カタカナabc[d]>")
+ (evil-test-buffer
+ "[カ]タカナabcd"
+ ("vaw")
+ "<カタカナabc[d]>")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("viw")
+ "<カタカナ123[4]>")
+ (evil-test-buffer
+ "[カ]タカナ1234"
+ ("vaw")
+ "<カタカナ123[4]>")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("viw")
+ "<カタカ[ナ]>漢字")
+ (evil-test-buffer
+ "[カ]タカナ漢字"
+ ("vaw")
+ "<カタカ[ナ]>漢字")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("viw")
+ "<カタカ[ナ]>ひらがな")
+ (evil-test-buffer
+ "[カ]タカナひらがな"
+ ("vaw")
+ "<カタカ[ナ]>ひらがな")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("viw")
+ "<カタカ[ナ]>カタカナ")
+ (evil-test-buffer
+ "[カ]タカナカタカナ"
+ ("vaw")
+ "<カタカ[ナ]>カタカナ")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("viw")
+ "<カタカナAB[C]>")
+ (evil-test-buffer
+ "[カ]タカナABC"
+ ("vaw")
+ "<カタカナAB[C]>")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("viw")
+ "<カタカナ12[3]>")
+ (evil-test-buffer
+ "[カ]タカナ123"
+ ("vaw")
+ "<カタカナ12[3]>")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("viw")
+ "<カタカ[ナ]>한글")
+ (evil-test-buffer
+ "[カ]タカナ한글"
+ ("vaw")
+ "<カタカ[ナ]>한글")
+ (evil-test-buffer
+ "[A]BCabcd"
+ ("viw")
+ "<ABCabc[d]>")
+ (evil-test-buffer
+ "[A]BCabcd"
+ ("vaw")
+ "<ABCabc[d]>")
+ (evil-test-buffer
+ "[A]BC1234"
+ ("viw")
+ "<ABC123[4]>")
+ (evil-test-buffer
+ "[A]BC1234"
+ ("vaw")
+ "<ABC123[4]>")
+ (evil-test-buffer
+ "[A]BC漢字"
+ ("viw")
+ "<AB[C]>漢字")
+ (evil-test-buffer
+ "[A]BC漢字"
+ ("vaw")
+ "<AB[C]>漢字")
+ (evil-test-buffer
+ "[A]BCひらがな"
+ ("viw")
+ "<AB[C]>ひらがな")
+ (evil-test-buffer
+ "[A]BCひらがな"
+ ("vaw")
+ "<AB[C]>ひらがな")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("viw")
+ "<AB[C]>カタカナ")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("vaw")
+ "<AB[C]>カタカナ")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("viw")
+ "<ABCカタカ[ナ]>")
+ (evil-test-buffer
+ "[A]BCカタカナ"
+ ("vaw")
+ "<ABCカタカ[ナ]>")
+ (evil-test-buffer
+ "[A]BC123"
+ ("viw")
+ "<ABC12[3]>")
+ (evil-test-buffer
+ "[A]BC123"
+ ("vaw")
+ "<ABC12[3]>")
+ (evil-test-buffer
+ "[A]BC한글"
+ ("viw")
+ "<AB[C]>한글")
+ (evil-test-buffer
+ "[A]BC한글"
+ ("vaw")
+ "<AB[C]>한글")
+ (evil-test-buffer
+ "[1]23abcd"
+ ("viw")
+ "<123abc[d]>")
+ (evil-test-buffer
+ "[1]23abcd"
+ ("vaw")
+ "<123abc[d]>")
+ (evil-test-buffer
+ "[1]231234"
+ ("viw")
+ "<123123[4]>")
+ (evil-test-buffer
+ "[1]231234"
+ ("vaw")
+ "<123123[4]>")
+ (evil-test-buffer
+ "[1]23漢字"
+ ("viw")
+ "<12[3]>漢字")
+ (evil-test-buffer
+ "[1]23漢字"
+ ("vaw")
+ "<12[3]>漢字")
+ (evil-test-buffer
+ "[1]23ひらがな"
+ ("viw")
+ "<12[3]>ひらがな")
+ (evil-test-buffer
+ "[1]23ひらがな"
+ ("vaw")
+ "<12[3]>ひらがな")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("viw")
+ "<12[3]>カタカナ")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("vaw")
+ "<12[3]>カタカナ")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("viw")
+ "<123カタカ[ナ]>")
+ (evil-test-buffer
+ "[1]23カタカナ"
+ ("vaw")
+ "<123カタカ[ナ]>")
+ (evil-test-buffer
+ "[1]23ABC"
+ ("viw")
+ "<123AB[C]>")
+ (evil-test-buffer
+ "[1]23ABC"
+ ("vaw")
+ "<123AB[C]>")
+ (evil-test-buffer
+ "[1]23한글"
+ ("viw")
+ "<12[3]>한글")
+ (evil-test-buffer
+ "[1]23한글"
+ ("vaw")
+ "<12[3]>한글")
+ (evil-test-buffer
+ "[한]글abcd"
+ ("viw")
+ "<한[글]>abcd")
+ (evil-test-buffer
+ "[한]글abcd"
+ ("vaw")
+ "<한[글]>abcd")
+ (evil-test-buffer
+ "[한]글1234"
+ ("viw")
+ "<한[글]>1234")
+ (evil-test-buffer
+ "[한]글1234"
+ ("vaw")
+ "<한[글]>1234")
+ (evil-test-buffer
+ "[한]글漢字"
+ ("viw")
+ "<한[글]>漢字")
+ (evil-test-buffer
+ "[한]글漢字"
+ ("vaw")
+ "<한[글]>漢字")
+ (evil-test-buffer
+ "[한]글ひらがな"
+ ("viw")
+ "<한[글]>ひらがな")
+ (evil-test-buffer
+ "[한]글ひらがな"
+ ("vaw")
+ "<한[글]>ひらがな")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("viw")
+ "<한[글]>カタカナ")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("vaw")
+ "<한[글]>カタカナ")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("viw")
+ "<한[글]>カタカナ")
+ (evil-test-buffer
+ "[한]글カタカナ"
+ ("vaw")
+ "<한[글]>カタカナ")
+ (evil-test-buffer
+ "[한]글ABC"
+ ("viw")
+ "<한[글]>ABC")
+ (evil-test-buffer
+ "[한]글ABC"
+ ("vaw")
+ "<한[글]>ABC")
+ (evil-test-buffer
+ "[한]글123"
+ ("viw")
+ "<한[글]>123")
+ (evil-test-buffer
+ "[한]글123"
+ ("vaw")
+ "<한[글]>123")))
+
+(ert-deftest evil-test-paragraph-objects ()
+ "Test `evil-inner-paragraph' and `evil-a-paragraph'"
+ :tags '(evil text-object)
+ (ert-info ("Select a paragraph with point at beginning")
+ (evil-test-buffer
+ "[;]; This buffer is for notes,
+;; and for Lisp evaluation.
+
+;; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("vap")
+ "<;; This buffer is for notes,
+;; and for Lisp evaluation.
+\[]\n>\
+;; This buffer is for notes,
+;; and for Lisp evaluation."))
+ (ert-info ("Select a paragraph with point at last line")
+ (evil-test-buffer
+ ";; This buffer is for notes,
+\[;]; and for Lisp evaluation.
+
+;; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("vap")
+ "<;; This buffer is for notes,
+;; and for Lisp evaluation.
+\[]\n>\
+;; This buffer is for notes,
+;; and for Lisp evaluation."))
+ (ert-info ("Select a paragraph with point after paragraph")
+ (evil-test-buffer
+ ";; This buffer is for notes,
+;; and for Lisp evaluation.
+\[]
+;; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("vap")
+ ";; This buffer is for notes,
+;; and for Lisp evaluation.
+<
+;; This buffer is for notes,
+;; and for Lisp evaluation[.]>"))
+ (ert-info ("Select inner paragraph")
+ (evil-test-buffer
+ "[;]; This buffer is for notes,
+;; and for Lisp evaluation.
+
+;; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("vip")
+ "<;; This buffer is for notes,
+;; and for Lisp evaluation.[]
+>
+;; This buffer is for notes,
+;; and for Lisp evaluation.")
+ (evil-test-buffer
+ ";; This buffer is for notes,
+\[;]; and for Lisp evaluation.
+
+;; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("vip")
+ "<;; This buffer is for notes,
+;; and for Lisp evaluation.[]
+>
+;; This buffer is for notes,
+;; and for Lisp evaluation.")
+ (evil-test-buffer
+ ";; This buffer is for notes,
+;; and for Lisp evaluation.
+\[]
+;; This buffer is for notes,
+;; and for Lisp evaluation."
+ ("vip")
+ ";; This buffer is for notes,
+;; and for Lisp evaluation.
+<
+;; This buffer is for notes,
+;; and for Lisp evaluation[.]>")))
+
+(ert-deftest evil-test-quote-objects ()
+ "Test `evil-inner-single-quote' and `evil-a-single-quote'"
+ :tags '(evil text-object)
+ (ert-info ("Select text inside of '...'")
+ (evil-test-buffer
+ "This is 'a [t]est' for quote objects."
+ ("vi'")
+ "This is '<a tes[t]>' for quote objects.")
+ (evil-test-buffer
+ "This is \"a '[t]est'\" for quote objects."
+ ("vi'")
+ "This is \"a '<tes[t]>'\" for quote objects."))
+ (ert-info ("Select text including enclosing quotes")
+ (evil-test-buffer
+ "This is 'a [t]est' for quote objects."
+ ("v2i'")
+ "This is <'a test[']> for quote objects."))
+ (ert-info ("Select text including enclosing quotes and following space")
+ (evil-test-buffer
+ "This is 'a [t]est' for quote objects."
+ ("va'")
+ "This is <'a test'[ ]>for quote objects."))
+ (ert-info ("Select text including enclosing quotes and previous space")
+ (evil-test-buffer
+ "This is 'a [t]est'. For quote objects."
+ ("va'")
+ "This is< 'a test[']>. For quote objects."))
+ (ert-info ("Select text on opening quote")
+ (evil-test-buffer
+ "This is [\"]a test\". For \"quote\" objects."
+ (emacs-lisp-mode)
+ ("va\"")
+ "This is< \"a test[\"]>. For \"quote\" objects."))
+ (ert-info ("Select text on closing quote")
+ (evil-test-buffer
+ "This is \"a test[\"]. For \"quote\" objects."
+ (emacs-lisp-mode)
+ ("va\"")
+ "This is< \"a test[\"]>. For \"quote\" objects."))
+ (ert-info ("Delete text from outside")
+ (evil-test-buffer
+ "Th[i]s is \"a test\". For \"quote\" objects."
+ (emacs-lisp-mode)
+ ("da\"")
+ "This is[.] For \"quote\" objects."))
+ (ert-info ("Operator on empty quotes")
+ (evil-test-buffer
+ "This is [a]n \"\" empty quote"
+ (emacs-lisp-mode)
+ ("ci\"XXX" [escape])
+ "This is an \"XX[X]\" empty quote")))
+
+(ert-deftest evil-test-paren-objects ()
+ "Test `evil-inner-paren', etc."
+ :tags '(evil text-object)
+ (ert-info ("Select inner text")
+ (evil-test-buffer
+ "[(]aaa)"
+ (emacs-lisp-mode) ; syntax
+ ("vi(")
+ "(<aa[a]>)")
+ (evil-test-buffer
+ "(aaa[)]"
+ (emacs-lisp-mode)
+ ("vi(")
+ "(<aa[a]>)")
+ (ert-info ("Next to outer delimiter")
+ (evil-test-buffer
+ "([(]aaa))"
+ (emacs-lisp-mode)
+ ("vi(")
+ "((<aa[a]>))")
+ (evil-test-buffer
+ "((aaa[)])"
+ (emacs-lisp-mode)
+ ("vi(")
+ "((<aa[a]>))")))
+ (ert-info ("Select double inner parentheses")
+ (evil-test-buffer
+ "([(]word))"
+ ("dib")
+ "(())")
+ (evil-test-buffer
+ "[(](word))"
+ ("dib")
+ "()")
+ (evil-test-buffer
+ "((word[)])"
+ ("dib")
+ "(())")
+ (evil-test-buffer
+ "((word)[)]"
+ ("dib")
+ "()"))
+ (ert-info ("Select double outer parentheses")
+ (evil-test-buffer
+ "a([(]word))b"
+ ("dab")
+ "a()b")
+ (evil-test-buffer
+ "a[(](word))b"
+ ("dab")
+ "ab")
+ (evil-test-buffer
+ "a((word[)])b"
+ ("dab")
+ "a()b")
+ (evil-test-buffer
+ "a((word)[)]b"
+ ("dab")
+ "ab"))
+ (ert-info ("Select parentheses inside strings")
+ (evil-test-buffer
+ "(aaa \"b(b[b]b)\" aa)"
+ (emacs-lisp-mode)
+ ("va(")
+ "(aaa \"b<(bbb[)]>\" aa)"))
+ (ert-info ("Break out of empty strings")
+ (evil-test-buffer
+ "(aaa \"bb[b]b\" aa)"
+ (emacs-lisp-mode)
+ ("va(")
+ "<(aaa \"bbbb\" aa[)]>"))
+ (ert-info ("Select inner parentheses around strings")
+ (evil-test-buffer
+ "((\"t[e]st\"))\n"
+ (emacs-lisp-mode)
+ ("vib")
+ "((<\"test[\"]>))\n"
+ ("ib")
+ "(<(\"test\"[)]>)\n")
+ (evil-test-buffer
+ "( ( \"t[e]st\" ) )\n"
+ (emacs-lisp-mode)
+ ("vib")
+ "( (< \"test\"[ ]>) )\n"
+ ("ib")
+ "(< ( \"test\" )[ ]>)\n")
+ (evil-test-buffer
+ "((\"t[e]st\"))\n"
+ (emacs-lisp-mode)
+ ("vhhib")
+ "((<[\"]test\">))\n"
+ ("ib")
+ "(<[(]\"test\")>)\n")
+ (evil-test-buffer
+ "( ( \"t[e]st\" ) )\n"
+ (emacs-lisp-mode)
+ ("vhhib")
+ "( (<[ ]\"test\" >) )\n"
+ ("ib")
+ "(<[ ]( \"test\" ) >)\n"))
+ (ert-info ("Select outer parentheses around strings")
+ (evil-test-buffer
+ "((\"t[e]st\"))\n"
+ (emacs-lisp-mode)
+ ("vab")
+ "(<(\"test\"[)]>)\n"
+ ("ab")
+ "<((\"test\")[)]>\n")
+ (evil-test-buffer
+ "( ( \"t[e]st\" ) )\n"
+ (emacs-lisp-mode)
+ ("vab")
+ "( <( \"test\" [)]> )\n"
+ ("ab")
+ "<( ( \"test\" ) [)]>\n")
+ (evil-test-buffer
+ "((\"t[e]st\"))\n"
+ (emacs-lisp-mode)
+ ("vhhab")
+ "(<[(]\"test\")>)\n"
+ ("ab")
+ "<[(](\"test\"))>\n")
+ (evil-test-buffer
+ "( ( \"t[e]st\" ) )\n"
+ (emacs-lisp-mode)
+ ("vhhab")
+ "( <[(] \"test\" )> )\n"
+ ("ab")
+ "<[(] ( \"test\" ) )>\n")
+ (evil-test-buffer
+ "(([\"]\"))\n"
+ ("dab")
+ "([)]\n"))
+ (ert-info ("Select inner paren on different lines")
+ (evil-test-buffer
+ "for (auto i : vector) {
+ if (cond) {
+ do_[s]omething();
+ }
+}"
+ ("vi}")
+ "for (auto i : vector) {
+ if (cond) {
+< do_something();[\n]> }\n}"
+ ("i}")
+ "for (auto i : vector) {
+< if (cond) {
+ do_something();
+ }[\n]>}"))
+ (ert-info ("Enlarge to smallest complete surrounding")
+ (evil-test-buffer
+ "for (auto i : vector) {
+ if (c<ond) {
+ do_[s]>omething();
+ }
+}"
+ ("i}")
+ "for (auto i : vector) {
+< if (cond) {
+ do_something();
+ }[\n]>}"))
+ (ert-info ("yank on blocks is turned linewise")
+ (evil-test-buffer
+ "{\n [f]oo();\n}\n"
+ ("yiBp")
+ "{\n foo();\n [f]oo();\n}\n"))
+ (ert-info ("exclusive like if ending at bol")
+ (evil-test-buffer
+ "(defun foo ()\n[ ] (insert \"bar\")\n )\n"
+ ("cibx" [escape])
+ "([x]\n )\n"))
+ (ert-info ("Operator on empty parentheses")
+ (evil-test-buffer
+ "a([(]))b"
+ ("cibx" [escape])
+ "a(([x]))b")
+ (evil-test-buffer
+ "a(([)])b"
+ ("cibx" [escape])
+ "a(([x]))b")))
+
+(ert-deftest evil-test-forces-linewise-text-objects ()
+ "Test `evil-text-object-change-visual-type' option."
+ :tags '(evil text-object)
+ (let ((evil-text-object-change-visual-type t))
+ (ert-info ("Change visual type")
+ (evil-test-buffer
+ " function(opts) {
+ this.var1 = something();
+ [t]his.var2 = something_else();
+ return something_nasty();
+ }
+"
+ ("Vi}")
+ " function(opts) {
+< this.var1 = something();
+ this.var2 = something_else();
+ return something_nasty();[
+]> }
+"
+ (should (eq (evil-visual-type) 'inclusive)))))
+ (let ((evil-text-object-change-visual-type nil))
+ (ert-info ("Change visual type keeping linewise")
+ (evil-test-buffer
+ " function(opts) {
+ this.var1 = something();
+ [t]his.var2 = something_else();
+ return something_nasty();
+ }
+"
+ ("Vi}")
+ " function(opts) {
+< this.var1 = something();
+ this.var2 = something_else();
+ return something_nasty();\n> }
+"
+ (should (eq (evil-visual-type) 'line)))))
+ (let ((evil-text-object-change-visual-type nil))
+ (ert-info ("Linewise outer block")
+ (evil-test-buffer
+ " function(opts) {
+ this.var1 = something();
+ [t]his.var2 = something_else();
+ return something_nasty();
+ }
+"
+ ("Va}")
+ "< function(opts) {
+ this.var1 = something();
+ this.var2 = something_else();
+ return something_nasty();
+ }
+>"
+ (should (eq (evil-visual-type) 'line)))))
+ (ert-info ("Forced motion type should change text object type")
+ (evil-test-buffer
+ "for (int i=0; i<10; i++) {
+ if ([c]ond) {
+ do_something();
+ }
+}"
+ ("dVi}")
+ "for (int i=0; i<10; i++) {
+\[}]")))
+
+(ert-deftest evil-test-tag-objects ()
+ "Test `evil-inner-tag', etc."
+ :tags '(evil text-object)
+ (ert-info ("Handle nested tags")
+ (evil-test-buffer
+ :visual-start "{"
+ :visual-end "}"
+ "<p><a>f[o]o</a> bar</p>"
+ ("vit")
+ "<p><a>{fo[o]}</a> bar</p>"))
+ (ert-info ("Break out of tags")
+ (evil-test-buffer
+ :visual-start "{"
+ :visual-end "}"
+ "<a[a]a>bbbb</aaa>"
+ ("vit")
+ "<aaa>{bbb[b]}</aaa>")
+ (evil-test-buffer
+ :visual-start "{"
+ :visual-end "}"
+ "<a[a]a>bbbb</aaa>"
+ ("vat")
+ "{<aaa>bbbb</aaa[>]}"))
+ (ert-info ("Handle quoted strings tags")
+ (evil-test-buffer
+ :visual-start "{"
+ :visual-end "}"
+ "<html>
+<body>
+<div id=\"content\">
+\[ ]
+<p>
+UPDATE
+</p>
+<p>
+test hello <a href=\"/deed.zh\">Creative Commons</a>
+</p>
+</div>
+</body>
+</html>
+"
+ ("vit")
+ "<html>
+<body>
+<div id=\"content\">{\n \n<p>
+UPDATE
+</p>
+<p>
+test hello <a href=\"/deed.zh\">Creative Commons</a>
+</p>[\n]}</div>
+</body>
+</html>
+"))
+ (ert-info ("Handle js arrow fns")
+ (evil-test-buffer
+ :visual-start "«"
+ :visual-end "»"
+ "<button foo=\"bar\" onClick={() => fnbody()}>inner [t]ext</button>"
+ ("vit")
+ "<button foo=\"bar\" onClick={() => fnbody()}>«inner tex[t]»</button>"))
+ (ert-info ("Inner tag is selected, even when empty")
+ (evil-test-buffer
+ :visual-start "«"
+ :visual-end "»"
+ "<p>foo<b [c]lass =\"bold\"></b>qux</p>"
+ ("cit" "bar")
+ "<p>foo<b class =\"bold\">bar</b>qux</p>")))
+
+;;; Visual state
+
+(defun evil-test-visual-select (selection &optional mark point)
+ "Verify that TYPE is selected correctly"
+ (let ((type (evil-visual-type selection)))
+ (evil-visual-make-selection mark point type)
+ (ert-info ("Activate region unless SELECTION is `block'")
+ (cond
+ ((eq selection 'block)
+ (should (mark t))
+ (should-not (region-active-p))
+ (should-not transient-mark-mode))
+ (t
+ (should (mark))
+ (should (region-active-p)))))
+ (ert-info ("Refresh Visual markers")
+ (should (= (evil-range-beginning (evil-expand (point) (mark) type))
+ evil-visual-beginning))
+ (should (= (evil-range-end (evil-expand (point) (mark) type))
+ evil-visual-end))
+ (should (eq (evil-visual-type) type))
+ (should (eq evil-visual-direction
+ (if (< (point) (mark)) -1 1))))))
+
+(ert-deftest evil-test-visual-refresh ()
+ "Test `evil-visual-refresh'"
+ :tags '(evil visual)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ (evil-visual-refresh nil nil 'inclusive)
+ (should (= evil-visual-beginning 4))
+ (should (= evil-visual-end 5)))
+ (evil-test-buffer
+ ";; [T]his buffer is for notes."
+ (let ((evil-visual-region-expanded t))
+ (evil-visual-refresh nil nil 'inclusive)
+ (should (= evil-visual-beginning 4))
+ (should (= evil-visual-end 4)))))
+
+(ert-deftest evil-test-non-transient-visual-selection ()
+ "Ensure visual charwise selection can be made when transient mark mode is nil."
+ :tags '(evil visual)
+ (evil-test-buffer
+ "Alpha [b]ravo charlie"
+ (setq-local transient-mark-mode nil)
+ ("ve")
+ "Alpha <brav[o]> charlie"))
+
+(ert-deftest evil-test-visual-exchange ()
+ "Test `exchange-point-and-mark' in Visual character selection"
+ :tags '(evil visual)
+ (evil-test-buffer
+ ";; <[T]his> buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("o")
+ (should (region-active-p))
+ ";; <Thi[s]> buffer is for notes you don't want to save,
+;; and for Lisp evaluation."))
+
+(ert-deftest evil-test-visual-char ()
+ "Test Visual character selection"
+ :tags '(evil visual)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ (evil-test-visual-select 'char)
+ ";; <[T]>his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("e")
+ ";; <Thi[s]> buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("o")
+ ";; <[T]his> buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("d")
+ ";; [ ]buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ ("vV")
+ "<;; [ ]buffer is for notes you don't want to save,\n>\
+;; and for Lisp evaluation."))
+
+(ert-deftest evil-test-visual-line ()
+ "Test Visual line selection"
+ :tags '(evil visual)
+ (evil-test-buffer
+ ";; [T]his buffer is for notes you don't want to save,
+;; and for Lisp evaluation."
+ (evil-test-visual-select 'line)
+ "<;; [T]his buffer is for notes you don't want to save,\n>\
+;; and for Lisp evaluation."
+ ("e")
+ "<;; Thi[s] buffer is for notes you don't want to save,\n>\
+;; and for Lisp evaluation."
+ ("o")
+ "<;; [T]his buffer is for notes you don't want to save,\n>\
+;; and for Lisp evaluation."
+ ("d")
+ ";; [a]nd for Lisp evaluation."))
+
+(ert-deftest evil-test-visual-block ()
+ "Test Visual block selection"
+ :tags '(evil visual)
+ (evil-test-buffer
+ "[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ (evil-test-visual-select 'block)
+ "<[;]>; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; then enter the text in that file's own buffer."
+ ("jjll")
+ "<;; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;;[ ]>then enter the text in that file's own buffer."
+ ("O")
+ ";; <This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+>[;]; then enter the text in that file's own buffer."
+ ("o")
+ ";;[ ]<This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+>;; then enter the text in that file's own buffer."
+ ("O")
+ "<[;]; This buffer is for notes you don't want to save.
+;; If you want to create a file, visit that file with C-x C-f,
+;; >then enter the text in that file's own buffer."
+ ("d")
+ "This buffer is for notes you don't want to save.
+If you want to create a file, visit that file with C-x C-f,
+then enter the text in that file's own buffer.")
+ (ert-info ("Visual block can select over lines of different length")
+ (evil-test-buffer
+ "Short [l]ine
+A much longer line
+A medium line
+Tiny ln"
+ ("\C-v$jd")
+ "Short[ ]
+A much
+A medium line
+Tiny ln"
+ ("jj\C-v" [end] "jd")
+ "Short
+A much
+A me[d]
+Tiny "))
+ (ert-info ("Visual block does not extend up to curswant unless tracking EOL")
+ (evil-test-buffer
+ "[a]bc
+"
+ ("\C-vfcjd")
+ "[b]c
+"))
+ (ert-info ("Pasting visual block")
+ (evil-test-buffer
+ "alpha [b]ravo charlie
+delta echo foxtrot
+golf hotel india
+juliet kilo mike"
+ ("\C-v" "jje" "y" "$" "p")
+ "alpha bravo charlie[b]rav
+delta echo foxtrot echo
+golf hotel india otel
+juliet kilo mike"
+ ("G" "o" [escape] "p")
+ "alpha bravo charliebrav
+delta echo foxtrot echo
+golf hotel india otel
+juliet kilo mike
+[b]rav
+echo
+otel")))
+
+(ert-deftest evil-test-visual-restore ()
+ "Test restoring a previous selection"
+ :tags '(evil visual)
+ (ert-info ("Restore characterwise selection")
+ (evil-test-buffer
+ ";; <[T]his> buffer is for notes."
+ ([escape] "gv")
+ ";; <[T]his> buffer is for notes."))
+ (ert-info ("Restore linewise selection")
+ (evil-test-buffer
+ :visual line
+ "<;; [T]his buffer is for notes.>"
+ ([escape] "gv")
+ "<;; [T]his buffer is for notes.>"))
+ (ert-info ("Restore blockwise selection")
+ (evil-test-buffer
+ :visual block
+ "<;; This buffer is for notes,
+;;[ ]>and for Lisp evaluation."
+ ([escape] "gv")
+ "<;; This buffer is for notes,
+;;[ ]>and for Lisp evaluation.")
+ (ert-info ("After paste shifts initially selected text")
+ (evil-test-buffer
+ :visual block
+ "<1\n2\n[3]>"
+ ("yP")
+ "[1]1\n22\n33"
+ ("gvr*")
+ "[*]1\n*2\n*3")))
+ (ert-info ("Restore linewise visually-pasted selection")
+ (evil-test-buffer
+ "[a]lpha bravo\ncharlie delta
+echo foxtrot\ngolf hotel"
+ ("2yy" "++" "Vp" "gv")
+ "alpha bravo\ncharlie delta
+<alpha bravo\ncharlie delta\n>golf hotel"))
+ ;; 4 repetitions appears necessary, from manual testing
+ (ert-info ("Restore previous linewise selection from linewise selection")
+ (evil-test-buffer
+ "alpha bravo\nch[a]rlie delta\necho foxtrot\ngolf hotel"
+ ("V" [escape] "jV")
+ "alpha bravo\ncharlie delta\n<ec[h]o foxtrot\n>golf hotel"
+ ("gv")
+ "alpha bravo\n<ch[a]rlie delta\n>echo foxtrot\ngolf hotel"
+ ("gv")
+ "alpha bravo\ncharlie delta\n<ec[h]o foxtrot\n>golf hotel"
+ ("gv")
+ "alpha bravo\n<ch[a]rlie delta\n>echo foxtrot\ngolf hotel"
+ ("gv")
+ "alpha bravo\ncharlie delta\n<ec[h]o foxtrot\n>golf hotel"))
+ (ert-info ("Restore between previous charwise selection and linewise selection")
+ (evil-test-buffer
+ "alpha bravo\nch[a]rlie delta\necho foxtrot\ngolf hotel"
+ ("viw" [escape] "jV")
+ "alpha bravo\ncharlie delta\n<echo f[o]xtrot\n>golf hotel"
+ ("gv")
+ "alpha bravo\n<charli[e]> delta\necho foxtrot\ngolf hotel"
+ ("gv")
+ "alpha bravo\ncharlie delta\n<echo f[o]xtrot\n>golf hotel"
+ ("gv")
+ "alpha bravo\n<charli[e]> delta\necho foxtrot\ngolf hotel"
+ ("gv")
+ "alpha bravo\ncharlie delta\n<echo f[o]xtrot\n>golf hotel")))
+
+(ert-deftest evil-test-visual-redefine ()
+ "Test redefining a previous selection"
+ :tags '(evil visual)
+ (ert-info ("Redefine characterwise selection")
+ (evil-test-buffer
+ ";; <[T]his> buffer is for notes."
+ ([escape] "gv")
+ ";; <[T]his> buffer is for notes."
+ ([escape] "2lm<2wm>gv")
+ ";; Th<is buffer [i]>s for notes."))
+ (ert-info ("Redefine linewise selection")
+ (evil-test-buffer
+ :visual line
+ "<[a]lpha bravo
+>charlie delta
+echo foxtrot
+golf hotel"
+ ([escape] "gv")
+ "<[a]lpha bravo
+>charlie delta
+echo foxtrot
+golf hotel"
+ ([escape] "2jm>gv")
+ "<alpha bravo
+charlie delta
+[e]cho foxtrot
+>golf hotel"
+ ([escape] "km<gv")
+ "alpha bravo
+<charlie delta
+[e]cho foxtrot
+>golf hotel"))
+ (ert-info ("Redefine blockwise selection")
+ (evil-test-buffer
+ :visual block
+ "<alpha bravo
+charli[e]> delta
+echo foxtrot
+golf hotel"
+ ([escape] "gv")
+ "<alpha bravo
+charli[e]> delta
+echo foxtrot
+golf hotel"
+ ([escape] "2jm>gv")
+ "<alpha bravo
+charlie delta
+echo foxtrot
+golf h[o]>tel"
+ ([escape] "k0m<gv")
+ "alpha bravo
+charlie delta
+<echo foxtrot
+golf h[o]>tel")))
+
+(ert-deftest evil-test-visual-separate-from-operator-marks ()
+ "Test that visual selection is kept separate from the '[ and '] marks (#1744)."
+ (evil-test-buffer "x\ny"
+ ("ylvpjxgv")
+ "[x]\n"))
+
+;;; Replace state
+
+(ert-deftest evil-test-replacement ()
+ "Test replacing consecutive characters"
+ :tags '(evil replace)
+ (ert-info ("Replace and restore consecutive characters")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes"
+ ("Rfoo")
+ ";; foo[s] buffer is for notes"
+ ([backspace backspace backspace])
+ ";; [T]his buffer is for notes"))
+ (ert-info ("Replace and restore consecutive characters beyond eol")
+ (evil-test-buffer
+ ";; [T]his buffer is for notes"
+ ("wwwwRxxxxxxx")
+ ";; This buffer is for xxxxxxx[]"
+ ([backspace backspace backspace backspace backspace backspace backspace])
+ ";; This buffer is for [n]otes"))
+ (ert-info ("Replace from line below and restore")
+ (define-key evil-replace-state-map (kbd "C-e") #'evil-copy-from-below)
+ (evil-test-buffer
+ ";; [f]oo bar\n;; qux quux"
+ ("R\C-e\C-e\C-e")
+ ";; qux[ ]bar\n;; qux quux"
+ ([backspace backspace backspace])
+ ";; [f]oo bar\n;; qux quux")
+ (define-key evil-replace-state-map (kbd "C-e") nil))
+ (ert-info ("Replace from line above and restore")
+ (define-key evil-replace-state-map (kbd "C-y") #'evil-copy-from-above)
+ (evil-test-buffer
+ ";; foo bar\n;; [q]ux quux"
+ ("R\C-y\C-y\C-y")
+ ";; foo bar\n;; foo[ ]quux"
+ ([backspace backspace backspace])
+ ";; foo bar\n;; [q]ux quux")
+ (define-key evil-replace-state-map (kbd "C-y") nil))
+ (ert-info ("Replace character twice and restore")
+ (evil-test-buffer "[a]"
+ ("Rb" [left] "c" [backspace])
+ "b"))
+ (ert-info ("Can give Replace-state a count repeat it")
+ (evil-test-buffer
+ "a[l]pha bravo"
+ ("3Rx" [escape])
+ "axx[x]a bravo"
+ ("wi\C-a")
+ "axxxa x[]bravo"))
+ (ert-info ("Replace deletion keeps consistent . register")
+ (evil-test-buffer
+ "a[l]pha bravo"
+ ("Rfop" [backspace] "o" [escape])
+ "afo[o]a bravo"
+ ("A \C-@")
+ "afooa bravo fo[o]"))
+ (ert-info ("Replace-state sets ^ mark")
+ (evil-test-buffer
+ "a[l]pha bravo"
+ ("Rxx" [escape] "$")
+ "axxha brav[o]"
+ ("`^")
+ "axx[h]a bravo")))
+
+;;; Ex
+
+(ert-deftest evil-test-ex-parse ()
+ "Test `evil-ex-parse'"
+ :tags '(evil ex)
+ (should (equal (evil-ex-parse "5cmd arg")
+ '(evil-ex-call-command (string-to-number "5") "cmd" "arg")))
+ (should (equal (evil-ex-parse "5cmd !arg")
+ '(evil-ex-call-command (string-to-number "5") "cmd" "!arg")))
+ (should (equal (evil-ex-parse "5 arg")
+ '(evil-ex-call-command (string-to-number "5") "arg" nil)))
+ (should (equal (evil-ex-parse "+1,+2t-1")
+ '(evil-ex-call-command
+ (let ((l1 (evil-ex-line
+ nil
+ (+ (evil-ex-signed-number
+ (intern "+")
+ (string-to-number "1"))))))
+ (save-excursion
+ (and l1 (string= "," ";") (goto-line l1))
+ (evil-ex-range
+ l1 (evil-ex-line
+ nil
+ (+ (evil-ex-signed-number
+ (intern "+")
+ (string-to-number "2")))))))
+ "t"
+ "-1"))))
+
+(ert-deftest evil-test-ex-parse-ranges ()
+ "Test parsing of ranges"
+ :tags '(evil ex)
+ (cl-flet
+ ((mk-range
+ (a b &optional relative)
+ `(let ((l1 ,(when a `(evil-ex-line ,@a))))
+ (save-excursion
+ (and l1 (string= ,(if relative ";" ",") ";") (goto-line l1))
+ (evil-ex-range l1 ,(when b `(evil-ex-line ,@b)))))))
+ (should (equal (evil-ex-parse "%" nil 'range)
+ '(evil-ex-full-range)))
+ (should (equal (evil-ex-parse "*" nil 'range)
+ '(evil-ex-last-visual-range)))
+ (should (equal (evil-ex-parse "5,27" nil 'range)
+ (mk-range '((string-to-number "5") nil)
+ '((string-to-number "27") nil))))
+ (should (equal (evil-ex-parse "5,$" nil 'range)
+ (mk-range '((string-to-number "5") nil)
+ '((evil-ex-last-line) nil))))
+ (should (equal (evil-ex-parse "5,'x" nil 'range)
+ (mk-range '((string-to-number "5") nil)
+ '((evil-ex-marker "x") nil))))
+ (should (equal (evil-ex-parse "`x,`y" nil 'range)
+ '(evil-ex-char-marker-range "x" "y")))
+ (should (equal (evil-ex-parse "`[,`]" nil 'range)
+ '(evil-ex-char-marker-range "[" "]")))
+ (should (equal (evil-ex-parse "5,+" nil 'range)
+ (mk-range '((string-to-number "5") nil)
+ '(nil (+ (evil-ex-signed-number (intern "+") nil))))))
+ (should (equal (evil-ex-parse "5,-" nil 'range)
+ (mk-range '((string-to-number "5") nil)
+ '(nil (+ (evil-ex-signed-number (intern "-") nil))))))
+ (should (equal (evil-ex-parse "5,4+2-7-3+10-" nil 'range)
+ (mk-range
+ '((string-to-number "5") nil)
+ '((string-to-number "4")
+ (+ (evil-ex-signed-number
+ (intern "+") (string-to-number "2"))
+ (evil-ex-signed-number
+ (intern "-") (string-to-number "7"))
+ (evil-ex-signed-number
+ (intern "-") (string-to-number "3"))
+ (evil-ex-signed-number
+ (intern "+") (string-to-number "10"))
+ (evil-ex-signed-number (intern "-") nil))))))
+ (should (equal (evil-ex-parse ".-2,4+2-7-3+10-" nil 'range)
+ (mk-range
+ '((evil-ex-current-line)
+ (+ (evil-ex-signed-number
+ (intern "-") (string-to-number "2"))))
+ '((string-to-number "4")
+ (+ (evil-ex-signed-number
+ (intern "+") (string-to-number "2"))
+ (evil-ex-signed-number
+ (intern "-") (string-to-number "7"))
+ (evil-ex-signed-number
+ (intern "-") (string-to-number "3"))
+ (evil-ex-signed-number
+ (intern "+") (string-to-number "10"))
+ (evil-ex-signed-number
+ (intern "-") nil))))))
+ (should (equal (evil-ex-parse "'a-2,$-10" nil 'range)
+ (mk-range
+ '((evil-ex-marker "a")
+ (+ (evil-ex-signed-number
+ (intern "-") (string-to-number "2"))))
+ '((evil-ex-last-line)
+ (+ (evil-ex-signed-number
+ (intern "-") (string-to-number "10")))))))
+ (should (equal (evil-ex-parse "'[,']" nil 'range)
+ (mk-range '((evil-ex-marker "[") nil)
+ '((evil-ex-marker "]") nil))))
+ (should (equal (evil-ex-parse "'{,'}" nil 'range)
+ (mk-range '((evil-ex-marker "{") nil)
+ '((evil-ex-marker "}") nil))))
+ (should (equal (evil-ex-parse "'(,')" nil 'range)
+ (mk-range '((evil-ex-marker "(") nil)
+ '((evil-ex-marker ")") nil))))
+ (should (equal (evil-ex-parse ",']" nil 'range)
+ (mk-range nil '((evil-ex-marker "]") nil))))
+ (should (equal (evil-ex-parse ";']" nil 'range)
+ (mk-range nil '((evil-ex-marker "]") nil) t)))
+ (should (equal (evil-ex-parse ".+42" nil 'range)
+ '(evil-ex-range
+ (evil-ex-line
+ (evil-ex-current-line)
+ (+ (evil-ex-signed-number
+ (intern "+") (string-to-number "42")))))))))
+
+(ert-deftest evil-test-ex-parse-emacs-commands ()
+ "Test parsing of Emacs commands"
+ :tags '(evil ex)
+ (should (equal (evil-ex-parse "ido-mode")
+ '(evil-ex-call-command nil "ido-mode" nil)))
+ (should (equal (evil-ex-parse "yas/reload-all")
+ '(evil-ex-call-command nil "yas/reload-all" nil)))
+ (should (equal (evil-ex-parse "mu4e")
+ '(evil-ex-call-command nil "mu4e" nil)))
+ (should (equal (evil-ex-parse "make-frame")
+ '(evil-ex-call-command nil "make-frame" nil))))
+
+(ert-deftest evil-text-ex-search-offset ()
+ "Test for addresses like /base//pattern/"
+ :tags '(evil ex)
+ (ert-info ("without base")
+ (evil-test-buffer
+ "[l]ine 1\naaa\nbbb\naaa\nccc\nddd"
+ (":/aaa/d")
+ "line 1\nbbb\naaa\nccc\nddd"))
+ (ert-info ("with base")
+ (evil-test-buffer
+ "[l]ine 1\naaa\nbbb\naaa\nccc\nddd"
+ (":/bbb//aaa/d")
+ "line 1\naaa\nbbb\nccc\nddd"))
+ (ert-info ("range without base")
+ (evil-test-buffer
+ "[l]ine 1\naaa\nbbb\naaa\nccc\nddd\nccc\neee\n"
+ (":/aaa/;/ccc/d")
+ "line 1\nddd\nccc\neee\n"))
+ (ert-info ("range with base")
+ (evil-test-buffer
+ "[l]ine 1\naaa\nbbb\naaa\nccc\nddd\nccc\neee\n"
+ (":/bbb//aaa/;/ddd//ccc/d")
+ "line 1\naaa\nbbb\neee\n")))
+
+(ert-deftest evil-test-ex-goto-line ()
+ "Test if :number moves point to a certain line"
+ :tags '(evil ex)
+ (ert-info ("Move to line")
+ (let ((evil-start-of-line t))
+ (evil-test-buffer
+ :visual line
+ "1\n 2\n [ ]3\n 4\n 5\n"
+ (":4" [return])
+ "1\n 2\n 3\n [4]\n 5\n"
+ (":2" [return])
+ "1\n [2]\n 3\n 4\n 5\n"))))
+
+(ert-deftest evil-test-ex-repeat ()
+ "Test :@: command."
+ :tags '(evil ex)
+ (evil-without-display
+ (ert-info ("Repeat in current line")
+ (evil-test-buffer
+ "[a]bcdef\nabcdef\nabcdef"
+ (":s/[be]/X/g" [return])
+ "[a]XcdXf\nabcdef\nabcdef"
+ ("jj:@:" [return])
+ "aXcdXf\nabcdef\n[a]XcdXf"))
+ (ert-info ("Repeat in specified line")
+ (evil-test-buffer
+ "[a]bcdef\nabcdef\nabcdef"
+ (":s/[be]/X/g" [return])
+ "[a]XcdXf\nabcdef\nabcdef"
+ (":3@:" [return])
+ "aXcdXf\nabcdef\n[a]XcdXf"))
+ (ert-info ("Double repeat, first without then with specified line")
+ (evil-test-buffer
+ "[a]bcdef\nabcdef\nabcdef"
+ (":s/[be]/X/" [return])
+ "[a]Xcdef\nabcdef\nabcdef"
+ ("jj:@:" [return] ":1@:" [return])
+ "[a]XcdXf\nabcdef\naXcdef"))))
+
+(ert-deftest evil-test-ex-repeat2 ()
+ "Test @: command."
+ :tags '(evil ex)
+ (evil-without-display
+ (ert-info ("Repeat in current line")
+ (evil-test-buffer
+ "[a]bcdef\nabcdef\nabcdef"
+ (":s/[be]/X" [return])
+ "[a]Xcdef\nabcdef\nabcdef"
+ ("jj@:")
+ "aXcdef\nabcdef\n[a]Xcdef"))
+ (ert-info ("Repeat with count in current line")
+ (evil-test-buffer
+ "[a]bcdef\nabcdef\nabcdef"
+ (":s/[be]/X" [return])
+ "[a]Xcdef\nabcdef\nabcdef"
+ ("jj2@:")
+ "aXcdef\nabcdef\n[a]XcdXf"))
+ (ert-info ("Do not record dot repeat")
+ (evil-test-buffer
+ ""
+ ("OAAAAAA" [escape] "^")
+ "[A]AAAAA\n"
+ (":s/A/X" [return])
+ "[X]AAAAA\n"
+ ("@:")
+ "[X]XAAAA\n"
+ (".")
+ "AAAAAA\nXXAAAA\n"))))
+
+(ert-deftest evil-test-ex-visual-char-range ()
+ "Test visual character ranges in ex state."
+ :tags '(evil ex visual)
+ (evil-without-display
+ (ert-info ("No character range, inclusive")
+ (let ((evil-visual-char 'inclusive)
+ evil-ex-visual-char-range)
+ (evil-test-buffer
+ "li[n]e 1\nline 2\nline 3\nline 4\n"
+ ("vjll:d" [return])
+ "line 3\nline 4\n")))
+ (ert-info ("No character range, exclusive")
+ (let ((evil-visual-char 'inclusive)
+ evil-ex-visual-char-range)
+ (evil-test-buffer
+ "li[n]e 1\nline 2\nline 3\nline 4\n"
+ ("vjll:d" [return])
+ "line 3\nline 4\n")))
+ (ert-info ("Character range, inclusive")
+ (let ((evil-visual-char 'inclusive)
+ (evil-ex-visual-char-range t))
+ (evil-test-buffer
+ "li[n]e 1\nline 2\nline 3\nline 4\n"
+ ("vjll:d" [return])
+ "li2\nline 3\nline 4\n")))
+ (ert-info ("Character range, exclusive")
+ (let ((evil-visual-char 'exclusive)
+ (evil-ex-visual-char-range t))
+ (evil-test-buffer
+ "li[n]e 1\nline 2\nline 3\nline 4\n"
+ ("vjll:d" [return])
+ "li 2\nline 3\nline 4\n")))))
+
+(ert-deftest evil-test-ex-substitute-replacement ()
+ "Test `evil-ex-substitute' with special replacements."
+ :tags '(evil ex search)
+ (ert-info ("Substitute upper first on first match in line")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar"
+ (":s/\\(foo\\|bar\\)/\\u\\1" [return])
+ "[x]xx Foo bar foo bar foo bar"))
+ (ert-info ("Substitute upper first on first match in line with confirm")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar"
+ (":s/\\(foo\\|bar\\)/\\u\\1/c" [return] "y")
+ "[x]xx Foo bar foo bar foo bar"))
+ (ert-info ("Substitute upper first on whole line")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar"
+ (":s/\\(foo\\|bar\\)/\\u\\1/g" [return])
+ "[x]xx Foo Bar Foo Bar Foo Bar"))
+ (ert-info ("Substitute upper first on whole line")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar"
+ (":s/\\(foo\\|bar\\)/\\u\\1/gc" [return] "yynyyn")
+ "[x]xx Foo Bar foo Bar Foo bar"))
+ (ert-info ("Substitute upper/lower on first match in line")
+ (evil-test-buffer
+ "[x]xx foo BAR foo BAR foo BAR"
+ (":s/\\(f[[:alpha:]]*\\>\\)\\s-*\\(b[[:alpha:]]*\\>\\)/\\L\\2_\\e\\U\\1" [return])
+ "[x]xx bar_FOO foo BAR foo BAR"))
+ (ert-info ("Substitute upper/lower on first match in line with confirm")
+ (evil-test-buffer
+ "[x]xx foo BAR foo BAR foo BAR"
+ (":s/\\(f[[:alpha:]]*\\>\\)\\s-*\\(b[[:alpha:]]*\\>\\)/\\L\\2_\\e\\U\\1/c" [return] "y")
+ "[x]xx bar_FOO foo BAR foo BAR"))
+ (ert-info ("Substitute upper/lower on whole line")
+ (evil-test-buffer
+ "[x]xx foo BAR foo BAR foo BAR"
+ (":s/\\(f[[:alpha:]]*\\>\\)\\s-*\\(b[[:alpha:]]*\\>\\)/\\L\\2_\\e\\U\\1/g" [return])
+ "[x]xx bar_FOO bar_FOO bar_FOO"))
+ (ert-info ("Substitute upper/lower on whole line")
+ (evil-test-buffer
+ "[x]xx foo BAR foo BAR foo BAR"
+ (":s/\\(f[[:alpha:]]*\\>\\)\\s-*\\(b[[:alpha:]]*\\>\\)/\\L\\2_\\e\\U\\1/gc" [return] "yny")
+ "[x]xx bar_FOO foo BAR bar_FOO"))
+ (ert-info ("Substitute with escaped characters in replacement")
+ (evil-test-buffer
+ "[a]bcXdefXghiXjkl\n"
+ (":s/X/\\|\\/\\|/g" [return])
+ "[a]bc|/|def|/|ghi|/|jkl\n"))
+ (ert-info ("Substitute with register")
+ (evil-test-buffer
+ "[a]bc\niiiXiiiXiiiXiii\n"
+ ("\"ayiwj:s/X/\\=@a/g" [return])
+ "abc\n[i]iiabciiiabciiiabciii\n"))
+ (ert-info ("Substitute newlines")
+ (evil-test-buffer
+ "[a]bc\ndef\nghi\n"
+ (":%s/\n/z/" [return])
+ "[a]bczdefzghiz"))
+ (ert-info ("Substitute newlines with g flag")
+ (evil-test-buffer
+ "[a]bc\ndef\nghi\n"
+ (":%s/\n/z/g" [return])
+ "[a]bczdefzghiz"))
+ (ert-info ("Substitute newlines without newline in regexp")
+ (evil-test-buffer
+ "[A]BC\nDEF\nGHI\n"
+ (":%s/[^]]*/z/" [return])
+ "Z"))
+ (ert-info ("Substitute n flag does not replace")
+ (evil-test-buffer
+ "[a]bc\naef\nahi\n"
+ (":%s/a//n" [return])
+ "[a]bc\naef\nahi\n"))
+ (ert-info ("Substitute n flag does not replace with g flag")
+ (evil-test-buffer
+ "[a]bc\naef\nahi\n"
+ (":%s/a//gn" [return])
+ "[a]bc\naef\nahi\n"))
+ (ert-info ("Substitute $ does not loop infinitely")
+ (evil-test-buffer
+ "[a]bc\ndef\nghi"
+ (":%s/$/ END/g" [return])
+ "abc END\ndef END\n[g]hi END"))
+ (ert-info ("Substitute the zero-length beginning of line character")
+ (evil-test-buffer
+ "[a]bc\ndef\nghi"
+ (":s/^/ #/" [return])
+ " [#]abc\ndef\nghi"))
+ (ert-info ("Substitute the zero-length beginning of line character with g flag")
+ (evil-test-buffer
+ "[a]bc\ndef\nghi"
+ (":s/^/ #/g" [return])
+ " [#]abc\ndef\nghi"))
+ (ert-info ("Use Substitute to delete individual characters")
+ (evil-test-buffer
+ "[x]xyxxz"
+ (":%s/x//g" [return])
+ "[y]z"))
+ (ert-info ("Substitute doesn't match final empty line")
+ (evil-test-buffer
+ "abc\n[d]ef\n\nghi"
+ (":s/$/4" [return])
+ "abc\n[d]ef4\n\nghi")
+ (evil-test-buffer
+ "abc\n[d]ef\n\nghi"
+ (":s/f\\w*/4" [return])
+ "abc\n[d]e4\n\nghi"))
+ (ert-info ("Substitute doesn't move point if 0 matches")
+ (evil-test-buffer
+ "abc\nd[e]f\nghi"
+ (":%s/nothere/foo" [return])
+ "abc\nd[e]f\nghi"))
+ (ert-info ("Substitute up to EOB works")
+ (evil-test-buffer "[f]oo"
+ (":s/foo")
+ ""))
+ (ert-info ("Substitute with multi-line replacement")
+ (evil-test-buffer "x"
+ (":s/./foo\\nbar")
+ "foo\n[b]ar"))
+ (ert-info ("Use replace count in substitution")
+ (evil-test-buffer "xx"
+ (":s/./\\#/g")
+ "01"))
+ (ert-info ("Substitute with `calc' Lisp expression")
+ (evil-test-buffer "1 + 2"
+ (":s/.*/\\,(calc-eval \\0)")
+ "3")))
+
+(ert-deftest evil-test-ex-repeat-substitute-replacement ()
+ "Test `evil-ex-substitute' with repeating of previous substitutions."
+ :tags '(evil ex search)
+ (ert-info ("Repeat previous pattern")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar"
+ (":s/foo/AAA" [return])
+ "[x]xx AAA bar foo bar foo bar"
+ (":s//BBB" [return])
+ "[x]xx AAA bar BBB bar foo bar"
+ ("/bar" [return] ":s//CCC" [return])
+ "[x]xx AAA CCC BBB bar foo bar"
+ (":s/ar/XX" [return])
+ "[x]xx AAA CCC BBB bXX foo bar"
+ (":s//YY" [return])
+ "[x]xx AAA CCC BBB bXX foo bYY"))
+ (ert-info ("Repeat previous replacement")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar"
+ (":s/foo/AAA" [return])
+ "[x]xx AAA bar foo bar foo bar"
+ (":s/bar/~" [return])
+ "[x]xx AAA AAA foo bar foo bar"))
+ (ert-info ("Repeat with previous flags")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar"
+ (":s/foo/AAA/g" [return])
+ "[x]xx AAA bar AAA bar AAA bar"
+ (":s/bar/BBB/&" [return])
+ "[x]xx AAA BBB AAA BBB AAA BBB"))
+ (ert-info ("Repeat previous substitute without flags")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA/g" [return])
+ "[x]xx AAA bar AAA bar AAA bar\nxxx foo bar foo bar foo bar"
+ ("j:s" [return])
+ "xxx AAA bar AAA bar AAA bar\n[x]xx AAA bar foo bar foo bar"
+ ("/bar" [return] ":s" [return])
+ "xxx AAA bar AAA bar AAA bar\n[x]xx AAA bar AAA bar foo bar")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA/g" [return])
+ "[x]xx AAA bar AAA bar AAA bar\nxxx foo bar foo bar foo bar"
+ ("j&")
+ "xxx AAA bar AAA bar AAA bar\n[x]xx AAA bar foo bar foo bar")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA/g" [return])
+ "[x]xx AAA bar AAA bar AAA bar\nxxx foo bar foo bar foo bar"
+ ("j:&" [return])
+ "xxx AAA bar AAA bar AAA bar\n[x]xx AAA bar foo bar foo bar"))
+ (ert-info ("Repeat previous substitute with the same flags")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA/g" [return])
+ "[x]xx AAA bar AAA bar AAA bar\nxxx foo bar foo bar foo bar"
+ ("j:s//~/&" [return])
+ "xxx AAA bar AAA bar AAA bar\n[x]xx AAA bar AAA bar AAA bar")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA/g" [return])
+ "[x]xx AAA bar AAA bar AAA bar\nxxx foo bar foo bar foo bar"
+ ("j:&&" [return])
+ "xxx AAA bar AAA bar AAA bar\n[x]xx AAA bar AAA bar AAA bar"))
+ (ert-info ("Repeat previous substitute with new flags")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA" [return])
+ "[x]xx AAA bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ ("j:s g" [return])
+ "xxx AAA bar foo bar foo bar\n[x]xx AAA bar AAA bar AAA bar")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA" [return])
+ "[x]xx AAA bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ ("j:& g" [return])
+ "xxx AAA bar foo bar foo bar\n[x]xx AAA bar AAA bar AAA bar"))
+ (ert-info ("Repeat with previous search pattern")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA" [return])
+ "[x]xx AAA bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ ("/bar" [return])
+ "xxx AAA [b]ar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":2s rg" [return])
+ "xxx AAA bar foo bar foo bar\n[x]xx foo AAA foo AAA foo AAA")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA" [return])
+ "[x]xx AAA bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ ("/bar" [return])
+ "xxx AAA [b]ar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":2~ g" [return])
+ "xxx AAA bar foo bar foo bar\n[x]xx foo AAA foo AAA foo AAA"))
+ (ert-info ("Repeat previous substitute globally")
+ (evil-test-buffer
+ "[x]xx foo bar foo bar foo bar\nxxx foo bar foo bar foo bar"
+ (":s/foo/AAA/g" [return])
+ "[x]xx AAA bar AAA bar AAA bar\nxxx foo bar foo bar foo bar"
+ ("g&")
+ "xxx AAA bar AAA bar AAA bar\n[x]xx AAA bar AAA bar AAA bar"))
+ (ert-info ("Substitute with last search, maintaining case sensitivty")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (evil-test-buffer
+ "[a]lpha\nbravo\nbravo\ncharlie\nBravo\ndelta"
+ ("/\\Cbravo" [return])
+ "alpha\n[b]ravo\nbravo\ncharlie\nBravo\ndelta"
+ (":%s//zulu" [return])
+ "alpha\nzulu\n[z]ulu\ncharlie\nBravo\ndelta"))
+ (ert-info ("Repeat magic multiple times")
+ (let ((evil-magic 'very-magic)
+ (evil-ex-search-vim-style-regexp t))
+ (evil-test-buffer
+ "[b]ravo, alpha\ndelta, charlie\nfoxtrot, echo\nhotel, golf"
+ (":s/(.*), (.*)/\\2 \\1" [return])
+ "alpha bravo\ndelta, charlie\nfoxtrot, echo\nhotel, golf"
+ ("j&")
+ "alpha bravo\ncharlie delta\nfoxtrot, echo\nhotel, golf"
+ ("j&")
+ "alpha bravo\ncharlie delta\necho foxtrot\nhotel, golf"
+ ("j&")
+ "alpha bravo\ncharlie delta\necho foxtrot\ngolf hotel"))))
+
+(ert-deftest evil-test-ex-regex-without-case ()
+ "Test `evil-ex-regex-without-case'"
+ :tags '(evil ex search)
+ (should (equal (evil-ex-regex-without-case "cdeCDE")
+ "cdeCDE"))
+ (should (equal (evil-ex-regex-without-case "\\ccde\\CCDE")
+ "cdeCDE"))
+ (should (equal (evil-ex-regex-without-case "\\\\ccde\\\\CCDE")
+ "\\\\ccde\\\\CCDE"))
+ (should (equal (evil-ex-regex-without-case "\\\\\\ccde\\\\\\CCDE")
+ "\\\\cde\\\\CDE")))
+
+(ert-deftest evil-test-ex-regex-case ()
+ "Test `evil-ex-regex-case'"
+ :tags '(evil ex search)
+ (should (equal (evil-ex-regex-case "cde" 'smart) 'insensitive))
+ (should (equal (evil-ex-regex-case "cDe" 'smart) 'sensitive))
+ (should (equal (evil-ex-regex-case "cde" 'sensitive) 'sensitive))
+ (should (equal (evil-ex-regex-case "cde" 'insensitive) 'insensitive))
+ (should (equal (evil-ex-regex-case "\\ccde" 'smart) 'insensitive))
+ (should (equal (evil-ex-regex-case "\\cCde" 'smart) 'insensitive))
+ (should (equal (evil-ex-regex-case "\\Ccde" 'smart) 'sensitive))
+ (should (equal (evil-ex-regex-case "\\CCde" 'smart) 'sensitive))
+ (should (equal (evil-ex-regex-case "\\ccd\\Ce" 'smart) 'insensitive))
+ (should (equal (evil-ex-regex-case "\\cCd\\Ce" 'smart) 'insensitive))
+ (should (equal (evil-ex-regex-case "\\Ccd\\ce" 'smart) 'sensitive))
+ (should (equal (evil-ex-regex-case "\\CCd\\ce" 'smart) 'sensitive)))
+
+(ert-deftest evil-test-ex-search ()
+ "Test evil internal search."
+ :tags '(evil ex search)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (ert-info ("Test smart case insensitive")
+ (evil-test-buffer
+ "[s]tart you YOU You you YOU You"
+ ("/you" [return])
+ "start [y]ou YOU You you YOU You"
+ ("n")
+ "start you [Y]OU You you YOU You"
+ ("n")
+ "start you YOU [Y]ou you YOU You"
+ ("n")
+ "start you YOU You [y]ou YOU You"))
+ (ert-info ("Test smart case sensitive")
+ (evil-test-buffer
+ "[s]tart you YOU You you YOU You"
+ ("/You" [return])
+ "start you YOU [Y]ou you YOU You"
+ ("n")
+ "start you YOU You you YOU [Y]ou"))
+ (ert-info ("Test insensitive")
+ (evil-test-buffer
+ "[s]tart you YOU You you YOU You"
+ ("/\\cyou" [return])
+ "start [y]ou YOU You you YOU You"
+ ("n")
+ "start you [Y]OU You you YOU You"
+ ("n")
+ "start you YOU [Y]ou you YOU You"
+ ("n")
+ "start you YOU You [y]ou YOU You"))
+ (ert-info ("Test sensitive")
+ (evil-test-buffer
+ "[s]tart you YOU You you YOU You"
+ ("/\\Cyou" [return])
+ "start [y]ou YOU You you YOU You"
+ ("n")
+ "start you YOU You [y]ou YOU You"))
+ (ert-info ("Test failing search does not move point")
+ (evil-test-buffer
+ "foo [f]oo foo\nbar bar2 bar\nbaz baz baz\n"
+ (error search-failed "/foofoo" [return])
+ "foo [f]oo foo\nbar bar2 bar\nbaz baz baz\n"
+ ("/bar2" [return])
+ "foo foo foo\nbar [b]ar2 bar\nbaz baz baz\n"
+ ("dw")
+ "foo foo foo\nbar [b]ar\nbaz baz baz\n"
+ (error search-failed "n")
+ "foo foo foo\nbar [b]ar\nbaz baz baz\n"
+ (error search-failed "N")
+ "foo foo foo\nbar [b]ar\nbaz baz baz\n"))
+ (ert-info ("Test search for newline")
+ (evil-test-buffer
+ "[s]tart\nline 2\nline 3\n\n"
+ ("/\\n" [return])
+ "star[t]\nline 2\nline 3\n\n"
+ ("n")
+ "start\nline [2]\nline 3\n\n"
+ ("n")
+ "start\nline 2\nline [3]\n\n"
+ ("n")
+ "start\nline 2\nline 3\n[]\n"))
+ (ert-info ("Can search for start/end of symbol")
+ (let ((evil-magic 'very-magic))
+ (evil-test-buffer
+ "[a]lpha bravo bra charlie"
+ ("/bra\\_>" [return])
+ "alpha bravo [b]ra charlie")))
+ (ert-info ("Can search for literal < and >")
+ (let ((evil-magic 'very-magic))
+ (evil-test-buffer
+ :visual-start "«"
+ :visual-end "»"
+ "[a]lpha bravo <bravo> charlie"
+ ("/<bravo>" [return])
+ "alpha bravo [<]bravo> charlie")))
+ (ert-info ("Can paste from register in ex-search")
+ (evil-test-buffer
+ "Alpha [b]ravo charlie alpha bravo delta bravo delta"
+ ("\"bye" "w")
+ "Alpha bravo [c]harlie alpha bravo delta bravo delta"
+ ("/\C-rb" [return])
+ "Alpha bravo charlie alpha [b]ravo delta bravo delta"
+ ("w/\C-r\C-o" [return])
+ "Alpha bravo charlie alpha bravo delta bravo [d]elta"))
+ (ert-info ("Can use C-w yank-word functionality")
+ (let ((old-val evil-want-C-w-delete))
+ (custom-set-variables '(evil-want-C-w-delete nil))
+ (evil-test-buffer
+ "alpha [b]ravo charlie delta bravo echo"
+ ("/\C-w" [return])
+ "alpha bravo charlie delta [b]ravo echo")
+ (custom-set-variables `(evil-want-C-w-delete ,old-val))))
+ (ert-info ("Can use backreferences with vim-style regexp")
+ (let ((evil-ex-search-vim-style-regexp t))
+ (evil-test-buffer
+ "[a]bacababcacabccadefghij"
+ ;; Very magic
+ ("/\\v(.)(.)(.)\\3\\1/e" [return])
+ "abacababcacabcc[a]defghij")
+ (evil-test-buffer
+ "[a]bacababcacabccadefghij"
+ ;; Default magic
+ ("/\\(.\\)\\(.\\)\\(.\\)\\3\\1/e" [return])
+ "abacababcacabcc[a]defghij")
+ (evil-test-buffer
+ "[a]bacababcac1abcca1defghij"
+ ;; With literal numbers
+ ("/\\(.\\)\\(.\\)\\(.\\)\\3\\11/e" [return])
+ "abacababcac1abcca[1]defghij")))))
+
+(ert-deftest evil-test-ex-search-offset ()
+ "Test search offsets."
+ :tags '(evil ex search)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (ert-info ("Test line offsets")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/2")
+ "foo foo\nbar bar\nbaz baz\n[A]nother line\nAnd yet another line"
+ ("?bar?-")
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/r bar/")
+ "foo foo\nba[r] bar\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Test end offsets")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/e")
+ "foo foo\nba[r] bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/baz/e+2")
+ "foo foo\nbar bar\nbaz [b]az\nAnother line\nAnd yet another line"
+ ("/line/e-1")
+ "foo foo\nbar bar\nbaz baz\nAnother li[n]e\nAnd yet another line"))
+ (ert-info ("Test begin offsets")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/b")
+ "foo foo\n[b]ar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/baz/b+2")
+ "foo foo\nbar bar\nba[z] baz\nAnother line\nAnd yet another line"
+ ("/line/b-")
+ "foo foo\nbar bar\nbaz baz\nAnother[ ]line\nAnd yet another line"))
+ (ert-info ("Test search-next with offset")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/ ba/+1" [return])
+ "foo foo\nbar bar\n[b]az baz\nAnother line\nAnd yet another line"
+ ("n")
+ "foo foo\nbar bar\nbaz baz\n[A]nother line\nAnd yet another line"))
+ (ert-info ("Test search next after /$")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\n\n\line 4\n"
+ ("/$" [return])
+ "line [1]\nline 2\n\n\line 4\n"
+ ("n")
+ "line 1\nline [2]\n\n\line 4\n"
+ ("n")
+ "line 1\nline 2\n[\n]\line 4\n"
+ ("n")
+ "line 1\nline 2\n\n\line [4]\n"))))
+
+(ert-deftest evil-test-ex-search-pattern-offset ()
+ "Test pattern offsets."
+ :tags '(evil ex search)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (ert-info ("Test simple pattern offsets")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nfoo foo\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/;/foo" [return])
+ "foo foo\nbar bar\n[f]oo foo\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Test simple pattern offsets in backward direction")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nfoo foo\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/;?foo" [return])
+ "foo [f]oo\nbar bar\nfoo foo\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Ensure second pattern is used for search repeat")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nfoo foo\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/;?foo" [return] "n")
+ "foo foo\nbar bar\n[f]oo foo\nbaz baz\nAnother line\nAnd yet another line"))))
+
+(ert-deftest evil-test-ex-search-repeat ()
+ "Test repeat of search."
+ :tags '(evil ex search)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (ert-info ("Test repeat of simple pattern")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar" [return] "/" [return])
+ "foo foo\nbar [b]ar\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Test repeat of simple pattern with new offset")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar" [return] "//e" [return])
+ "foo foo\nbar ba[r]\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Test repeat of pattern with offset")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/e" [return] "/" [return])
+ "foo foo\nbar ba[r]\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Test repeat of pattern with offset without offset")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/e" [return] "//" [return])
+ "foo foo\nbar [b]ar\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Test repeat of pattern with offset with new offset")
+ (evil-test-buffer
+ "[f]oo foo\nbar bar\nbaz baz\nAnother line\nAnd yet another line"
+ ("/bar/e" [return] "//b+1" [return])
+ "foo foo\nbar b[a]r\nbaz baz\nAnother line\nAnd yet another line"))
+ (ert-info ("Test repeat of pattern in the same search")
+ (evil-test-buffer
+ "[a]lpha bravo charlie delta charlie alpha bravo alpha"
+ ("/charlie/;/")
+ "alpha bravo charlie delta [c]harlie alpha bravo alpha"
+ ("/alpha/;//")
+ "alpha bravo charlie delta charlie alpha bravo [a]lpha"
+ ("?charlie?;?")
+ "alpha bravo [c]harlie delta charlie alpha bravo alpha")
+ (ert-info ("including when switching direction")
+ (evil-test-buffer
+ "[a]lpha bravo charlie delta charlie alpha bravo alpha"
+ ("/bravo/;?")
+ "alpha bravo charlie delta charlie alpha [b]ravo alpha"
+ ("?alpha?;//")
+ "alpha bravo charlie delta charlie alpha bravo [a]lpha")))))
+
+(ert-deftest evil-test-ex-search-word ()
+ "Test search for word under point."
+ :tags '(evil ex search)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (setq evil-ex-search-history nil)
+ (evil-test-buffer
+ "so[m]e text with a strange word
+and here some other stuff
+maybe we need one line more with some text\n"
+ (setq evil-symbol-word-search nil)
+ ("*")
+ "some text with a strange word
+and here [s]ome other stuff
+maybe we need one line more with some text\n"
+ ("n")
+ "some text with a strange word
+and here some other stuff
+maybe we need one line more with [s]ome text\n"
+ (ert-info ("Search history")
+ (should (equal evil-ex-search-history '("\\<some\\>"))))
+ ("*")
+ "[s]ome text with a strange word
+and here some other stuff
+maybe we need one line more with some text\n"
+ (ert-info ("Search history with double pattern")
+ (should (equal evil-ex-search-history '("\\<some\\>")))))
+ (ert-info ("Test unbounded search")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (setq evil-ex-search-history nil)
+ (evil-test-buffer
+ "[s]ymbol\n(defun my-symbolfunc ())\n(defvar my-symbolvar)\nanother symbol\n"
+ ("*")
+ (setq evil-symbol-word-search nil)
+ "symbol\n(defun my-symbolfunc ())\n(defvar my-symbolvar)\nanother [s]ymbol\n"
+ ("ggg*")
+ "symbol\n(defun my-[s]ymbolfunc ())\n(defvar my-symbolvar)\nanother symbol\n"
+ (should (equal evil-ex-search-history '("symbol" "\\<symbol\\>")))
+ ("n")
+ "symbol\n(defun my-symbolfunc ())\n(defvar my-[s]ymbolvar)\nanother symbol\n"))
+ (ert-info ("Test symbol search")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (evil-test-buffer
+ "(defun my-s[y]mbol-func ())\n(defvar my-symbol-var)\n(my-symbol-func)\n(setq my-symbol-func2 (my-symbol-func))\n"
+ (setq evil-symbol-word-search t)
+ ("*")
+ "(defun my-symbol-func ())\n(defvar my-symbol-var)\n([m]y-symbol-func)\n(setq my-symbol-func2 (my-symbol-func))\n"
+ ("n")
+ "(defun my-symbol-func ())\n(defvar my-symbol-var)\n(my-symbol-func)\n(setq my-symbol-func2 ([m]y-symbol-func))\n"))
+ (ert-info ("Test with non-nil `evil-ex-search-vim-style-regexp'")
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (let ((evil-ex-search-vim-style-regexp t)
+ (evil-magic 'very-magic))
+ (evil-test-buffer
+ "[a]lpha bravo alpha charlie alpha"
+ ("*")
+ "alpha bravo [a]lpha charlie alpha"
+ ("/" [return])
+ "alpha bravo alpha charlie [a]lpha")))))
+
+(ert-deftest evil-test-ex-search-motion ()
+ "Test that Ex forward search, as a motion, can be repeated."
+ :tags '(evil ex search)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (evil-test-buffer "alpha [b]ravo charlie delta golf hotel charlie india"
+ ("c/charlie" [return] "replacement " [escape] "4w.")
+ "alpha replacement charlie delta golf replacement[ ]charlie india")))
+
+(ert-deftest evil-test-ex-search-next+previous-match ()
+ :tags '(evil ex search)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (ert-info ("evil-next-match in normal state")
+ (evil-test-buffer
+ "[b]ravo charlie delta charlie alpha charlie bravo"
+ ("/charlie" [return] "e")
+ "bravo charli[e] delta charlie alpha charlie bravo"
+ ("gn")
+ "bravo <charli[e]> delta charlie alpha charlie bravo"
+ ([escape] "b")
+ "bravo [c]harlie delta charlie alpha charlie bravo"
+ ("gn")
+ "bravo <charli[e]> delta charlie alpha charlie bravo"
+ ([escape] "w")
+ "bravo charlie [d]elta charlie alpha charlie bravo"
+ ("gn")
+ "bravo charlie delta <charli[e]> alpha charlie bravo"
+ ([escape] "^")
+ "[b]ravo charlie delta charlie alpha charlie bravo"
+ ("3gn")
+ "bravo charlie delta charlie alpha <charli[e]> bravo"))
+ (ert-info ("evil-previous-match in normal state")
+ (evil-test-buffer
+ "[b]ravo charlie delta charlie alpha charlie bravo"
+ ("/charlie" [return] "e")
+ "bravo charli[e] delta charlie alpha charlie bravo"
+ ("$gN")
+ "bravo charlie delta charlie alpha <[c]harlie> bravo"
+ ([escape] "gN")
+ "bravo charlie delta charlie alpha <[c]harlie> bravo"
+ ([escape] "e" "2gN")
+ "bravo charlie delta <[c]harlie> alpha charlie bravo"))
+ (ert-info ("evil-next-match in visual state")
+ (evil-test-buffer
+ "[b]ravo charlie delta charlie alpha charlie bravo"
+ ("/charlie" [return] "e")
+ "bravo charli[e] delta charlie alpha charlie bravo"
+ ("gn")
+ "bravo <charli[e]> delta charlie alpha charlie bravo"
+ ("gn")
+ "bravo <charlie delta charli[e]> alpha charlie bravo"
+ ("o")
+ "bravo <[c]harlie delta charlie> alpha charlie bravo"
+ ("gn")
+ "bravo charli<[e] delta charlie> alpha charlie bravo"
+ ([escape] "^v2gn")
+ "<bravo charlie delta charli[e]> alpha charlie bravo"))
+ (ert-info ("evil-previous-match in visual state")
+ (evil-test-buffer
+ "bravo charlie delta charlie alpha charlie brav[o]"
+ ("?charlie" [return])
+ "bravo charlie delta charlie alpha [c]harlie bravo"
+ ("gN")
+ "bravo charlie delta charlie alpha <[c]harlie> bravo"
+ ("gN")
+ "bravo charlie delta <[c]harlie alpha charlie> bravo"
+ ("o")
+ "bravo charlie delta <charlie alpha charli[e]> bravo"
+ ("gN")
+ "bravo charlie delta <charlie alpha [c]>harlie bravo"
+ ([escape] "$v2gN")
+ "bravo charlie delta <[c]harlie alpha charlie bravo>"))
+ (ert-info ("evil-match in operator state")
+ (evil-test-buffer
+ "[b]ravo charlie delta charlie alpha charlie bravo"
+ ("/charlie" [return])
+ "bravo [c]harlie delta charlie alpha charlie bravo"
+ ("cgn" "foo" [escape])
+ "bravo fo[o] delta charlie alpha charlie bravo"
+ (".")
+ "bravo foo delta fo[o] alpha charlie bravo"
+ ("$cgN" "bar" [escape])
+ "bravo foo delta foo alpha ba[r] bravo"))
+ (ert-info ("Unfound evil ex next match doesn't move cursor")
+ (evil-test-buffer
+ "[a]lpha bravo"
+ (should-error (execute-kbd-macro "/zulu"))
+ "[a]lpha bravo"
+ (should-error (execute-kbd-macro "gn"))
+ "[a]lpha bravo"))))
+
+(ert-deftest evil-test-isearch-word ()
+ "Test isearch for word under point."
+ :tags '(evil isearch)
+ (evil-without-display
+ (evil-select-search-module 'evil-search-module 'isearch)
+ (evil-test-buffer
+ "so[m]e text with a strange word
+and here some other stuff
+maybe we need one line more with some text\n"
+ (setq evil-symbol-word-search nil)
+ ("*")
+ "some text with a strange word
+and here [s]ome other stuff
+maybe we need one line more with some text\n"
+ ("n")
+ "some text with a strange word
+and here some other stuff
+maybe we need one line more with [s]ome text\n"
+ ("*")
+ "[s]ome text with a strange word
+and here some other stuff
+maybe we need one line more with some text\n")
+ (ert-info ("Test unbounded search")
+ (evil-select-search-module 'evil-search-module 'isearch)
+ (evil-test-buffer
+ "[s]ymbol\n(defun my-symbolfunc ())\n(defvar my-symbolvar)\nanother symbol\n"
+ (setq evil-symbol-word-search nil)
+ ("*")
+ "symbol\n(defun my-symbolfunc ())\n(defvar my-symbolvar)\nanother [s]ymbol\n"
+ ("ggg*")
+ "symbol\n(defun my-[s]ymbolfunc ())\n(defvar my-symbolvar)\nanother symbol\n"
+ ("n")
+ "symbol\n(defun my-symbolfunc ())\n(defvar my-[s]ymbolvar)\nanother symbol\n"))
+ (ert-info ("Test symbol search")
+ (evil-select-search-module 'evil-search-module 'isearch)
+ (evil-test-buffer
+ "(defun my-s[y]mbol-func ())\n(defvar my-symbol-var)\n(my-symbol-func)\n(setq my-symbol-func2 (my-symbol-func))\n"
+ (setq evil-symbol-word-search t)
+ ("*")
+ "(defun my-symbol-func ())\n(defvar my-symbol-var)\n([m]y-symbol-func)\n(setq my-symbol-func2 (my-symbol-func))\n"
+ ("n")
+ "(defun my-symbol-func ())\n(defvar my-symbol-var)\n(my-symbol-func)\n(setq my-symbol-func2 ([m]y-symbol-func))\n"))))
+
+(ert-deftest evil-test-read ()
+ "Test of `evil-read'"
+ :tags '(evil ex)
+ (evil-without-display
+ (ert-info ("Test insertion of file with trailing newline")
+ (evil-with-temp-file name
+ "temp file 1\ntemp file 2\n"
+ (ert-info ("At first line")
+ (evil-test-buffer
+ "[l]ine 1\nline 2"
+ ((vconcat ":read " name [return]))
+ "line 1\n[t]emp file 1\ntemp file 2\nline 2"))
+ (ert-info ("At last line")
+ (evil-test-buffer
+ "line 1\n[l]ine 2"
+ ((vconcat ":read " name [return]))
+ "line 1\nline 2\n[t]emp file 1\ntemp file 2\n"))
+ (ert-info ("After specified line number")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4\line 5"
+ ((vconcat ":3read " name [return]))
+ "line 1\nline 2\nline 3\n[t]emp file 1\ntemp file 2\nline 4\line 5"))
+ (ert-info ("After specified line 0")
+ (evil-test-buffer
+ "line 1\nline [2]\nline 3\nline 4\line 5"
+ ((vconcat ":0read " name [return]))
+ "[t]emp file 1\ntemp file 2\nline 1\nline 2\nline 3\nline 4\line 5"))))
+ (ert-info ("Test insertion of file without trailing newline")
+ (evil-with-temp-file name
+ "temp file 1\ntemp file 2"
+ (evil-test-buffer
+ "[l]ine 1\nline 2"
+ ((vconcat ":read " name [return]))
+ "line 1\n[t]emp file 1\ntemp file 2\nline 2")))
+ (ert-info ("Test insertion of shell command")
+ (ert-info ("with space")
+ (evil-test-buffer
+ "[l]line 1\nline 2"
+ (":read !echo cmd line 1" [return])
+ "line 1\n[c]md line 1\nline 2"))
+ (ert-info ("without space")
+ (evil-test-buffer
+ "[l]line 1\nline 2"
+ (":read!echo cmd line 1" [return])
+ "line 1\n[c]md line 1\nline 2")))
+ (ert-info ("Test substitution of % in shell commands")
+ (evil-with-temp-file name
+ "3\n2\n1\n"
+ (evil-test-buffer
+ (":e " name [return])
+ "[3]\n2\n1\n"
+ (":read !echo %" [return] ":w" [return])
+ (file name (concat "3\n"
+ (buffer-file-name) "\n"
+ "2\n"
+ "1\n")))))
+ (ert-info ("Ensure that point ends up at the last line of shell output, if any")
+ (evil-with-temp-file name
+ "3\n2\n1\n"
+ (evil-test-buffer
+ "[l]ine 1\nline 2"
+ ((vconcat ":read !cat " name [return]))
+ "line 1\n3\n2\n[1]\nline 2")))
+ (ert-info ("Test insertion of shell command without trailing newline")
+ (ert-info ("with space")
+ (evil-test-buffer
+ "[l]line 1\nline 2"
+ (":read !echo -n cmd line 1" [return])
+ "line 1\n[c]md line 1\nline 2"))
+ (ert-info ("without space")
+ (evil-test-buffer
+ "[l]line 1\nline 2"
+ (":read!echo -n cmd line 1" [return])
+ "line 1\n[c]md line 1\nline 2")))))
+
+(ert-deftest evil-test-shell-command ()
+ "Test `evil-shell-command'."
+ (ert-info ("ex shell command")
+ (evil-test-buffer
+ "[l]ine 5\nline 4\nline 3\nline 2\nline 1\n"
+ (":2,3!sort" [return])
+ "line 5\n[l]ine 3\nline 4\nline 2\nline 1\n"))
+ (ert-info ("shell command operator with count")
+ (evil-test-buffer
+ "line 5\n[l]ine 4\nline 3\nline 2\nline 1\n"
+ ("2!!sort" [return])
+ "line 5\n[l]ine 3\nline 4\nline 2\nline 1\n"))
+ (ert-info ("shell command operator with motion")
+ (evil-test-buffer
+ "line 5\n[l]ine 4\nline 3\nline 2\nline 1\n"
+ ("!jsort" [return])
+ "line 5\n[l]ine 3\nline 4\nline 2\nline 1\n"))
+ (ert-info ("shell command operator with backward motion")
+ (evil-test-buffer
+ "line 5\nline 4\n[l]ine 3\nline 2\nline 1\n"
+ ("!ksort" [return])
+ "line 5\n[l]ine 3\nline 4\nline 2\nline 1\n"))
+ (ert-info ("shell command operator with visual selection")
+ (evil-test-buffer
+ "line 5\n[l]ine 4\nline 3\nline 2\nline 1\n"
+ ("vj!sort" [return])
+ "line 5\n[l]ine 3\nline 4\nline 2\nline 1\n")))
+
+(defmacro evil-with-both-search-modules (&rest body)
+ `(mapc (lambda (search-module)
+ (setq evil-search-forward-history nil
+ evil-search-backward-history nil
+ evil-ex-search-history nil)
+ (evil-select-search-module 'evil-search-module search-module)
+ ,@body)
+ '(isearch evil-search)))
+
+(ert-deftest evil-test-global ()
+ "Test `evil-ex-global'."
+ :tags '(evil ex global)
+ (ert-info ("global delete")
+ (evil-test-buffer
+ "[n]o 1\nno 2\nno 3\nyes 4\nno 5\nno 6\nno 7\n"
+ (":g/yes/d" [return])
+ "no 1\nno 2\nno 3\n[n]o 5\nno 6\nno 7\n"))
+ (ert-info ("global delete, specifying case sensitivty")
+ (evil-test-buffer
+ "[a]lpha bravo charlie\nalpha Bravo charlie\nalpha BRAVO charlie\nalpha delta charlie"
+ (":g/\\CBravo/d" [return])
+ "alpha bravo charlie\n[a]lpha BRAVO charlie\nalpha delta charlie"
+ (":g/\\cBravo/d" [return])
+ "alpha delta charlie"))
+ (ert-info ("global delete with arg")
+ (evil-test-buffer
+ "[n]o 1\nno 2\nno 3\nyes 4\nno 5\nno 6\nno 7\n"
+ (":g/yes/d2" [return])
+ "no 1\nno 2\nno 3\n[n]o 6\nno 7\n"))
+ (ert-info ("global delete with range")
+ (evil-test-buffer
+ "alpha\nbravo\ncharlie\ndelta\ncharlie\necho\ngolf\ncharlie\nhotel"
+ (":g/charlie/-1d")
+ "alpha\ncharlie\ncharlie\necho\ncharlie\nhotel"))
+ (ert-info ("global substitute")
+ (evil-test-buffer
+ "[n]o 1\nno 2\nno 3\nyes 4\nno 5\nno 6\nno 7\n"
+ (":g/no/s/[3-6]/x" [return])
+ "no 1\nno 2\nno x\nyes 4\nno x\nno x\n[n]o 7\n"
+ ("u")
+ "no 1\nno 2\nno [3]\nyes 4\nno 5\nno 6\nno 7\n"))
+ (ert-info ("global substitute with trailing slash")
+ (evil-test-buffer
+ "[n]o 1\nno 2\nno 3\nyes 4\nno 5\nno 6\nno 7\n"
+ (":g/no/s/[3-6]/x/" [return])
+ "no 1\nno 2\nno x\nyes 4\nno x\nno x\n[n]o 7\n"
+ ("u")
+ "no 1\nno 2\nno [3]\nyes 4\nno 5\nno 6\nno 7\n"))
+ (evil-select-search-module 'evil-search-module 'evil-search)
+ (ert-info ("global use last match if none given, with evil-search")
+ (evil-test-buffer
+ "[n]o 1\nno 2\nno 3\nyes 4\nno 5\nno 6\nno 7\n"
+ ("/yes" [return])
+ "no 1\nno 2\nno 3\nyes 4\nno 5\nno 6\nno 7\n"
+ (":g//d" [return])
+ "no 1\nno 2\nno 3\n[n]o 5\nno 6\nno 7\n"
+ (":v//d" [return])
+ ""))
+ (evil-select-search-module 'evil-search-module 'isearch)
+ (ert-info ("global use last match if none given, with isearch")
+ (evil-test-buffer
+ "[n]o 1\nno 2\nno 3\nisearch 4\nno 5\nno 6\nno 7\n"
+ ("/isearch" [return])
+ "no 1\nno 2\nno 3\nisearch 4\nno 5\nno 6\nno 7\n"
+ (":g//d" [return])
+ "no 1\nno 2\nno 3\n[n]o 5\nno 6\nno 7\n"
+ (":v//d" [return])
+ ""))
+ (ert-info (":global should take into account evil-ex-search-case")
+ (evil-with-both-search-modules
+ (let ((evil-ex-search-case 'sensitive))
+ (evil-test-buffer
+ "this\nThis\n"
+ (":g/this/d" [return])
+ "This\n"))
+ (let ((evil-ex-search-case 'insensitive))
+ (evil-test-buffer
+ "this\nThis\n"
+ (":g/this/d" [return])
+ ""))
+ (let ((evil-ex-search-case 'smart))
+ (evil-test-buffer
+ "this\nThis\n"
+ (":g/this/d" [return])
+ "")
+ (evil-test-buffer
+ "this\nThis\n"
+ (":g/This/d" [return])
+ "this\n"))))
+ (ert-info (":global should transform vim-style regexp when appropriate")
+ (let ((evil-ex-search-vim-style-regexp t))
+ (evil-test-buffer
+ "a\n1\nb\n2\nc\n3\n"
+ (":g/\\d/>")
+ "a\n 1\nb\n 2\nc\n 3\n"))))
+
+(ert-deftest evil-test-normal ()
+ "Test `evil-ex-normal'."
+ :tags '(evil ex)
+ (let (evil-want-fine-undo)
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4\nline 5\n"
+ (":normal lxIABC" [escape] "AXYZ" [return])
+ "ABClne 1XY[Z]\nline 2\nline 3\nline 4\nline 5\n"
+ (":3,4normal lxIABC" [escape] "AXYZ" [return])
+ "ABClne 1XYZ\nline 2\nABClne 3XYZ\nABClne 4XY[Z]\nline 5\n"
+ ("u")
+ "ABClne 1XYZ\nline 2\nl[i]ne 3\nline 4\nline 5\n")))
+
+(ert-deftest evil-test-copy ()
+ :tags '(evil ex)
+ "Test `evil-copy'."
+ (ert-info ("Copy to last line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (":2,3copy$")
+ "line1\nline2\nline3\nline4\nline5\nline2\n[l]ine3\n"))
+ (ert-info ("Copy to last incomplete line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5"
+ (":2,3copy$")
+ "line1\nline2\nline3\nline4\nline5\nline2\n[l]ine3\n"))
+ (ert-info ("Copy incomplete line to last incomplete line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5"
+ (":4,5copy$")
+ "line1\nline2\nline3\nline4\nline5\nline4\n[l]ine5\n"))
+ (ert-info ("Copy to first line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (":2,3copy0")
+ "line2\n[l]ine3\nline1\nline2\nline3\nline4\nline5\n"))
+ (ert-info ("Copy to intermediate line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (":2,4copy2")
+ "line1\nline2\nline2\nline3\n[l]ine4\nline3\nline4\nline5\n"))
+ (ert-info ("Copy to current line")
+ (evil-test-buffer
+ "line1\nline2\nline3\nli[n]e4\nline5\n"
+ (":2,4copy.")
+ "line1\nline2\nline3\nline4\nline2\nline3\n[l]ine4\nline5\n")))
+
+(ert-deftest evil-test-move ()
+ :tags '(evil ex)
+ "Test `evil-move'."
+ (ert-info ("Move to last line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (":2,3move$")
+ "line1\nline4\nline5\nline2\n[l]ine3\n"))
+ (ert-info ("Move to last incomplete line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5"
+ (":2,3move$")
+ "line1\nline4\nline5\nline2\n[l]ine3\n"))
+ (ert-info ("Move incomplete line to last incomplete line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5"
+ (":4,5move$")
+ "line1\nline2\nline3\nline4\n[l]ine5\n"))
+ (ert-info ("Move to first line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (":2,3move0")
+ "line2\n[l]ine3\nline1\nline4\nline5\n"))
+ (ert-info ("Move to intermediate line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (":2,4move2")
+ "line1\nline2\nline3\n[l]ine4\nline5\n"))
+ (ert-info ("Move to other line")
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (":2,3move4")
+ "line1\nline4\nline2\n[l]ine3\nline5\n"))
+ (ert-info ("Move to current line")
+ (evil-test-buffer
+ "line1\nline2\nline3\nli[n]e4\nline5\n"
+ (":2,4move.")
+ "line1\nline2\nline3\n[l]ine4\nline5\n"))
+ (ert-info ("Move to backwards line, searching forwards (wrapping around)")
+ (evil-test-buffer
+ "
+Target
+Other line
+[S]ource
+"
+ (":move/Target/")
+ "
+Target
+[S]ource
+Other line
+"))
+ (ert-info ("Move to forwards line, searching backwards (wrapping around)")
+ (evil-test-buffer
+ "
+Target
+[O]ther line
+Source
+"
+ (":move?Source?")
+ "
+Target
+Source
+[O]ther line
+"))
+ (ert-info ("Move with global (classic line reversal)")
+ (evil-test-buffer
+ "5\n4\n3\n2\n1\n"
+ (":g/^/m0")
+ "1\n2\n3\n4\n5\n")
+ (ert-info ("... and visual selection")
+ (evil-test-buffer
+ "<5\n4\n3\n2\n[1]>\n"
+ (":g/^/m0")
+ "1\n2\n3\n4\n5\n"))
+ (ert-info ("... and no last blank line")
+ (evil-test-buffer
+ "5\n4\n3\n2\n1"
+ (":g/^/m0")
+ "1\n2\n3\n4\n5"))))
+
+(ert-deftest evil-test-write ()
+ :tags '(evil ex)
+ "Test `evil-write'."
+ (ert-info ("Write open file")
+ (evil-with-temp-file filename "line1\nline2\nline3\n"
+ (evil-test-buffer
+ ((vconcat ":e " filename [return]))
+ "[l]ine1\nline2\nline3\n"
+ ("Galine4\nline5\n" [escape])
+ "line1\nline2\nline3\nline4\nline5\n"
+ (":w")
+ (file filename "line1\nline2\nline3\nline4\nline5\n"))))
+ (ert-info ("Write current buffer to new file")
+ (let ((filename (make-temp-file "evil-test-write")))
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (delete-file filename)
+ ((vconcat ":w " filename [return]))
+ (file filename "line1\nline2\nline3\nline4\nline5\n")
+ (delete-file filename))))
+ (ert-info ("Write part of a buffer")
+ (let ((filename (make-temp-file "evil-test-write")))
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (delete-file filename)
+ ((vconcat ":2,3w " filename [return]))
+ (file filename "line2\nline3\n")
+ (delete-file filename))))
+ (ert-info ("Appending a file")
+ (let ((filename (make-temp-file "evil-test-write")))
+ (evil-test-buffer
+ "[l]ine1\nline2\nline3\nline4\nline5\n"
+ (delete-file filename)
+ ((vconcat ":4w " filename [return]))
+ (file filename "line4\n")
+ ((vconcat ":1,2w >>" filename [return]))
+ (file filename "line4\nline1\nline2\n")
+ ((vconcat ":w >> " filename [return]))
+ (file filename
+ "line4\nline1\nline2\nline1\nline2\nline3\nline4\nline5\n")
+ (delete-file filename)))))
+
+(ert-deftest evil-test-ex-sort ()
+ :tags '(evil ex)
+ "Text Ex command \":sort\" (`evil-ex-sort')."
+ (ert-info ("Plain sort")
+ (evil-test-buffer
+ "[z]zyy\ntest\ntEst\ntesT\nTEST\ntest\n"
+ (":sort")
+ "[T]EST\ntEst\ntesT\ntest\ntest\nzzyy\n"))
+ (ert-info ("Reverse sort")
+ (evil-test-buffer
+ "[z]zyy\ntest\ntEst\ntesT\nTEST\ntest\n"
+ (":sort!")
+ "[z]zyy\ntest\ntest\ntesT\ntEst\nTEST\n"))
+ (ert-info ("case insensitive")
+ (evil-test-buffer
+ "[z]zyy\ntest\ntEst\ntesT\nTEST\ntest\n"
+ (":sort i")
+ "[t]est\ntEst\ntesT\nTEST\ntest\nzzyy\n"))
+ (ert-info ("unique")
+ (evil-test-buffer
+ "[z]zyy\ntest\ntEst\ntesT\nTEST\ntest\n"
+ (":sort u")
+ "[T]EST\ntEst\ntesT\ntest\nzzyy\n"))
+ (ert-info ("case insensitive and unique")
+ (evil-test-buffer
+ "[z]zyy\ntest\ntEst\ntesT\nTEST\ntest\n"
+ (":sort iu")
+ "[t]est\nzzyy\n"))
+ (ert-info ("pattern sort")
+ (evil-test-buffer
+ "[t]e|z|t\nzz|a|y\n"
+ (":sort /|[a-z]|/ r")
+ ("zz|a|y\nte|z|t\n"))
+ (evil-test-buffer
+ "[a],b\nb,a\n"
+ (":sort /[^,]*,/")
+ "b,a\na,b\n")
+ (evil-test-buffer
+ "[a],b\nb,a\n"
+ ("/," [return] ":sort //")
+ "b,a\na,b\n"))
+ (ert-info ("numeric sort")
+ (ert-info ("decimal")
+ (evil-test-buffer
+ "27\n027\n2\na\n1\n"
+ (":sort n")
+ "a\n1\n2\n27\n027\n"))
+ (ert-info ("octal")
+ (evil-test-buffer
+ "9\n8\n"
+ (":sort o")
+ "9\n8\n")
+ (evil-test-buffer
+ "777\n776\n7239\n"
+ (":sort o")
+ "7239\n776\n777\n"))
+ (ert-info ("hexadecimal")
+ (evil-test-buffer
+ "0xae\n0xb\nae\nad\n"
+ (":sort x")
+ "0xb\nad\n0xae\nae\n"))))
+
+;;; Command line window
+
+(ert-deftest evil-test-command-window-ex ()
+ "Test command line window for Ex commands."
+ (let ((evil-ex-history (list "s/foo/baz" "s/foo/bar")))
+ (evil-test-buffer "[b]ar baz foo"
+ ("q:")
+ "s/foo/bar\ns/foo/baz\n[]\n"
+ ("kk:s/bar/quz" [return])
+ "[s]/foo/quz\ns/foo/baz\n"
+ ("fzrx" [return])
+ "[b]ar baz qux"
+ (should (equal (car evil-ex-history) "s/foo/qux")))))
+
+(ert-deftest evil-test-command-window-noop ()
+ "Test that executing a blank command does nothing."
+ (evil-test-buffer "[f]oo foo foo"
+ ("q:")
+ "[]\n"
+ ([return])
+ "[f]oo foo foo"))
+
+(ert-deftest evil-test-command-window-search-history ()
+ "Test command window with forward and backward search history."
+ (let ((evil-search-module 'isearch)
+ (evil-search-forward-history (list "four" "three" "qux"))
+ (evil-search-backward-history (list "baz" "bar")))
+ (evil-test-buffer "foo bar [b]az qux one two three four"
+ ("q/")
+ "qux\nthree\nfour\n[]\n"
+ ("k" [return])
+ "foo bar baz qux one two three [f]our"
+ ("0N")
+ "foo bar baz qux one two three [f]our"
+ ("q?")
+ "bar\nbaz\n[]\n"
+ ("k$rr" [return])
+ "foo [b]ar baz qux one two three four"
+ (error 'user-error "q/iNOT THERE" [return])
+ "foo [b]ar baz qux one two three four")))
+
+(ert-deftest evil-test-command-window-search-word ()
+ "Test command window history when searching for word under cursor."
+ (let ((evil-search-module 'isearch))
+ (evil-test-buffer
+ "[f]oo bar foo bar foo"
+ ("**")
+ "foo bar foo bar [f]oo"
+ ("B#")
+ "foo [b]ar foo bar foo"
+ ("q/k" [return])
+ "foo bar [f]oo bar foo"
+ ("q?k" [return])
+ "foo [b]ar foo bar foo")))
+
+;;; Window motions
+
+(ert-deftest evil-test-window-next-and-prev-respect-window-parameters ()
+ "Test that `evil-window-next' and `evil-window-prev' respect window parameters.
+E.g. they do not move to windows that have the `no-other-window'
+parameter set."
+ (save-window-excursion
+ ;; Make sure there is a single original window and open a second
+ ;; other window with `no-other-window' set.
+ (delete-other-windows)
+ (let* ((this-window (selected-window))
+ (other-window (split-window)))
+ (set-window-parameter other-window 'no-other-window t)
+ ;; `evil-window-next'/`evil-window-prev' should not switch to
+ ;; the window with `no-other-window' parameter set.
+ (evil-window-next nil)
+ (should (eq (selected-window) this-window))
+ (evil-window-prev nil)
+ (should (eq (selected-window) this-window)))))
+
+;;; Utilities
+
+(ert-deftest evil-test-parser ()
+ "Test `evil-parser'"
+ (with-temp-buffer
+ (cl-flet
+ ((parse
+ (s &rest args)
+ (erase-buffer)
+ (insert s)
+ (goto-char (point-min))
+ (apply
+ (evil-parser
+ '((number "[0-9]+" #'string-to-number)
+ (plus "\\+" #'intern)
+ (minus "-" #'intern)
+ (operator
+ plus
+ minus)
+ (sign (\? operator))
+ (signed-number (sign number))
+ (expr
+ ("foo" (& "bar"))
+ ("xxx" (! "yyy"))
+ (number operator number))
+ (epsilon nil))
+ expr operator plus signed-number number epsilon)
+ args)))
+ (ert-info ("Nothing")
+ (should (equal (parse "1+2" 'epsilon) '(nil))))
+ (ert-info ("Symbols")
+ (should (equal (parse "+" 'plus) '((intern "+"))))
+ (should (equal (parse "+" 'operator) '((intern "+")))))
+ (ert-info ("Leading whitespace")
+ (should (equal (parse " 1" 'number) '((string-to-number "1")))))
+ (ert-info ("Syntax tree")
+ (should (equal (parse "1" 'signed-number t)
+ '((signed-number (sign . 1) (number . 2))))))
+ (ert-info ("Lookahead")
+ (should (equal (parse "foobar" 'expr) '((list "foo"))))
+ (should (null (parse "foobaz" 'expr)))
+ (should (null (parse "xxxyyy" 'expr)))
+ (should (equal (parse "xxxzzz" 'expr) '((list "xxx")))))
+ (ert-info ("Semantic actions")
+ (should (equal (parse "1+1" 'expr)
+ '((list
+ (string-to-number "1")
+ (intern "+")
+ (string-to-number "1")))))))))
+
+(ert-deftest evil-test-delimited-arguments ()
+ "Test `evil-delimited-arguments'"
+ :tags '(evil util)
+ (ert-info ("Any number of arguments")
+ (should (equal (evil-delimited-arguments "/a/b/c/")
+ '("a" "b" "c")))
+ (should (equal (evil-delimited-arguments "/a/b/c")
+ '("a" "b" "c")))
+ (should (equal (evil-delimited-arguments "/a/b//")
+ '("a" "b" "")))
+ (should (equal (evil-delimited-arguments "/a///")
+ '("a" "" "")))
+ (should (equal (evil-delimited-arguments "/a/ ")
+ '("a" " ")))
+ (should (equal (evil-delimited-arguments "/a/")
+ '("a")))
+ (should (equal (evil-delimited-arguments "//b//")
+ '("" "b" "")))
+ (should (equal (evil-delimited-arguments "/a//c")
+ '("a" "" "c")))
+ (should (equal (evil-delimited-arguments "////")
+ '("" "" "")))
+ (should (equal (evil-delimited-arguments "/")
+ nil))
+ (should (equal (evil-delimited-arguments " ")
+ nil))
+ (should (equal (evil-delimited-arguments "")
+ nil)))
+ (ert-info ("Two arguments")
+ (should (equal (evil-delimited-arguments "/a/b/c" 2)
+ '("a" "b/c")))
+ (should (equal (evil-delimited-arguments "/a/b/" 2)
+ '("a" "b")))
+ (should (equal (evil-delimited-arguments "/a/b" 2)
+ '("a" "b")))
+ (should (equal (evil-delimited-arguments "/a//" 2)
+ '("a" "")))
+ (should (equal (evil-delimited-arguments "/a/ " 2)
+ '("a" " ")))
+ (should (equal (evil-delimited-arguments "/a/" 2)
+ '("a" nil)))
+ (should (equal (evil-delimited-arguments "/a" 2)
+ '("a" nil)))
+ (should (equal (evil-delimited-arguments " " 2)
+ '(nil nil)))
+ (should (equal (evil-delimited-arguments "" 2)
+ '(nil nil))))
+ (ert-info ("One argument")
+ (should (equal (evil-delimited-arguments "/a/b/c" 1)
+ '("a/b/c")))
+ (should (equal (evil-delimited-arguments "/a/ " 1)
+ '("a")))
+ (should (equal (evil-delimited-arguments "/a/" 1)
+ '("a")))
+ (should (equal (evil-delimited-arguments "/a" 1)
+ '("a")))
+ (should (equal (evil-delimited-arguments "/" 1)
+ '(nil)))
+ (should (equal (evil-delimited-arguments " " 1)
+ '(nil)))
+ (should (equal (evil-delimited-arguments "" 1)
+ '(nil))))
+ (ert-info ("Zero arguments")
+ (should (equal (evil-delimited-arguments "/a" 0)
+ nil))
+ (should (equal (evil-delimited-arguments "/" 0)
+ nil))
+ (should (equal (evil-delimited-arguments " " 0)
+ nil))
+ (should (equal (evil-delimited-arguments "" 0)
+ nil))))
+
+(ert-deftest evil-test-concat-charsets ()
+ "Test `evil-concat-charsets'"
+ :tags '(evil util)
+ (ert-info ("Bracket")
+ (should (equal (evil-concat-charsets "abc" "]def")
+ "]abcdef")))
+ (ert-info ("Complement")
+ (should (equal (evil-concat-charsets "^abc" "def")
+ "^abcdef"))
+ (should (equal (evil-concat-charsets "^abc" "^def")
+ "^abcdef")))
+ (ert-info ("Hyphen")
+ (should (equal (evil-concat-charsets "abc" "-def")
+ "-abcdef"))
+ (should (equal (evil-concat-charsets "^abc" "-def")
+ "^-abcdef")))
+ (ert-info ("Newline")
+ (should (equal (evil-concat-charsets "^ \t\r\n" "[:word:]_")
+ "^ \t\r\n[:word:]_"))))
+
+(ert-deftest evil-test-properties ()
+ "Test `evil-get-property' and `evil-put-property'"
+ :tags '(evil util)
+ (defvar evil--alist)
+ (let (evil--alist)
+ (ert-info ("Set properties")
+ (evil-put-property 'evil--alist 'wibble :foo t)
+ (should (equal evil--alist '((wibble . (:foo t)))))
+ (evil-put-property 'evil--alist 'wibble :bar nil)
+ (should (equal evil--alist '((wibble . (:foo t :bar nil)))))
+ (evil-put-property 'evil--alist 'wobble :foo nil :bar nil :baz t)
+ (should (equal evil--alist '((wobble . (:foo nil :bar nil :baz t))
+ (wibble . (:foo t :bar nil))))))
+ (ert-info ("Get properties")
+ (should (evil-get-property evil--alist 'wibble :foo))
+ (should-not (evil-get-property evil--alist 'wibble :bar))
+ (should-not (evil-get-property evil--alist 'wobble :foo))
+ (should-not (evil-get-property evil--alist 'wibble :baz))
+ (should (equal (evil-get-property evil--alist t :foo)
+ '((wibble . t) (wobble . nil))))
+ (should (equal (evil-get-property evil--alist t :bar)
+ '((wibble . nil) (wobble . nil))))
+ (should (equal (evil-get-property evil--alist t :baz)
+ '((wobble . t)))))))
+
+(ert-deftest evil-test-filter-list ()
+ "Test `evil-filter-list'"
+ :tags '(evil util)
+ (ert-info ("Return filtered list")
+ (should (null (evil-filter-list #'null '(nil))))
+ (should (equal (evil-filter-list #'null '(nil 1)) '(1)))
+ (should (equal (evil-filter-list #'null '(nil 1 2 nil)) '(1 2)))
+ (should (equal (evil-filter-list #'null '(nil nil 1)) '(1)))
+ (should (equal (evil-filter-list #'null '(nil 1 nil 2 nil 3))
+ '(1 2 3))))
+ (ert-info ("Remove matches by side-effect when possible")
+ (let (list)
+ (setq list '(1 nil))
+ (evil-filter-list #'null list)
+ (should (equal list '(1)))
+
+ (setq list '(1 nil nil))
+ (evil-filter-list #'null list)
+ (should (equal list '(1)))
+
+ (setq list '(1 nil nil 2))
+ (evil-filter-list #'null list)
+ (should (equal list '(1 2)))
+
+ (setq list '(1 nil 2 nil 3))
+ (evil-filter-list #'null list)
+ (should (equal list '(1 2 3))))))
+
+(ert-deftest evil-test-concat-lists ()
+ "Test `evil-concat-lists' and `evil-concat-alists'"
+ :tags '(evil util)
+ (ert-info ("Remove duplicates across lists")
+ (should (equal (evil-concat-lists
+ nil '(a b) '(b c))
+ '(a b c))))
+ (ert-info ("Remove duplicates inside lists")
+ (should (equal (evil-concat-lists
+ '(a a b) nil '(b c) nil)
+ '(a b c))))
+ (ert-info ("Remove duplicate associations")
+ (should (equal (evil-concat-alists
+ '((a . b)) '((a . c)))
+ '((a . c))))
+ (should-not (equal (evil-concat-lists
+ '((a . b)) '((a . c)))
+ '((a . b))))))
+
+(ert-deftest evil-test-sort ()
+ "Test `evil-sort'."
+ :tags '(evil util)
+ (ert-info ("Two elements")
+ (let ((a 2) (b 1))
+ (evil-sort a b)
+ (should (= a 1))
+ (should (= b 2))))
+ (ert-info ("Three elements")
+ (let ((a 3) (b 1) (c 2))
+ (evil-sort a b c)
+ (should (= a 1))
+ (should (= b 2))
+ (should (= c 3))))
+ (ert-info ("Four elements")
+ (let ((a 4) (b 3) (c 2) (d 1))
+ (evil-sort a b c d)
+ (should (= a 1))
+ (should (= b 2))
+ (should (= c 3))
+ (should (= d 4)))))
+
+(ert-deftest evil-test-read-key ()
+ "Test `evil-read-key'"
+ :tags '(evil util)
+ (let ((unread-command-events '(?A)))
+ (ert-info ("Prevent downcasing in `this-command-keys'")
+ (should (eq (evil-read-key) ?A))
+ (should (equal (this-command-keys) "A")))))
+
+(ert-deftest evil-test-extract-count ()
+ "Test `evil-extract-count'"
+ :tags '(evil util)
+ (evil-test-buffer
+ (ert-info ("Exact without count")
+ (should (equal (evil-extract-count "x")
+ (list nil 'evil-delete-char "x" nil)))
+ (should (equal (evil-extract-count "g0")
+ (list nil 'evil-beginning-of-visual-line "g0" nil))))
+
+ (ert-info ("Exact with count")
+ (should (equal (evil-extract-count "420x")
+ (list 420 'evil-delete-char "x" nil)))
+ (should (equal (evil-extract-count (vconcat "420" [M-right]))
+ (list 420 (key-binding [M-right]) (vconcat [M-right]) nil)))
+ (should (equal (evil-extract-count "2301g0")
+ (list 2301 'evil-beginning-of-visual-line "g0" nil))))
+
+ (ert-info ("Extra elements without count")
+ (should (equal (evil-extract-count "xAB")
+ (list nil 'evil-delete-char "x" "AB")))
+ (should (equal (evil-extract-count "g0CD")
+ (list nil 'evil-beginning-of-visual-line "g0" "CD"))))
+
+ (ert-info ("Extra elements with count")
+ (should (equal (evil-extract-count "420xAB")
+ (list 420 'evil-delete-char "x" "AB")))
+ (should (equal (evil-extract-count "2301g0CD")
+ (list 2301 'evil-beginning-of-visual-line "g0" "CD"))))
+
+ (ert-info ("Exact \"0\" count")
+ (should (equal (evil-extract-count "0")
+ (list nil 'evil-beginning-of-line
+ "0" nil))))
+
+ (ert-info ("Extra elements and \"0\"")
+ (should (equal (evil-extract-count "0XY")
+ (list nil 'evil-beginning-of-line
+ "0" "XY"))))
+
+ (ert-info ("Count only")
+ (should-error (evil-extract-count "1230")))
+
+ (ert-info ("Unknown command")
+ (should-error (evil-extract-count "°"))
+ (should-error (evil-extract-count "12°")))))
+
+(ert-deftest evil-transform-vim-style-regexp ()
+ "Test `evil-transform-vim-style-regexp'"
+ (dolist (repl '((?s . "[[:space:]]")
+ (?S . "[^[:space:]]")
+ (?d . "[[:digit:]]")
+ (?D . "[^[:digit:]]")
+ (?x . "[[:xdigit:]]")
+ (?X . "[^[:xdigit:]]")
+ (?o . "[0-7]")
+ (?O . "[^0-7]")
+ (?a . "[[:alpha:]]")
+ (?A . "[^[:alpha:]]")
+ (?l . "[a-z]")
+ (?L . "[^a-z]")
+ (?u . "[A-Z]")
+ (?U . "[^A-Z]")
+ (?y . "\\s")
+ (?Y . "\\S")
+ (?w . "\\w")
+ (?W . "\\W")))
+ (ert-info ((format "Test transform from '\\%c' to '%s'"
+ (car repl) (cdr repl)))
+ (should (equal (evil-transform-vim-style-regexp
+ (concat "xxx\\"
+ (char-to-string (car repl))
+ "\\"
+ (char-to-string (car repl))
+ "\\\\"
+ (char-to-string (car repl))
+ "\\\\\\"
+ (char-to-string (car repl))
+ "yyy"))
+ (concat "xxx"
+ (cdr repl)
+ (cdr repl)
+ "\\\\"
+ (char-to-string (car repl))
+ "\\\\"
+ (cdr repl)
+ "yyy"))))))
+
+;;; Advice
+
+(ert-deftest evil-test-eval-last-sexp ()
+ "Test advised `evil-last-sexp'"
+ :tags '(evil advice)
+ (ert-info ("Normal state")
+ (evil-test-buffer
+ "(+ 1 (+ 2 3[)])"
+ ("1" (kbd "C-x C-e"))
+ "(+ 1 (+ 2 35[)])"))
+ (ert-info ("Insert state")
+ (evil-test-buffer
+ "(+ 1 (+ 2 3[)])"
+ ("i" (kbd "C-u") (kbd "C-x C-e") [escape])
+ "(+ 1 (+ 2 3[3]))"))
+ (ert-info ("Emacs state")
+ (evil-test-buffer
+ "(+ 1 (+ 2 3[)])"
+ ((kbd "C-z") (kbd "C-u") (kbd "C-x C-e"))
+ "(+ 1 (+ 2 33[)])")))
+
+;;; ESC
+
+(ert-deftest evil-test-esc-count ()
+ "Test if prefix-argument is transferred for key sequences with meta-key"
+ :tags '(evil esc)
+ (unless noninteractive
+ (ert-info ("Test M-<right>")
+ (evil-test-buffer
+ "[A]BC DEF GHI JKL MNO"
+ ("3" (kbd "ESC <right>"))
+ "ABC DEF GHI[ ]JKL MNO"))
+ (ert-info ("Test shell-command")
+ (evil-test-buffer
+ "[A]BC DEF GHI JKL MNO"
+ ("1" (kbd "ESC !") "echo TEST" [return])
+ "[T]EST\nABC DEF GHI JKL MNO"))))
+
+(when (or evil-tests-profiler evil-tests-run)
+ (evil-tests-initialize))
+
+(ert-deftest evil-test-black-hole-register ()
+ :tags '(evil)
+ (ert-info ("Test \"_ on delete word")
+ (evil-test-buffer
+ "[E]vil evil is awesome."
+ ("dw\"_dwP")
+ "Evil[ ]is awesome."))
+ (ert-info ("Test \"_ on delete line")
+ (evil-test-buffer
+ "[T]his line is a keeper!\nThis line is not."
+ ("dd\"_ddP")
+ "[T]his line is a keeper!"))
+ (ert-info ("Test \"_ on delete region")
+ (evil-test-buffer
+ "<This region is a keeper>!\nThis line is not."
+ ("d\gg\"_dGP")
+ "This region is a keepe[r]")))
+
+(ert-deftest evil-test-pasteable-macros ()
+ "Test if we can yank and paste macros containing
+ <escape>"
+ :tags '(evil)
+ (ert-info ("Execute yanked macro")
+ (evil-test-buffer
+ "[i]foo\e"
+ ("\"qD@q\"qp"
+ "fooifoo\e")))
+ (ert-info ("Paste recorded marco")
+ (evil-test-buffer
+ (evil-set-register ?q (vconcat "ifoo" [escape]))
+ ("@q\"qp")
+ "fooifoo\e")))
+
+(ert-deftest evil-test-forward-symbol ()
+ :tags '(evil)
+ (ert-info ("Test symbol deletion")
+ (evil-test-buffer
+ "(test [t]his (hello there) with dao)"
+ ("dao")
+ "(test [(]hello there) with dao)"))
+ (ert-info ("Test symbol motion")
+ (evil-test-buffer
+ "(test[ ](hello there) with dao)"
+ (should (eq 0 (forward-evil-symbol 1)))
+ "(test ([h]ello there) with dao)"
+ (should (eq 0 (forward-evil-symbol 1)))
+ "(test (hello[ ]there) with dao)"))
+ (ert-info ("Test dio on whitespace")
+ (evil-test-buffer
+ "(test[ ]dio with whitespace)"
+ ("dio")
+ "(test[d]io with whitespace)"))
+ (ert-info ("Test dao/dio with empty lines")
+ (evil-test-buffer
+ "there are two lines in this file\n[\n]and some whitespace between them"
+ ("dao")
+ "there are two lines in this file\n[a]nd some whitespace between them")
+ (evil-test-buffer
+ "here are another two lines\n[\n]with a blank line between them"
+ ("dio")
+ "here are another two lines\n[w]ith a blank line between them"))
+ (ert-info ("Test dao/dio with empty lines and punctuation")
+ (evil-test-buffer
+ "These two lines \n[\n]!have punctuation on them"
+ ("dao")
+ "These two lines \n[!]have punctuation on them")))
+
+(ert-deftest evil-test-jump ()
+ :tags '(evil jumps)
+ (let ((evil--jumps-buffer-targets "\\*\\(new\\|scratch\\|test\\)\\*"))
+ (ert-info ("Test jumping backward and forward in a single buffer")
+ (evil-test-buffer
+ "[z] z z z z z z z z z"
+ ("/z" [return])
+ "z [z] z z z z z z z z"
+ ("nnnn")
+ "z z z z z [z] z z z z"
+ ("\C-o")
+ "z z z z [z] z z z z z"
+ ("\C-o")
+ "z z z [z] z z z z z z"
+ ("\C-i\C-i")
+ "z z z z z [z] z z z z"))
+ (ert-info ("Test jumping backward and forward with counts")
+ (evil-test-buffer
+ "[z] z z z z z z z z z"
+ ("/z" [return] "nnnn")
+ "z z z z z [z] z z z z"
+ ("3\C-o")
+ "z z [z] z z z z z z z"
+ ("2\C-i")
+ "z z z z [z] z z z z z"
+ ))
+ (ert-info ("Jump list branches off when new jump is set")
+ (evil-test-buffer
+ "[z] z z z z z z z"
+ ("/z" [return] "nnnn4\C-o") ;; adds a bunch of jumps after the 2nd z
+ "z [z] z z z z z z"
+ ("/z" [return]) ;; sets a new jump, list should be reset
+ "z z [z] z z z z z"
+ ("\C-o")
+ "z [z] z z z z z z"
+ ("3\C-i") ;; even after jumping forward 3 times it can't get past the 3rd z
+ "z z [z] z z z z z"))
+ (ert-info ("Jump across files")
+ (let ((temp-file (make-temp-file "evil-test-")))
+ (unwind-protect
+ (evil-test-buffer
+ "[z] z z z z z z"
+ ("\M-x" "find-file" [return] temp-file [return] "inew buffer" [escape])
+ "new buffe[r]"
+ ("\C-o")
+ "[z] z z z z z z"
+ ("\C-i")
+ "new buffe[r]")
+ (delete-file temp-file)
+ (let ((buf (file-name-nondirectory temp-file)))
+ (when (get-buffer buf)
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf))))))
+ (ert-info ("Jump multiple times between files")
+ (let ((a (make-temp-file "evil-aa-" nil nil "evil-bb\n\nthis is a"))
+ (b (make-temp-file "evil-bb-" nil nil "evil-cc\n\nthis is b"))
+ (c (make-temp-file "evil-cc-" nil nil "this is c")))
+ (unwind-protect
+ (evil-test-buffer
+ (find-file a)
+ ("gf" [return])
+ "evil-cc\n\nthis is b"
+ ("gf" [return])
+ "this is c"
+ ("\C-o" "\C-o")
+ "evil-bb\n\nthis is a"
+ ("\C-i" "\C-i")
+ "this is c")
+ (dolist (f (list a b c))
+ (let ((buf (file-name-nondirectory f)))
+ (when (get-buffer buf)
+ (with-current-buffer buf (set-buffer-modified-p nil))
+ (kill-buffer buf)))
+ (delete-file f)))))))
+
+(ert-deftest evil-test-find-file ()
+ :tags '(evil jumps)
+ (when (memq system-type '(cygwin windows-nt ms-dos))
+ (ert-skip "[INFO] GitHub Actions has different userprofile name."))
+ (ert-info ("Find file at point (normal state)")
+ (evil-with-temp-file file-name ""
+ (evil-test-buffer
+ (vconcat "i" file-name [escape])
+ (should-not (equal file-name (buffer-file-name)))
+ ("gf")
+ (should (equal file-name (buffer-file-name))))))
+ (ert-info ("Find file at point (visual state)")
+ (evil-with-temp-file file-name ""
+ (evil-test-buffer
+ (vconcat "iuser@localhost:" file-name "$" [escape])
+ (should-not (equal file-name (buffer-file-name)))
+ ("0f:lvt$gf")
+ (should (equal file-name (buffer-file-name))))))
+ (ert-info ("Find file at point with line number")
+ (let* ((line-number 3)
+ (file-content (make-string (* 2 line-number) ?\n)))
+ (evil-with-temp-file file-name (insert file-content)
+ (evil-test-buffer
+ (vconcat "i" file-name (format ":%d" line-number) [escape])
+ (should (and (not (equal file-name (buffer-file-name)))
+ (not (equal line-number (line-number-at-pos)))))
+ ("gF")
+ (should (and (equal file-name (buffer-file-name))
+ (equal line-number (line-number-at-pos))))))))
+ (ert-info ("Find file at point with line and column numbers")
+ (let* ((line-number 3)
+ (column-number 5)
+ (file-content (mapconcat #'identity
+ (make-list (* 2 line-number)
+ (make-string (* 2 column-number) ?\s))
+ "\n")))
+ (evil-with-temp-file file-name (insert file-content)
+ (evil-test-buffer
+ (vconcat "i" file-name (format ":%d:%d" line-number column-number) [escape])
+ (should (and (not (equal file-name (buffer-file-name)))
+ (not (equal line-number (line-number-at-pos)))
+ (not (equal column-number (current-column)))))
+ ("gF")
+ (should (and (equal file-name (buffer-file-name))
+ (equal line-number (line-number-at-pos))
+ (equal column-number (1+ (current-column))))))))))
+
+(ert-deftest evil-test-jump-buffers ()
+ :tags '(evil jumps)
+ (skip-unless nil)
+ (ert-info ("Test jumping backward and forward across buffers")
+ (evil-test-buffer
+ "[z] z z z z z z z z z"
+ (":new" [return] "inew buffer" [escape])
+ "new buffe[r]"
+ ("\C-o")
+ "[z] z z z z z z z z z"
+ ("\C-i")
+ "new buffe[r]")))
+
+(ert-deftest evil-test-abbrev-expand ()
+ :tags '(evil abbrev)
+ (ert-info ("Test abbrev expansion on insert state exit")
+ (define-abbrev-table 'global-abbrev-table
+ '(("undef" "undefined"))) ; add global abbrev
+ (evil-test-buffer
+ "foo unde[f] bar"
+ (abbrev-mode)
+ ("a" [escape])
+ "foo undefine[d] bar") ; 'undef' should be expanded
+ (evil-test-buffer
+ "foo unde[f] bar"
+ ("a" [escape])
+ "foo unde[f] bar") ; 'undef' shouldn't be expanded,
+ ; abbrev-mode is not enabled
+ (evil-test-buffer
+ "fo[o] undef bar"
+ (abbrev-mode)
+ ("a" [escape])
+ "fo[o] undef bar") ; 'foo' shouldn't be expanded,
+ ; it's not an abbrev
+ (kill-all-abbrevs) ; remove all abbrevs
+ (evil-test-buffer
+ "foo unde[f] bar"
+ (abbrev-mode)
+ ("a" [escape])
+ "foo unde[f] bar") ; 'undef' shouldn't be expanded,
+ ; it's not an abbrev
+ (setq abbrevs-changed nil)))
+
+(ert-deftest evil-test-text-object-macro ()
+ :tags '(evil abbrev)
+ (ert-info ("Test pipe character and other delimiters as object delimiters")
+ ;; This is the macro that broke after pull #747.
+ (defmacro evil-test-define-and-bind-text-object (name key start-regex end-regex)
+ (let ((inner-name (make-symbol (concat "evil-inner-" name)))
+ (outer-name (make-symbol (concat "evil-a-" name))))
+ `(progn
+ (evil-define-text-object ,inner-name (count &optional beg end _type)
+ (evil-select-paren ,start-regex ,end-regex beg end type count nil))
+ (evil-define-text-object ,outer-name (count &optional beg end _type)
+ (evil-select-paren ,start-regex ,end-regex beg end type count t))
+ (define-key evil-inner-text-objects-map ,key #',inner-name)
+ (define-key evil-outer-text-objects-map ,key #',outer-name))))
+ (evil-test-define-and-bind-text-object "pipe" "|" "|" "|")
+ (evil-test-define-and-bind-text-object "rackety" "#" "#|" "|#")
+
+ (evil-test-buffer
+ "#|this i[s] a test #|with rackety|# multiline
+ and nestable comments|#"
+ ("vi#")
+ "#|<this is a test #|with rackety|# multiline
+ and nestable comments>|#")
+ (evil-test-buffer
+ "| foo | aoe[u] | bar |"
+ ("vi|")
+ "| foo |< aoeu >| bar |"
+ ("a|")
+ "| foo <| aoeu |> bar |"
+ ("a|")
+ "<| foo | aoeu | bar |>")
+ (evil-test-buffer
+ "| foo | aoe[u] | bar |"
+ ("ci|testing" [escape])
+ "| foo |testing| bar |")))
+
+(ert-deftest evil-test-kbd-macro ()
+ "Test recording and replaying of macros."
+ :tags '(evil kbd-macro)
+ (ert-info ("Execute macro an infinite number of times")
+ (evil-test-buffer "xxx"
+ (evil-set-register ?q "ryl")
+ (error 'end-of-line "\C-u@q")
+ "yyy")))
+
+(ert-deftest evil-test-undo-kbd-macro ()
+ "Test if evil can undo the changes made by a keyboard macro
+when an error stops the execution of the macro"
+ :tags '(evil undo kbd-macro)
+ (ert-info ("When kbd-macro goes to the end of buffer")
+ (evil-test-buffer
+ "[l]ine 1\nline 2\nline 3\nline 4"
+ (evil-set-register ?q "jdd")
+ ("jdd")
+ (should-error (execute-kbd-macro "2@q"))
+ ("uu")
+ "line 1\n[l]ine 2\nline 3\nline 4"))
+ (ert-info ("When kbd-macro goes to the end of line")
+ (evil-test-buffer
+ "[f]ofof"
+ (evil-set-register ?q "lx")
+ ("lx")
+ (should-error (execute-kbd-macro "2@q"))
+ ("uu")
+ "f[o]fof"))
+ (ert-info ("When kbd-macro goes to the beginning of buffer")
+ (evil-test-buffer
+ "line 1\nline 2\n[l]ine 3"
+ (evil-set-register ?q "kx")
+ ("kx")
+ (should-error (execute-kbd-macro "2@q"))
+ ("uu")
+ "line 1\n[l]ine 2\nline 3")))
+
+(ert-deftest evil-test-undo-jump ()
+ "Test that undo adds to the jump list."
+ :tags '(evil)
+ (let ((evil--jumps-buffer-targets "\\*\\(new\\|scratch\\|test\\)\\*"))
+ (ert-info ("Undo adds to the jump list")
+ (evil-test-buffer
+ "alpha [b]ravo charlie delta"
+ ("dw" "w")
+ "alpha charlie [d]elta"
+ ("u")
+ "alpha [b]ravo charlie delta"
+ ("``")
+ "alpha bravo charlie [d]elta"))))
+
+(ert-deftest evil-test-insert-state-undo ()
+ "Test that undo isn't lost when done from insert state."
+ :tags '(evil)
+ (skip-unless (version<= "28" emacs-version))
+ (let (evil-want-fine-undo)
+ (customize-set-variable 'evil-undo-system 'undo-redo)
+ (evil-test-buffer
+ "alpha [ ]delta"
+ (evil-define-key* 'insert 'local [f8] 'evil-undo)
+ ("icharlie" [f8] [escape])
+ "alpha[ ] delta"
+ ("\C-r")
+ "alpha [c]harlie delta")))
+
+(ert-deftest evil-test-visual-update-x-selection ()
+ "Test `evil-visual-update-x-selection'."
+ :tags '(evil)
+ (ert-info ("Buffer argument isn't a live buffer")
+ ;; create buffer in normal mode, so we don't try to actually copy anything to
+ ;; the X selection.
+ (let ((buf (evil-test-buffer-from-string "foobar")))
+ (kill-buffer buf)
+ ;; should not raise an "Selecting deleted buffer" error
+ (evil-visual-update-x-selection buf))))
+
+(ert-deftest evil-test-append-to-kbd-macro ()
+ "Test if evil can append to a keyboard macro."
+ :tags '(evil append to kbd-macro)
+ (ert-info ("When kbd-macro ends in <escape>")
+ (evil-test-buffer
+ (evil-set-register ?a (vconcat "ainserted text" [escape]))
+ (evil-set-register ?A (vconcat "a appended text" [escape]))
+ ("@a")
+ "inserted text appended tex[t]")))
+
+(ert-deftest evil-test-paren-jumping ()
+ :tags '(evil paren)
+ (ert-info ("Test doing motions on parens that you aren't in")
+ (evil-test-buffer
+ "[m]ain(argc, argv) char **argv; {"
+ ("dib" [escape])
+ "main([)] char **argv; {")
+ (evil-test-buffer
+ "[a]lpha (bravo) charlie "
+ ("yi(")
+ "alpha ([b]ravo) charlie "
+ ("$p")
+ "alpha (bravo) charlie brav[o]")
+ (evil-test-buffer
+ "[a]lpha (bravo (charlie))"
+ ("2di(")
+ "alpha (bravo ([)]")
+ (evil-test-buffer
+ :point-start "("
+ :point-end ")"
+ "(a)lpha [bravo [charlie]] [bravo]"
+ ("3di[")
+ "alpha [bravo [charlie]] [(])")
+ (evil-test-buffer
+"[#]include \"stdlib.h\"
+main(argc, argv) char **argv; {
+ while (1) malloc(0);
+}"
+ ("ci{ return 0;" [escape])
+"#include \"stdlib.h\"
+main(argc, argv) char **argv; {
+ return 0[;]
+}")))
+
+;;; Core
+
+(ert-deftest evil-test-initial-state ()
+ "Test `evil-initial-state'"
+ :tags '(evil core)
+ ;; FIXME: These have a global effect, so better move them out and give them
+ ;; a proper namespace prefix.
+ (define-derived-mode test-1-mode prog-mode "Test1")
+ (define-derived-mode test-2-mode test-1-mode "Test2")
+ (evil-set-initial-state 'test-1-mode 'insert)
+ (ert-info ("Check default state")
+ (should (eq (evil-initial-state 'prog-mode 'normal) 'normal)))
+ (ert-info ("Basic functionality 1")
+ (should (eq (evil-initial-state 'test-1-mode) 'insert)))
+ (ert-info ("Basic functionality 2")
+ (evil-test-buffer
+ "abc\ndef\n"
+ (test-1-mode)
+ (should (eq evil-state 'insert))))
+ (ert-info ("Inherit initial state from a parent")
+ (evil-test-buffer
+ "abc\ndef\n"
+ (test-2-mode)
+ (should (eq evil-state 'insert))))
+ (evil-set-initial-state 'test-1-mode nil)
+ (ert-info ("Check for inheritance loops")
+ (evil-test-buffer
+ "abc\ndef\n"
+ (unwind-protect
+ (let ((major-mode 'test-2-mode))
+ (put 'test-1-mode 'derived-mode-parent 'test-2-mode)
+ ;; avoid triggering all of the hooks here, some of which might get
+ ;; caught in loops depending on the environment. settings major-mode
+ ;; is sufficient for `evil-initial-state-for-buffer' to work.
+ (should-error (evil-initial-state-for-buffer)))
+ (put 'test-1-mode 'derived-mode-parent 'prog-mode))))
+ ;; FIXME: Same as above.
+ (defalias 'test-1-alias-mode #'test-1-mode)
+ (define-derived-mode test-3-mode test-1-alias-mode "Test3")
+ (evil-set-initial-state 'test-1-mode 'insert)
+ (ert-info ("Check inheritance from major mode aliases")
+ "abc\ndef\n"
+ (test-3-mode)
+ (should (eq evil-state 'insert))))
+
+(ert-deftest evil-test-keep-input-method ()
+ "Test that the input method is preserved when changing the major mode."
+ :tags '(evil core input-method)
+ (cl-flet ((use-german-input-method () (set-input-method "german-prefix")))
+ (unwind-protect
+ (progn
+ (add-hook 'text-mode-hook #'use-german-input-method)
+ (evil-test-buffer
+ "[]"
+ (should (null evil-input-method))
+ ("a\"a" [escape])
+ "\"[a]"
+ (text-mode)
+ (should (equal evil-input-method "german-prefix"))
+ ("a\"a" [escape])
+ "\"a[ä]"
+ (emacs-lisp-mode)
+ (should (equal evil-input-method "german-prefix"))))
+ (remove-hook 'text-mode-hook #'use-german-input-method))))
+
+(ert-deftest evil-retab ()
+ "Test the :retab command"
+ :tags '(evil)
+ (ert-info ("From tabs to spaces")
+ (evil-test-buffer
+ "def foo():\n\twhile True:\n\t\treturn\n"
+ (setq indent-tabs-mode nil)
+ (setq tab-width 4)
+ (":retab" [return])
+ "def foo():\n while True:\n return\n"))
+ (ert-info ("From spaces to tabs")
+ (evil-test-buffer
+ "def foo():\n while True:\n return\n"
+ (setq indent-tabs-mode t)
+ (setq tab-width 4)
+ (":retab" [return])
+ "def foo():\n\twhile True:\n\t\treturn\n"))
+ (ert-info ("Specify tab width as an argument")
+ (evil-test-buffer
+ "def foo():\n\twhile True:\n\t\treturn\n"
+ (setq indent-tabs-mode nil)
+ (setq tab-width 4)
+ (":retab 2" [return])
+ "def foo():\n while True:\n return\n"))
+ (ert-info ("Invalid argument")
+ (evil-test-buffer
+ "def foo():\n\twhile True:\n\t\treturn\n"
+ (should-error (execute-kbd-macro ":retab foo" [return])))))
+
+(ert-deftest evil-retab-visual ()
+ "Test the :retab command on visual line selection.
+This test fails in the batch mode (and therefore in the GitHub CI)
+but it works fine in `M-x ert-run-tests-interactively'."
+ :tags '(evil visual)
+ (skip-unless (not noninteractive))
+ (ert-info ("Retab only selected lines")
+ (evil-test-buffer
+ "def foo():\n\twhile True:\n\t\treturn\n"
+ (setq indent-tabs-mode nil)
+ (setq tab-width 4)
+ ("Vj" ":retab" [return])
+ "def foo():\n while True:\n\t\treturn\n")))
+
+(provide 'evil-tests)
+
+;;; evil-tests.el ends here
diff --git a/.config/emacs/lisp/evil/evil-types.el b/.config/emacs/lisp/evil/evil-types.el
new file mode 100644
index 0000000..360316a
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-types.el
@@ -0,0 +1,465 @@
+;;; evil-types.el --- Type system -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A type defines a transformation on a pair of buffer positions.
+;; Types are used by Visual state (character/line/block selection)
+;; and Operator-Pending state (character/line/block motions).
+;;
+;; The basic transformation is "expansion". For example, the `line'
+;; type "expands" a pair of positions to whole lines by moving the
+;; first position to the beginning of the line and the last position
+;; to the end of the line. That expanded selection is what the rest
+;; of Emacs sees and acts on.
+;;
+;; An optional transformation is "contraction", which is the opposite
+;; of expansion. If the transformation is one-to-one, expansion
+;; followed by contraction always returns the original range.
+;; (The `line' type is not one-to-one, as it may expand multiple
+;; positions to the same lines.)
+;;
+;; Another optional transformation is "normalization", which takes
+;; two unexpanded positions and adjusts them before expansion.
+;; This is useful for cleaning up "invalid" positions.
+;;
+;; Types are defined at the end of this file using the macro
+;; `evil-define-type'.
+
+(require 'evil-common)
+(require 'evil-macros)
+
+;;; Code:
+
+;;; Type definitions
+
+(evil-define-type exclusive
+ "Return the positions unchanged, with some exceptions.
+If the end position is at the beginning of a line, then:
+
+* If the beginning position is at or before the first non-blank
+ character on the line, return `line' (expanded).
+
+* Otherwise, move the end position to the end of the previous
+ line and return `inclusive' (expanded)."
+ :normalize (lambda (beg end)
+ (cond
+ ((progn
+ (goto-char end)
+ (and (/= beg end) (bolp)))
+ (setq end (max beg (1- end)))
+ (cond
+ ((progn
+ (goto-char beg)
+ (looking-back "^[ \f\t\v]*" (line-beginning-position)))
+ (evil-expand beg end 'line))
+ (t
+ (unless evil-cross-lines
+ (setq end (max beg (1- end))))
+ (evil-expand beg end 'inclusive))))
+ (t
+ (evil-range beg end))))
+ :string (lambda (beg end)
+ (let ((width (- end beg)))
+ (format "%s character%s" width
+ (if (= width 1) "" "s")))))
+
+(evil-define-type inclusive
+ "Include the character under point.
+Handling for `evil-want-visual-char-semi-exclusive' is deprecated,
+and will be removed in a future version."
+ :expand (lambda (beg end)
+ (if (and (with-no-warnings evil-want-visual-char-semi-exclusive)
+ (evil-visual-state-p)
+ (< beg end)
+ (save-excursion
+ (goto-char end)
+ (or (bolp) (eolp))))
+ (evil-range beg end 'exclusive)
+ (evil-range beg (1+ end))))
+ :contract (lambda (beg end)
+ (evil-range beg (max beg (1- end))))
+ :normalize (lambda (beg end)
+ (evil-range beg (if (eq (char-after end) ?\n)
+ (max beg (1- end)) end)))
+ :string (lambda (beg end)
+ (let ((width (- end beg)))
+ (format "%s character%s" width
+ (if (= width 1) "" "s")))))
+
+(evil-define-type line
+ "Include whole lines."
+ :one-to-one nil
+ :expand (lambda (beg end)
+ (evil-range
+ (progn
+ (goto-char beg)
+ ;; move to beginning of line as displayed
+ (evil-move-beginning-of-line)
+ (point))
+ (progn
+ (goto-char end)
+ ;; move to the end of line as displayed
+ (evil-move-end-of-line)
+ (line-beginning-position 2))))
+ :contract (lambda (beg end)
+ (evil-range beg (max beg (1- end))))
+ :string (lambda (beg end)
+ (let ((height (count-lines beg end)))
+ (format "%s line%s" height
+ (if (= height 1) "" "s")))))
+
+(evil-define-type screen-line
+ "Include whole lines, being aware of `visual-line-mode'
+when `evil-respect-visual-line-mode' is non-nil."
+ :one-to-one nil
+ :expand (lambda (beg end)
+ (if (not (and evil-respect-visual-line-mode visual-line-mode))
+ (evil-line-expand beg end)
+ (evil-range
+ (progn
+ (goto-char beg)
+ (save-excursion
+ (beginning-of-visual-line)))
+ (progn
+ (goto-char end)
+ (save-excursion
+ ;; `beginning-of-visual-line' reverts to the beginning of the
+ ;; last visual line if the end of the last line is the end of
+ ;; the buffer. This would prevent selecting the last screen
+ ;; line.
+ (if (= (line-beginning-position 2) (point-max))
+ (point-max)
+ (beginning-of-visual-line 2)))))))
+ :contract (lambda (beg end)
+ (evil-range beg (max beg (1- end))))
+ :string (lambda (beg end)
+ (let ((height (count-screen-lines beg end)))
+ (format "%s screen line%s" height
+ (if (= height 1) "" "s")))))
+
+(evil-define-type block
+ "Like `inclusive', but for rectangles:
+the last column is included."
+ :expand (lambda (beg end &rest properties)
+ (let ((beg-col (evil-column beg))
+ (end-col (evil-column end))
+ (corner (plist-get properties :corner)))
+ ;; Since blocks are implemented as a pair of buffer
+ ;; positions, expansion is restricted to what the buffer
+ ;; allows. In the case of a one-column block, there are
+ ;; two ways to expand it (either move the upper corner
+ ;; beyond the lower corner, or the lower beyond the
+ ;; upper), so try out both possibilities when
+ ;; encountering the end of the line.
+ (cond
+ ((= beg-col end-col)
+ (goto-char end)
+ (cond
+ ((eolp)
+ (goto-char beg)
+ (if (eolp)
+ (evil-range beg end)
+ (evil-range (1+ beg) end)))
+ ((memq corner '(lower-right upper-right right))
+ (evil-range (1+ beg) end))
+ (t
+ (evil-range beg (1+ end)))))
+ ((< beg-col end-col)
+ (goto-char end)
+ (if (eolp)
+ (evil-range beg end)
+ (evil-range beg (1+ end))))
+ (t
+ (goto-char beg)
+ (if (eolp)
+ (evil-range beg end)
+ (evil-range (1+ beg) end))))))
+ :contract (lambda (beg end)
+ (let ((beg-col (evil-column beg))
+ (end-col (evil-column end)))
+ (if (> beg-col end-col)
+ (evil-range (1- beg) end)
+ (evil-range beg (max beg (1- end))))))
+ :string (lambda (beg end)
+ (let ((height (count-lines
+ beg
+ (progn
+ (goto-char end)
+ (if (and (bolp) (not (eobp)))
+ (1+ end)
+ end))))
+ (width (abs (- (evil-column beg)
+ (evil-column end)))))
+ (format "%s row%s and %s column%s"
+ height
+ (if (= height 1) "" "s")
+ width
+ (if (= width 1) "" "s"))))
+ :rotate (lambda (beg end &rest properties)
+ "Rotate block according to :corner property.
+:corner can be one of `upper-left',``upper-right', `lower-left'
+and `lower-right'."
+ (let ((left (evil-column beg))
+ (right (evil-column end))
+ (corner (or (plist-get properties :corner)
+ 'upper-left)))
+ (evil-sort left right)
+ (goto-char beg)
+ (if (memq corner '(upper-right lower-left))
+ (move-to-column right)
+ (move-to-column left))
+ (setq beg (point))
+ (goto-char end)
+ (if (memq corner '(upper-right lower-left))
+ (move-to-column left)
+ (move-to-column right))
+ (setq end (point))
+ (setq properties (plist-put properties
+ :corner corner))
+ (apply #'evil-range beg end properties))))
+
+(evil-define-type rectangle
+ "Like `exclusive', but for rectangles:
+the last column is excluded."
+ :expand (lambda (beg end)
+ ;; select at least one column
+ (if (= (evil-column beg) (evil-column end))
+ (evil-expand beg end 'block)
+ (evil-range beg end 'block))))
+
+;;; Standard interactive codes
+
+(evil-define-interactive-code "*"
+ "Signal error if the buffer is read-only."
+ (when buffer-read-only
+ (signal 'buffer-read-only nil)))
+
+(evil-define-interactive-code "b" (prompt)
+ "Name of existing buffer."
+ (list (read-buffer prompt (current-buffer) t)))
+
+(evil-define-interactive-code "c"
+ "Read character."
+ (list (read-char)))
+
+(evil-define-interactive-code "p"
+ "Prefix argument converted to number."
+ (list (prefix-numeric-value current-prefix-arg)))
+
+(evil-define-interactive-code "P"
+ "Prefix argument in raw form."
+ (list current-prefix-arg))
+
+;;; Custom interactive codes
+
+(evil-define-interactive-code "<w>"
+ "Prefix argument converted to number, possibly multiplied by evil--window-digit."
+ (let ((prefix-num (prefix-numeric-value current-prefix-arg)))
+ (if evil--window-digit
+ (list (* evil--window-digit prefix-num))
+ (list prefix-num))))
+
+(evil-define-interactive-code "<c>"
+ "Count."
+ (list (when current-prefix-arg
+ (prefix-numeric-value current-prefix-arg))))
+
+(evil-define-interactive-code "<vc>"
+ "Count, but only in visual state.
+This should be used by an operator taking a count. In normal
+state the count should not be handled by the operator but by the
+motion that defines the operator's range. In visual state the
+range is specified by the visual region and the count is not used
+at all. Thus in the case the operator may use the count
+directly."
+ (list (when (and (evil-visual-state-p) current-prefix-arg)
+ (prefix-numeric-value
+ current-prefix-arg))))
+
+(evil-define-interactive-code "<wc>"
+ "Prefix argument converted to number, or nil possibly multiplied by
+evil--window-digit."
+ (let ((prefix-num (prefix-numeric-value current-prefix-arg)))
+ (list
+ (cond (evil--window-digit (* evil--window-digit prefix-num))
+ (current-prefix-arg prefix-num)))))
+
+(evil-define-interactive-code "<C>"
+ "Character read through `evil-read-key'."
+ (list
+ (if (evil-operator-state-p)
+ (evil-without-restriction (evil-read-key))
+ (evil-read-key))))
+
+(evil-define-interactive-code "<r>"
+ "Untyped motion range (BEG END)."
+ (evil-operator-range))
+
+(evil-define-interactive-code "<R>"
+ "Typed motion range (BEG END TYPE)."
+ (evil-operator-range t))
+
+(evil-define-interactive-code "<v>"
+ "Typed motion range of visual range (BEG END TYPE).
+If visual state is inactive then those values are nil."
+ (if (evil-visual-state-p)
+ (let ((range (evil-visual-range)))
+ (list (car range)
+ (cadr range)
+ (evil-type range)))
+ (list nil nil nil)))
+
+(evil-define-interactive-code "<x>"
+ "Current register."
+ (list evil-this-register))
+
+(evil-define-interactive-code "<y>"
+ "Current yank-handler."
+ (list (evil-yank-handler)))
+
+(evil-define-interactive-code "<a>"
+ "Ex argument."
+ :ex-arg t
+ (list (when evil-called-from-ex-p evil-ex-argument)))
+
+(evil-define-interactive-code "<N>" ()
+ "Prefix argument or ex-arg, converted to number"
+ (list (cond
+ (current-prefix-arg (prefix-numeric-value current-prefix-arg))
+ (evil-ex-argument (string-to-number evil-ex-argument))
+ (evil-called-from-ex-p nil)
+ (t 1))))
+
+(evil-define-interactive-code "<f>"
+ "Ex file argument."
+ :ex-arg file
+ (list (when evil-called-from-ex-p (evil-ex-file-arg))))
+
+(evil-define-interactive-code "<b>"
+ "Ex buffer argument."
+ :ex-arg buffer
+ (list evil-ex-argument))
+
+(evil-define-interactive-code "<sh>"
+ "Ex shell command argument."
+ :ex-arg shell
+ (list evil-ex-argument))
+
+(evil-define-interactive-code "<fsh>"
+ "Ex file or shell command argument."
+ :ex-arg file-or-shell
+ (list evil-ex-argument))
+
+(evil-define-interactive-code "<sym>"
+ "Ex symbolic argument."
+ :ex-arg sym
+ (list (and evil-ex-argument (intern evil-ex-argument))))
+
+(evil-define-interactive-code "<addr>"
+ "Ex line number."
+ (list
+ (when evil-called-from-ex-p
+ (let ((expr (evil-ex-parse (or evil-ex-argument ""))))
+ (if (eq (car expr) 'evil-goto-line)
+ (save-excursion (goto-char evil-ex-point)
+ (eval (cadr expr) t))
+ (user-error "Invalid address"))))))
+
+(evil-define-interactive-code "<!>"
+ "Ex bang argument."
+ :ex-bang t
+ (list evil-ex-bang))
+
+(evil-define-interactive-code "</>"
+ "Ex delimited argument."
+ (when evil-called-from-ex-p
+ (evil-delimited-arguments (or evil-ex-argument ""))))
+
+(evil-define-interactive-code "<g/>"
+ "Ex global argument."
+ (when evil-called-from-ex-p
+ (evil-ex-parse-global (or evil-ex-argument ""))))
+
+(evil-define-interactive-code "<s/>"
+ "Ex substitution argument."
+ :ex-arg substitution
+ (when evil-called-from-ex-p
+ (evil-ex-get-substitute-info (or evil-ex-argument "") t)))
+
+(evil-define-interactive-code "<xc/>"
+ "Ex register and count argument, both optional.
+Can be used for commands such as :delete [REGISTER] [COUNT] where the
+command can be called with either zero, one or two arguments. With one
+argument, if it is numeric, it is treated as a COUNT, otherwise, as a
+REGISTER."
+ (when evil-called-from-ex-p
+ (evil-ex-get-optional-register-and-count evil-ex-argument)))
+
+(defun evil-ex-get-optional-register-and-count (string)
+ "Parse STRING as an ex arg with both optional REGISTER and COUNT.
+Return a list (REGISTER COUNT)."
+ (let* ((split-args (split-string (or string "")))
+ (arg-count (length split-args))
+ (arg0 (car split-args))
+ (arg1 (cadr split-args))
+ (number-regex "^-?[1-9][0-9]*$")
+ (register nil)
+ (count nil))
+ (cond
+ ;; :command REGISTER or :command COUNT
+ ((= arg-count 1)
+ (if (string-match-p number-regex arg0)
+ (setq count arg0)
+ (setq register arg0)))
+ ;; :command REGISTER COUNT
+ ((eq arg-count 2)
+ (setq register arg0
+ count arg1))
+ ;; more than 2 args aren't allowed
+ ((> arg-count 2)
+ (user-error "Invalid use")))
+
+ ;; if register is given, check it's valid
+ (when register
+ (unless (= (length register) 1)
+ (user-error "Invalid register"))
+ (setq register (string-to-char register)))
+
+ ;; if count is given, check it's valid
+ (when count
+ (unless (string-match-p number-regex count)
+ (user-error "Invalid count"))
+ (setq count (string-to-number count))
+ (unless (> count 0)
+ (user-error "Invalid count")))
+
+ (list register count)))
+
+(provide 'evil-types)
+
+;;; evil-types.el ends here
diff --git a/.config/emacs/lisp/evil/evil-vars.el b/.config/emacs/lisp/evil/evil-vars.el
new file mode 100644
index 0000000..291a91a
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil-vars.el
@@ -0,0 +1,2121 @@
+;;; evil-vars.el --- Settings and variables -*- lexical-binding: t -*-
+
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.15.0
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(declare-function evil-add-command-properties "evil-common"
+ (command &rest properties))
+(declare-function evil-update-insert-state-bindings "evil-maps"
+ (&optional _option-name remove force))
+
+;;; Hooks
+
+(defvar evil-after-load-hook nil
+ "Functions to be run when loading of Evil is finished.
+This hook can be used to execute some initialization routines
+when Evil is completely loaded.")
+
+(defvar evil-after-global-hook nil
+ "Functions to be run after :global and :vglobal.")
+
+(defcustom evil-goto-definition-functions
+ '(evil-goto-definition-imenu
+ evil-goto-definition-semantic
+ evil-goto-definition-xref
+ evil-goto-definition-search)
+ "List of functions run until success by `evil-goto-definition'."
+ :type 'hook
+ :group 'evil)
+
+;;; Initialization
+
+(defvar evil-pending-custom-initialize nil
+ "A list of pending initializations for custom variables.
+Each element is a triple (FUNC VAR VALUE). When Evil is
+completely loaded then the functions (funcall FUNC VAR VALUE) is
+called for each element. FUNC should be a function suitable for
+the :initialize property of `defcustom'.")
+
+(defun evil-custom-initialize-pending-reset (var value)
+ "Add a pending customization with `custom-initialize-reset'."
+ (push (list 'custom-initialize-reset var value)
+ evil-pending-custom-initialize))
+
+(defun evil-run-pending-custom-initialize ()
+ "Execute the pending initializations.
+See `evil-pending-custom-initialize'."
+ (dolist (init evil-pending-custom-initialize)
+ (apply (car init) (cdr init)))
+ (remove-hook 'evil-after-load-hook #'evil-run-pending-custom-initialize))
+(add-hook 'evil-after-load-hook #'evil-run-pending-custom-initialize)
+
+;;; Setters
+
+(defun evil-set-toggle-key (key)
+ "Set `evil-toggle-key' to KEY.
+KEY must be readable by `read-kbd-macro'."
+ (let ((old-key (read-kbd-macro
+ (if (boundp 'evil-toggle-key)
+ evil-toggle-key
+ "C-z")))
+ (key (read-kbd-macro key)))
+ (with-no-warnings
+ (dolist (pair '((evil-motion-state-map evil-emacs-state)
+ (evil-insert-state-map evil-emacs-state)
+ (evil-emacs-state-map evil-exit-emacs-state)))
+ (when (boundp (car pair))
+ (let ((map (symbol-value (car pair)))
+ (fun (cadr pair)))
+ (when (keymapp map)
+ (define-key map key fun)
+ (define-key map old-key nil))))))))
+
+(defun evil-set-custom-state-maps (var pending-var key _make newlist)
+ "Change the list of special keymaps.
+VAR is the variable containing the list of keymaps.
+PENDING-VAR is the variable containing the list of the currently pending
+ keymaps.
+KEY the special symbol to be stored in the keymaps.
+MAKE the creation function of the special keymaps.
+NEWLIST the list of new special keymaps."
+ (set-default pending-var newlist)
+ (when (default-boundp var)
+ (dolist (map (default-value var))
+ (when (and (boundp (car map))
+ (keymapp (default-value (car map))))
+ (define-key (default-value (car map)) (vector key) nil))))
+ (set-default var newlist)
+ (evil-update-pending-maps))
+
+(defun evil-update-pending-maps (&optional _file)
+ "Try to set pending special keymaps.
+This function should be called from an `after-load-functions'
+hook."
+ (let ((maps '((evil-make-overriding-map . evil-pending-overriding-maps)
+ (evil-make-intercept-map . evil-pending-intercept-maps))))
+ (while maps
+ (let* ((map (pop maps))
+ (make (car map))
+ (pending-var (cdr map))
+ (pending (symbol-value pending-var))
+ newlist)
+ (while pending
+ (let* ((map (pop pending))
+ (kmap (and (boundp (car map))
+ (keymapp (symbol-value (car map)))
+ (symbol-value (car map))))
+ (state (cdr map)))
+ (if kmap
+ (funcall make kmap state)
+ (push map newlist))))
+ (set-default pending-var newlist)))))
+
+(defun evil-set-visual-newline-commands (var value)
+ "Set the value of `evil-visual-newline-commands'.
+Setting this variable changes the properties of the appropriate
+commands."
+ (with-no-warnings
+ (when (default-boundp var)
+ (dolist (cmd (default-value var))
+ (evil-set-command-property cmd :exclude-newline nil)))
+ (set-default var value)
+ (dolist (cmd (default-value var))
+ (evil-set-command-property cmd :exclude-newline t))))
+
+(defun evil-set-custom-motions (var values)
+ "Set the list of motion commands."
+ (with-no-warnings
+ (when (default-boundp var)
+ (dolist (motion (default-value var))
+ (evil-add-command-properties motion :keep-visual nil :repeat nil)))
+ (set-default var values)
+ (mapc #'evil-declare-motion (default-value var))))
+
+;;; Customization group
+
+(defgroup evil nil
+ "Extensible vi layer."
+ :group 'emulations
+ :prefix 'evil-)
+
+(defcustom evil-auto-indent t
+ "\\<evil-normal-state-map>
+Whether to auto-indent when opening lines with \\[evil-open-below] \
+and \\[evil-open-above]."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-shift-width 4
+ "\\<evil-normal-state-map>
+The number of columns by which a line is shifted.
+This applies to the shifting operators \\[evil-shift-right] and \
+\\[evil-shift-left]."
+ :type 'integer
+ :safe #'integerp
+ :group 'evil)
+
+(defcustom evil-shift-round t
+ "\\<evil-normal-state-map>
+Whether shifting rounds to the nearest multiple.
+If non-nil, \\[evil-shift-right] and \\[evil-shift-left] adjust line
+indentation to the nearest multiple of `evil-shift-width'."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-indent-convert-tabs t
+ "\\<evil-normal-state-map>
+If non-nil, the \\[evil-indent] operator converts between leading tabs and spaces.
+Whether tabs are converted to spaces or vice versa depends on the
+value of `indent-tabs-mode'."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-default-cursor t
+ "The default cursor.
+May be a cursor type as per `cursor-type', a color string as passed
+to `set-cursor-color', a zero-argument function for changing the
+cursor, or a list of the above.
+
+nil is interpreted as t; if you want the nil `cursor-type' (i.e.,
+you want to disable the cursor), set this variable to (list nil)."
+ :type '(set symbol (cons symbol symbol) string function)
+ :group 'evil)
+
+(defvar evil-force-cursor nil
+ "Overwrite the current states default cursor.")
+
+(defcustom evil-start-of-line nil
+ "Analogue of vim's `startofline'.
+If nil, preserve column when making relevant movements of the cursor.
+Otherwise, move the cursor to the start of the line."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-repeat-move-cursor t
+ "\\<evil-normal-state-map>
+Whether repeating commands with \\[evil-repeat] may move the cursor.
+If nil, the original cursor position is preserved, even if the command
+normally would have moved the cursor."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-cross-lines nil
+ "\\<evil-motion-state-map>
+Whether horizontal motions may move to other lines. If non-nil,
+certain motions that conventionally operate in a single line may move
+the cursor to other lines. Otherwise, they are restricted to the
+current line. This applies to \\[evil-backward-char], \
+\\[evil-forward-char], \\[evil-find-char], \
+\\[evil-find-char-backward], \\[evil-find-char-to], \
+\\[evil-find-char-to-backward], \
+\\<evil-normal-state-map>\\[evil-invert-char]."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-backspace-join-lines t
+ "Whether backward delete in insert state may join lines."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-move-cursor-back t
+ "Whether the cursor is moved backwards when exiting insert state.
+If non-nil, the cursor moves \"backwards\" when exiting insert state,
+so that it ends up on the character to the left. Otherwise it remains
+in place, on the character to the right.
+
+See also `evil-move-beyond-eol'."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-move-beyond-eol nil
+ "Whether the cursor can move past the end of the line.
+If non-nil, the cursor is allowed to move one character past the
+end of the line, as in Emacs."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-respect-visual-line-mode nil
+ "\\<evil-motion-state-map>
+Whether movement commands respect `visual-line-mode'.
+If non-nil, `visual-line-mode' is generally respected when it is
+on. In this case, motions such as \\[evil-next-line] and
+\\[evil-previous-line] navigate by visual lines (on the screen) rather
+than \"physical\" lines (defined by newline characters). If nil,
+the setting of `visual-line-mode' is ignored.
+
+This variable must be set before Evil is loaded."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-repeat-find-to-skip-next t
+ "Whether a repeat of t or T should skip an adjacent character."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-kbd-macro-suppress-motion-error nil
+ "\\<evil-motion-state-map>
+Whether left/right motions signal errors in keyboard macros.
+This variable only affects beginning-of-line or end-of-line errors
+regarding the motions \\[evil-backward-char] and \\[evil-forward-char]
+respectively. This may be desired since such errors cause macro
+definition or execution to be terminated. There are four
+possibilities:
+
+- `record': errors are suppressed when recording macros, but not when
+ replaying them.
+- `replay': errors are suppressed when replaying macros, but not when
+ recording them.
+- `t': errors are suppressed in both cases.
+- `nil': errors are never suppressed."
+ :type '(radio (const :tag "No" :value nil)
+ (const :tag "Record" :value record)
+ (const :tag "Replay" :value replay)
+ (const :tag "Both" :value t))
+ :group 'evil)
+
+(defcustom evil-track-eol t
+ "\\<evil-motion-state-map>
+Whether \\[evil-end-of-line] \"sticks\" the cursor to the end of the line.
+If non-nil, vertical motions after \\[evil-end-of-line] maintain the cursor at the
+end of the line, even if the target line is longer. This is analogous
+to `track-eol', but respects Evil's interpretation of end-of-line."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-mode-line-format 'before
+ "The position of the state tag in the mode line.
+If set to `before' or `after', the tag is placed at the beginning
+or the end of the mode-line, respectively. If nil, there is no
+tag. Otherwise it should be a cons cell (WHERE . WHICH), where
+WHERE is either `before' or `after', and WHICH is a symbol in
+`mode-line-format'. The tag is then placed before or after that
+symbol, respectively."
+ :type '(radio :value 'before
+ (const :tag "No tag" nil)
+ (const before)
+ (const after)
+ (cons :tag "Next to symbol"
+ (choice :value after
+ (const before)
+ (const after))
+ symbol))
+ :group 'evil)
+
+(defcustom evil-mouse-word 'evil-word
+ "The thing-at-point symbol for double click selection.
+The double-click starts visual state in a special word selection
+mode. This symbol is used to determine the words to be
+selected. Possible values are `evil-word' or `evil-WORD'."
+ :type 'symbol
+ :group 'evil)
+
+(defcustom evil-bigword "^ \t\r\n"
+ "The set of characters to be interpreted as WORD boundaries.
+This is enclosed with square brackets and used as a regular
+expression. By default, whitespace characters are considered
+WORD boundaries."
+ :type 'string
+ :group 'evil)
+
+(defcustom evil-want-fine-undo nil
+ "Whether actions are undone in several steps.
+There are two possible choices: nil (\"no\") means that all
+changes made during insert state, including a possible delete
+after a change operation, are collected in a single undo step.
+Non-nil (\"yes\") means that undo steps are determined according
+to Emacs heuristics, and no attempt is made to aggregate changes.
+
+For backward compatibility purposes, the value `fine' is
+interpreted as `nil'. This option was removed because it did not
+work consistently."
+ :type '(radio (const :tag "No" :value nil)
+ (const :tag "Fine (obsolete)" :value fine)
+ (const :tag "Yes" :value t))
+ :group 'evil)
+
+(defcustom evil-regexp-search t
+ "\\<evil-motion-state-map>
+Whether to use regular expressions for searching in \
+\\[evil-search-forward] and \\[evil-search-backward]."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-search-wrap t
+ "\\<evil-motion-state-map>
+Whether search with \\[evil-search-forward] and \
+\\[evil-search-backward] wraps around the buffer.
+If this is non-nil, search stops at the buffer boundaries."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-flash-delay 2
+ "\\<evil-motion-state-map>
+Time in seconds to flash search matches after \\[evil-search-next] and \
+\\[evil-search-previous]."
+ :type 'number
+ :group 'evil)
+
+(defcustom evil-auto-balance-windows t
+ "If non-nil window creation and deletion trigger rebalancing."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-split-window-below nil
+ "If non-nil split windows are created below."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-vsplit-window-right nil
+ "If non-nil vertically split windows with are created to the right."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-esc-delay 0.01
+ "The time, in seconds, to wait for another key after escape.
+If no further event arrives during this time, the event is
+translated to `ESC'. Otherwise, it is translated according to
+`input-decode-map'. This does not apply in Emacs state, and may
+also be inhibited by setting `evil-inhibit-esc'."
+ :type 'number
+ :group 'evil)
+
+(defvar evil-esc-mode nil
+ "Non-nil if `evil-esc-mode' is enabled.")
+
+(defvar evil-esc-map nil
+ "Original ESC prefix map in `input-decode-map'.
+Used by `evil-esc-mode'.")
+
+(defvar evil-inhibit-esc nil
+ "If non-nil, the \"\\e\" event will never be translated to `escape'.")
+
+(defcustom evil-intercept-esc 'always
+ "Whether Evil should intercept the escape key.
+In the terminal, escape and a meta key sequence both generate the
+same event. In order to distingush these, Evil uses
+`input-decode-map'. It is not necessary to do this in a graphical
+Emacs session. However, if you prefer to use \"C-[\" as escape (which
+is identical to the terminal escape key code), this interception must
+also happen in graphical Emacs sessions. Set this variable to
+`always', t (only in the terminal) or nil (never intercept)."
+ :type '(radio (const :tag "Never" :value nil)
+ (const :tag "In terminal only" :value t)
+ (const :tag "Always" :value always))
+ :group 'evil)
+
+(defcustom evil-show-paren-range 0
+ "The maximum distance between point and a parenthesis
+which causes the parenthesis to be highlighted."
+ :type 'integer
+ :group 'evil)
+
+(defcustom evil-ex-hl-update-delay 0.02
+ "Time in seconds of idle before updating search highlighting.
+Setting this to a period shorter than that of keyboard's repeat
+rate allows highlights to update while scrolling."
+ :type 'number
+ :group 'evil)
+
+(defcustom evil-highlight-closing-paren-at-point-states
+ '(not emacs insert replace)
+ "The states in which the closing parenthesis at point should be highlighted.
+All states listed here highlight the closing parenthesis at
+point (which is Vim's default behavior). All others highlight the
+parenthesis before point (which is Emacs default behavior). If
+this list contains the symbol `not' then its meaning is inverted,
+i.e. all states listed here highlight the closing parenthesis
+before point."
+ :type '(repeat symbol)
+ :group 'evil)
+
+(defcustom evil-kill-on-visual-paste t
+ "Whether pasting in visual state adds the replaced text to the
+kill ring, making it the default for the next paste. The default
+replicates the default Vim behavior for `p'. This value is flipped by
+`evil-paste-before' (\\[evil-paste-before])."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-want-C-i-jump t
+ "Whether `C-i' jumps forward in the jump list (like Vim).
+Otherwise, `C-i' inserts a tab character."
+ :type 'boolean
+ :group 'evil
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (when (boundp 'evil-motion-state-map)
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-motion-state-map (kbd "C-i"))
+ 'evil-jump-forward))
+ (define-key evil-motion-state-map (kbd "C-i") nil))
+ ((and value
+ (not (lookup-key evil-motion-state-map (kbd "C-i"))))
+ (define-key evil-motion-state-map (kbd "C-i")
+ 'evil-jump-forward))))))
+
+(defcustom evil-want-C-u-scroll nil
+ "Whether `C-u' scrolls up (like Vim).
+Otherwise, `C-u' applies a prefix argument. The binding of
+`C-u' mirrors Emacs behaviour by default due to the relative
+ubiquity of prefix arguments."
+ :type 'boolean
+ :group 'evil
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (when (boundp 'evil-motion-state-map)
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-motion-state-map (kbd "C-u"))
+ 'evil-scroll-up))
+ (define-key evil-motion-state-map (kbd "C-u") nil))
+ ((and value
+ (not (lookup-key evil-motion-state-map (kbd "C-u"))))
+ (define-key evil-motion-state-map (kbd "C-u")
+ 'evil-scroll-up))))))
+
+(defcustom evil-want-C-d-scroll t
+ "Whether `C-d' scrolls down (like Vim)."
+ :type 'boolean
+ :group 'evil
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (when (boundp 'evil-motion-state-map)
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-motion-state-map (kbd "C-d"))
+ 'evil-scroll-down))
+ (define-key evil-motion-state-map (kbd "C-d") nil))
+ ((and value
+ (not (lookup-key evil-motion-state-map (kbd "C-d"))))
+ (define-key evil-motion-state-map (kbd "C-d")
+ 'evil-scroll-down))))))
+
+(defcustom evil-want-C-u-delete nil
+ "Whether `C-u' deletes back to indentation in insert state.
+Otherwise, `C-u' applies a prefix argument. The binding of
+`C-u' mirrors Emacs behaviour by default due to the relative
+ubiquity of prefix arguments."
+ :type 'boolean
+ :group 'evil
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (when (and (boundp 'evil-insert-state-map)
+ (boundp 'evil-replace-state-map))
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-insert-state-map (kbd "C-u"))
+ 'evil-delete-back-to-indentation))
+ (define-key evil-insert-state-map (kbd "C-u") nil)
+ (define-key evil-replace-state-map (kbd "C-u") nil))
+ ((and value
+ (not (lookup-key evil-insert-state-map (kbd "C-u"))))
+ (define-key evil-insert-state-map (kbd "C-u")
+ 'evil-delete-back-to-indentation)
+ (define-key evil-replace-state-map (kbd "C-u")
+ 'evil-delete-back-to-indentation))))))
+
+(defcustom evil-want-C-w-delete t
+ "Whether `C-w' deletes a word in Insert/Ex/Search state."
+ :type 'boolean
+ :group 'evil
+ :set (lambda (sym value)
+ (set-default sym value)
+ (when (and (boundp 'evil-insert-state-map)
+ (boundp 'evil-replace-state-map))
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-insert-state-map (kbd "C-w"))
+ 'evil-delete-backward-word))
+ (define-key evil-insert-state-map (kbd "C-w") 'evil-window-map)
+ (define-key evil-replace-state-map (kbd "C-w") 'evil-window-map))
+ ((and value
+ (eq (lookup-key evil-insert-state-map (kbd "C-w"))
+ 'evil-window-map))
+ (define-key evil-insert-state-map (kbd "C-w") 'evil-delete-backward-word)
+ (define-key evil-replace-state-map (kbd "C-w") 'evil-delete-backward-word))))
+ (when (boundp 'evil-command-line-map)
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-command-line-map (kbd "C-w"))
+ 'evil-delete-backward-word))
+ (define-key evil-command-line-map (kbd "C-w") nil))
+ ((and value
+ (null (lookup-key evil-command-line-map (kbd "C-w"))))
+ (define-key evil-command-line-map (kbd "C-w") 'evil-delete-backward-word))))
+ (when (boundp 'evil-ex-search-keymap)
+ (cond
+ ((and (not value)
+ (null (lookup-key evil-ex-search-keymap (kbd "C-w"))))
+ (define-key evil-ex-search-keymap (kbd "C-w") 'evil-search-yank-word))
+ ((and value
+ (eq (lookup-key evil-ex-search-keymap (kbd "C-w"))
+ 'evil-search-yank-word))
+ (define-key evil-ex-search-keymap (kbd "C-w") nil))))))
+
+(defcustom evil-want-C-h-delete nil
+ "Whether `C-h' deletes a char in Insert state."
+ :type 'boolean
+ :group 'evil
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (when (and (boundp 'evil-insert-state-map)
+ (boundp 'evil-replace-state-map))
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-insert-state-map (kbd "C-h"))
+ 'evil-delete-backward-char-and-join))
+ (define-key evil-insert-state-map (kbd "C-h") nil)
+ (define-key evil-replace-state-map (kbd "C-h") nil))
+ ((and value
+ (not (lookup-key evil-insert-state-map (kbd "C-h"))))
+ (define-key evil-insert-state-map (kbd "C-h")
+ 'evil-delete-backward-char-and-join)
+ (define-key evil-replace-state-map (kbd "C-h")
+ 'evil-replace-backspace))))))
+
+(defcustom evil-want-C-g-bindings nil
+ "Whether `C-g' postfix can be used in bindings."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-want-C-w-in-emacs-state nil
+ "Whether `C-w' prefixes windows commands in Emacs state."
+ :type 'boolean
+ :group 'evil
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (when (boundp 'evil-emacs-state-map)
+ (cond
+ ((and (not value)
+ (eq (lookup-key evil-emacs-state-map (kbd "C-w"))
+ 'evil-window-map))
+ (define-key evil-emacs-state-map (kbd "C-w") nil))
+ ((and value
+ (not (lookup-key evil-emacs-state-map (kbd "C-w"))))
+ (define-key evil-emacs-state-map (kbd "C-w") 'evil-window-map))))))
+
+(defcustom evil-want-change-word-to-end t
+ "Whether `cw' behaves like `ce'."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-want-Y-yank-to-eol nil
+ "Whether `Y' yanks to the end of the line.
+The default behavior is to yank the whole line, like Vim."
+ :group 'evil
+ :type 'boolean
+ :initialize #'evil-custom-initialize-pending-reset
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (evil-add-command-properties
+ 'evil-yank-line
+ :motion (if value
+ 'evil-end-of-line-or-visual-line
+ 'evil-line-or-visual-line))))
+
+(defcustom evil-disable-insert-state-bindings nil
+ "Whether insert state bindings should be used.
+Bindings for escape, delete and `evil-toggle-key' are always
+available. If this is non-nil, default Emacs bindings are by and
+large accessible in insert state."
+ :group 'evil
+ :type 'boolean
+ :initialize #'evil-custom-initialize-pending-reset
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (evil-update-insert-state-bindings sym value)))
+
+(defcustom evil-echo-state t
+ "Whether to signal the current state in the echo area."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-complete-all-buffers t
+ "\\<evil-insert-state-map>
+Whether completion looks for matches in all buffers.
+This applies to \\[evil-complete-next] and \\[evil-complete-previous] \
+in insert state."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-search-wrap-ring-bell nil
+ "Whether to ring the bell when search wraps around the buffer."
+ :type 'boolean
+ :group 'evil)
+
+(defvar dabbrev-search-these-buffers-only)
+(defvar dabbrev-case-distinction)
+(defcustom evil-complete-next-func
+ #'(lambda (arg)
+ (require 'dabbrev)
+ (let ((dabbrev-search-these-buffers-only
+ (unless evil-complete-all-buffers
+ (list (current-buffer))))
+ dabbrev-case-distinction)
+ (condition-case nil
+ (if (eq last-command this-command)
+ (dabbrev-expand nil)
+ (dabbrev-expand (- (abs (or arg 1)))))
+ (error (dabbrev-expand nil)))))
+ "Completion function used by \
+\\<evil-insert-state-map>\\[evil-complete-next]."
+ :type 'function
+ :group 'evil)
+
+(defcustom evil-complete-previous-func
+ #'(lambda (arg)
+ (require 'dabbrev)
+ (let ((dabbrev-search-these-buffers-only
+ (unless evil-complete-all-buffers
+ (list (current-buffer))))
+ dabbrev-case-distinction)
+ (dabbrev-expand arg)))
+ "Completion function used by \
+\\<evil-insert-state-map>\\[evil-complete-previous]."
+ :type 'function
+ :group 'evil)
+
+(defcustom evil-complete-next-minibuffer-func 'minibuffer-complete
+ "Minibuffer completion function used by \
+\\<evil-insert-state-map>\\[evil-complete-next]."
+ :type 'function
+ :group 'evil)
+
+(defcustom evil-complete-previous-minibuffer-func 'minibuffer-complete
+ "Minibuffer completion function used by \
+\\<evil-insert-state-map>\\[evil-complete-previous]."
+ :type 'function
+ :group 'evil)
+
+(defcustom evil-complete-next-line-func
+ #'(lambda (arg)
+ (let ((hippie-expand-try-functions-list
+ '(try-expand-line
+ try-expand-line-all-buffers)))
+ (hippie-expand arg)))
+ "Minibuffer completion function used by \
+\\<evil-insert-state-map>\\[evil-complete-next-line]."
+ :type 'function
+ :group 'evil)
+
+(defcustom evil-complete-previous-line-func
+ evil-complete-next-line-func
+ "Minibuffer completion function used by \
+\\<evil-insert-state-map>\\[evil-complete-previous-line]."
+ :type 'function
+ :group 'evil)
+
+(defcustom evil-lookup-func #'woman
+ "Lookup function used by \
+\"\\<evil-motion-state-map>\\[evil-lookup]\"."
+ :type 'function
+ :group 'evil)
+
+(defcustom evil-toggle-key "C-z"
+ "The key used to change to and from Emacs state.
+Must be readable by `read-kbd-macro'. For example: \"C-z\"."
+ :type 'string
+ :group 'evil
+ :set #'(lambda (sym value)
+ (evil-set-toggle-key value)
+ (set-default sym value)))
+
+(defcustom evil-default-state 'normal
+ "The default Evil state.
+This is the state a buffer starts in when it is not otherwise
+configured (see `evil-set-initial-state' and
+`evil-buffer-regexps'). The value may be one of `normal',
+`insert', `visual', `replace', `operator', `motion' and `emacs'."
+ :type 'symbol
+ :group 'evil)
+
+(defcustom evil-buffer-regexps
+ '(("^ \\*load\\*" . nil))
+ "Regular expressions determining the initial state for a buffer.
+Entries have the form (REGEXP . STATE), where REGEXP is a regular
+expression matching the buffer's name and STATE is one of `normal',
+`insert', `visual', `replace', `operator', `motion', `emacs' and
+`nil'. If STATE is `nil', Evil is disabled in the buffer."
+ :type '(alist :key-type string :value-type symbol)
+ :group 'evil)
+
+(defcustom evil-emacs-state-modes
+ '(5x5-mode
+ archive-mode
+ bbdb-mode
+ biblio-selection-mode
+ blackbox-mode
+ bookmark-bmenu-mode
+ bookmark-edit-annotation-mode
+ browse-kill-ring-mode
+ bs-mode
+ bubbles-mode
+ bzr-annotate-mode
+ calc-mode
+ cfw:calendar-mode
+ completion-list-mode
+ Custom-mode
+ custom-theme-choose-mode
+ debugger-mode
+ delicious-search-mode
+ desktop-menu-blist-mode
+ desktop-menu-mode
+ doc-view-mode
+ dun-mode
+ dvc-bookmarks-mode
+ dvc-diff-mode
+ dvc-info-buffer-mode
+ dvc-log-buffer-mode
+ dvc-revlist-mode
+ dvc-revlog-mode
+ dvc-status-mode
+ dvc-tips-mode
+ ediff-mode
+ ediff-meta-mode
+ efs-mode
+ Electric-buffer-menu-mode
+ emms-browser-mode
+ emms-mark-mode
+ emms-metaplaylist-mode
+ emms-playlist-mode
+ ess-help-mode
+ etags-select-mode
+ fj-mode
+ gc-issues-mode
+ gdb-breakpoints-mode
+ gdb-disassembly-mode
+ gdb-frames-mode
+ gdb-locals-mode
+ gdb-memory-mode
+ gdb-registers-mode
+ gdb-threads-mode
+ gist-list-mode
+ git-rebase-mode
+ gnus-article-mode
+ gnus-browse-mode
+ gnus-group-mode
+ gnus-server-mode
+ gnus-summary-mode
+ gomoku-mode
+ google-maps-static-mode
+ ibuffer-mode
+ jde-javadoc-checker-report-mode
+ magit-cherry-mode
+ magit-diff-mode
+ magit-log-mode
+ magit-log-select-mode
+ magit-popup-mode
+ magit-popup-sequence-mode
+ magit-process-mode
+ magit-reflog-mode
+ magit-refs-mode
+ magit-revision-mode
+ magit-stash-mode
+ magit-stashes-mode
+ magit-status-mode
+ mh-folder-mode
+ monky-mode
+ mpuz-mode
+ mu4e-main-mode
+ mu4e-headers-mode
+ mu4e-view-mode
+ notmuch-hello-mode
+ notmuch-search-mode
+ notmuch-show-mode
+ notmuch-tree-mode
+ occur-mode
+ org-agenda-mode
+ package-menu-mode
+ pdf-outline-buffer-mode
+ pdf-view-mode
+ proced-mode
+ rcirc-mode
+ rebase-mode
+ recentf-dialog-mode
+ reftex-select-bib-mode
+ reftex-select-label-mode
+ reftex-toc-mode
+ sldb-mode
+ slime-inspector-mode
+ slime-thread-control-mode
+ slime-xref-mode
+ snake-mode
+ solitaire-mode
+ sr-buttons-mode
+ sr-mode
+ sr-tree-mode
+ sr-virtual-mode
+ tar-mode
+ tetris-mode
+ tla-annotate-mode
+ tla-archive-list-mode
+ tla-bconfig-mode
+ tla-bookmarks-mode
+ tla-branch-list-mode
+ tla-browse-mode
+ tla-category-list-mode
+ tla-changelog-mode
+ tla-follow-symlinks-mode
+ tla-inventory-file-mode
+ tla-inventory-mode
+ tla-lint-mode
+ tla-logs-mode
+ tla-revision-list-mode
+ tla-revlog-mode
+ tla-tree-lint-mode
+ tla-version-list-mode
+ twittering-mode
+ urlview-mode
+ vc-annotate-mode
+ vc-dir-mode
+ vc-git-log-view-mode
+ vc-hg-log-view-mode
+ vc-svn-log-view-mode
+ vm-mode
+ vm-summary-mode
+ w3m-mode
+ wab-compilation-mode
+ xgit-annotate-mode
+ xgit-changelog-mode
+ xgit-diff-mode
+ xgit-revlog-mode
+ xhg-annotate-mode
+ xhg-log-mode
+ xhg-mode
+ xhg-mq-mode
+ xhg-mq-sub-mode
+ xhg-status-extra-mode)
+ "Modes that should come up in Emacs state."
+ :type '(repeat symbol)
+ :group 'evil)
+
+(defcustom evil-insert-state-modes
+ '(comint-mode
+ erc-mode
+ eshell-mode
+ geiser-repl-mode
+ gud-mode
+ inferior-apl-mode
+ inferior-caml-mode
+ inferior-emacs-lisp-mode
+ inferior-j-mode
+ inferior-python-mode
+ inferior-scheme-mode
+ inferior-sml-mode
+ internal-ange-ftp-mode
+ haskell-interactive-mode
+ prolog-inferior-mode
+ racket-repl-mode
+ reb-mode
+ shell-mode
+ slime-repl-mode
+ term-mode
+ utop-mode
+ wdired-mode)
+ "Modes that should come up in Insert state."
+ :type '(repeat symbol)
+ :group 'evil)
+
+(defcustom evil-motion-state-modes
+ '(apropos-mode
+ Buffer-menu-mode
+ calendar-mode
+ color-theme-mode
+ command-history-mode
+ compilation-mode
+ dictionary-mode
+ ert-results-mode
+ help-mode
+ Info-mode
+ Man-mode
+ speedbar-mode
+ undo-tree-visualizer-mode
+ woman-mode)
+ "Modes that should come up in Motion state."
+ :type '(repeat symbol)
+ :group 'evil)
+
+(defvar evil-pending-overriding-maps nil
+ "An alist of pending overriding maps.")
+
+(defvar evil-pending-intercept-maps nil
+ "An alist of pending intercept maps.")
+
+(defcustom evil-overriding-maps '()
+ "Keymaps that should override Evil maps.
+Entries have the form (MAP-VAR . STATE), where MAP-VAR is
+a keymap variable and STATE is the state whose bindings
+should be overridden. If STATE is nil, all states are
+overridden."
+ :type '(alist :key-type symbol :value-type symbol)
+ :group 'evil
+ :set #'(lambda (var values)
+ (set-default var values)
+ (evil-set-custom-state-maps 'evil-overriding-maps
+ 'evil-pending-overriding-maps
+ 'override-state
+ 'evil-make-overriding-map
+ values))
+ :initialize #'evil-custom-initialize-pending-reset)
+
+(add-hook 'after-load-functions #'evil-update-pending-maps)
+
+(defcustom evil-intercept-maps
+ '((edebug-mode-map . nil))
+ "Keymaps that should intercept Evil maps.
+Entries have the form (MAP-VAR . STATE), where MAP-VAR is
+a keymap variable and STATE is the state whose bindings
+should be intercepted. If STATE is nil, all states are
+intercepted."
+ :type '(alist :key-type symbol :value-type symbol)
+ :group 'evil
+ :set #'(lambda (var values)
+ (set-default var values)
+ (evil-set-custom-state-maps 'evil-intercept-maps
+ 'evil-pending-intercept-maps
+ 'intercept-state
+ 'evil-make-intercept-map
+ values))
+ :initialize #'evil-custom-initialize-pending-reset)
+
+(defcustom evil-motions
+ '(back-to-indentation
+ backward-char
+ backward-list
+ backward-paragraph
+ backward-sentence
+ backward-sexp
+ backward-up-list
+ backward-word
+ beginning-of-buffer
+ beginning-of-defun
+ beginning-of-line
+ beginning-of-visual-line
+ c-beginning-of-defun
+ c-end-of-defun
+ diff-file-next
+ diff-file-prev
+ diff-hunk-next
+ diff-hunk-prev
+ down-list
+ end-of-buffer
+ end-of-defun
+ end-of-line
+ end-of-visual-line
+ exchange-point-and-mark
+ forward-char
+ forward-list
+ forward-paragraph
+ forward-sentence
+ forward-sexp
+ forward-word
+ goto-char
+ goto-last-change
+ ibuffer-backward-line
+ ibuffer-forward-line
+ isearch-abort
+ isearch-cancel
+ isearch-complete
+ isearch-del-char
+ isearch-delete-char
+ isearch-edit-string
+ isearch-exit
+ isearch-highlight-regexp
+ isearch-occur
+ isearch-other-control-char
+ isearch-other-meta-char
+ isearch-printing-char
+ isearch-query-replace
+ isearch-query-replace-regexp
+ isearch-quote-char
+ isearch-repeat-backward
+ isearch-repeat-forward
+ isearch-ring-advance
+ isearch-ring-retreat
+ isearch-toggle-case-fold
+ isearch-toggle-input-method
+ isearch-toggle-regexp
+ isearch-toggle-specified-input-method
+ isearch-toggle-word
+ isearch-yank-char
+ isearch-yank-kill
+ isearch-yank-line
+ isearch-yank-word-or-char
+ keyboard-quit
+ left-char
+ left-word
+ mouse-drag-region
+ mouse-save-then-kill
+ mouse-set-point
+ mouse-set-region
+ mwheel-scroll
+ move-beginning-of-line
+ move-end-of-line
+ next-error
+ next-line
+ paredit-backward
+ paredit-backward-down
+ paredit-backward-up
+ paredit-forward
+ paredit-forward-down
+ paredit-forward-up
+ pop-global-mark
+ pop-tag-mark
+ pop-to-mark-command
+ previous-error
+ previous-line
+ right-char
+ right-word
+ scroll-down
+ scroll-down-command
+ scroll-up
+ scroll-up-command
+ sgml-skip-tag-backward
+ sgml-skip-tag-forward
+ up-list)
+ "Non-Evil commands to initialize to motions."
+ :type '(repeat symbol)
+ :group 'evil
+ :set #'evil-set-custom-motions
+ :initialize #'evil-custom-initialize-pending-reset)
+
+(defcustom evil-visual-newline-commands
+ '(LaTeX-section
+ TeX-font)
+ "Commands excluding the trailing newline of a Visual Line selection.
+These commands work better without this newline."
+ :type '(repeat symbol)
+ :group 'evil
+ :set #'evil-set-visual-newline-commands
+ :initialize #'evil-custom-initialize-pending-reset)
+
+(defcustom evil-want-visual-char-semi-exclusive nil
+ "DEPRECATED. Will be removed in a future version.
+Prefer to set `evil-v$-excludes-newline' to non-nil.
+
+Visual character selection to beginning/end of line is exclusive.
+If non nil then an inclusive visual character selection which
+ends at the beginning or end of a line is turned into an
+exclusive selection. Thus if the selected (inclusive) range ends
+at the beginning of a line it is changed to not include the first
+character of that line, and if the selected range ends at the end
+of a line it is changed to not include the newline character of
+that line."
+ :type 'boolean
+ :group 'evil)
+(make-obsolete-variable
+ 'evil-want-visual-char-semi-exclusive
+ "Semi-exclusivity prevents selecting text + 1st char of next line,
+without having to introduce new niche functionality.
+Prefer to set `evil-v$-excludes-newline' to non-nil."
+ "1.15.0")
+
+(defcustom evil-v$-excludes-newline nil
+ "If non-nil, `evil-end-of-line' does not move as far as to include
+the `\n' char at eol. This makes `v$' consistent with `$' used as a
+motion (e.g. `v$y' is consistent with `y$' in normal state)."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-text-object-change-visual-type t
+ "Text objects change the current visual state type.
+If non-nil then a text-object changes the type of the visual state to
+its default selection type (e.g. a word object always changes to
+charwise visual state). Otherwise the current visual state type is
+preserved."
+ :type 'boolean
+ :group 'evil)
+
+(defgroup evil-cjk nil
+ "CJK support"
+ :prefix "evil-cjk-"
+ :group 'evil)
+
+(defcustom evil-cjk-emacs-word-boundary nil
+ "Determine word boundary exactly the same way as Emacs does."
+ :type 'boolean
+ :group 'evil-cjk)
+
+(defcustom evil-cjk-word-separating-categories
+ '(;; Kanji
+ (?C . ?H) (?C . ?K) (?C . ?k) (?C . ?A) (?C . ?G)
+ ;; Hiragana
+ (?H . ?C) (?H . ?K) (?H . ?k) (?H . ?A) (?H . ?G)
+ ;; Katakana
+ (?K . ?C) (?K . ?H) (?K . ?k) (?K . ?A) (?K . ?G)
+ ;; half-width Katakana
+ (?k . ?C) (?k . ?H) (?k . ?K) ; (?k . ?A) (?k . ?G)
+ ;; full-width alphanumeric
+ (?A . ?C) (?A . ?H) (?A . ?K) ; (?A . ?k) (?A . ?G)
+ ;; full-width Greek
+ (?G . ?C) (?G . ?H) (?G . ?K) ; (?G . ?k) (?G . ?A)
+ )
+ "List of pair (cons) of categories to determine word boundary
+used in `evil-cjk-word-boundary-p'. See the documentation of
+`word-separating-categories'. Use `describe-categories' to see
+the list of categories."
+ :type '(alist :key-type (choice character (const nil))
+ :value-type (choice character (const nil)))
+ :group 'evil-cjk)
+
+(defcustom evil-cjk-word-combining-categories
+ '(;; default value in word-combining-categories
+ (nil . ?^) (?^ . nil)
+ ;; Roman
+ (?r . ?k) (?r . ?A) (?r . ?G)
+ ;; half-width Katakana
+ (?k . ?r) (?k . ?A) (?k . ?G)
+ ;; full-width alphanumeric
+ (?A . ?r) (?A . ?k) (?A . ?G)
+ ;; full-width Greek
+ (?G . ?r) (?G . ?k) (?G . ?A)
+ )
+ "List of pair (cons) of categories to determine word boundary
+used in `evil-cjk-word-boundary-p'. See the documentation of
+`word-combining-categories'. Use `describe-categories' to see the
+list of categories."
+ :type '(alist :key-type (choice character (const nil))
+ :value-type (choice character (const nil)))
+ :group 'evil-cjk)
+
+(defcustom evil-ex-complete-emacs-commands 'in-turn
+ "TAB-completion for Emacs commands in ex command line.
+This variable determines when Emacs commands are considered for
+completion, always, never, or only if no Evil ex command is
+available for completion."
+ :group 'evil
+ :type '(radio (const :tag "Only if no ex-command." :value in-turn)
+ (const :tag "Never" :value nil)
+ (const :tag "Always" :value t)))
+
+(defface evil-ex-commands '(( nil
+ :underline t
+ :slant italic))
+ "Face for the Evil command in completion in ex mode."
+ :group 'evil)
+
+(defface evil-ex-info '(( ((supports :slant))
+ :slant italic
+ :foreground "red"))
+ "Face for the info message in ex mode."
+ :group 'evil)
+
+(defcustom evil-ex-visual-char-range nil
+ "Type of default ex range in visual char state.
+If non-nil the default range when starting an ex command from
+character visual state is `<,`> otherwise it is '<,'>. In the
+first case the ex command will be passed a region covering only
+the visual selection. In the second case the passed region will
+be extended to contain full lines."
+ :group 'evil
+ :type 'boolean)
+
+(defvar evil--ex-global-active-p nil
+ "If the :global command is running.
+Used to change the behaviour of certain commands like :print.")
+
+(defvar evil--ex-print-accumulator ""
+ "Used by :print etc. to accumulate a string when invoked by :global etc.")
+
+;; Searching
+(defcustom evil-symbol-word-search nil
+ "If nil then * and # search for words otherwise for symbols."
+ :group 'evil
+ :type 'boolean)
+
+(defcustom evil-magic t
+ "Meaning which characters in a pattern are magic.
+The meaning of those values is the same as in Vim. Note that it
+only has influence if the Evil search module is chosen in
+`evil-search-module'."
+ :group 'evil
+ :type '(radio (const :tag "Very magic." :value very-magic)
+ (const :tag "Magic" :value t)
+ (const :tag "Nomagic" :value nil)
+ (const :tag "Very nomagic" :value very-nomagic)))
+
+(defcustom evil-ex-search-vim-style-regexp nil
+ "If non-nil Vim-style backslash codes are supported in search patterns.
+See `evil-transform-vim-style-regexp' for the supported backslash
+codes. Note that this only affects the search command if
+`evil-search-module' is set to `evil-search'. The isearch module
+always uses plain Emacs regular expressions."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-ex-interactive-search-highlight 'all-windows
+ "Determine in which windows the interactive highlighting should be shown."
+ :type '(radio (const :tag "All windows." all-windows)
+ (const :tag "Selected window." selected-window)
+ (const :tag "Disable highlighting." nil))
+ :group 'evil)
+
+(defcustom evil-ex-search-persistent-highlight t
+ "If non-nil matches remain highlighted when the search ends."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-ex-search-case 'smart
+ "The case behaviour of the search command.
+Smart case means that the pattern is case sensitive if and only
+if it contains an upper case letter, otherwise it is case
+insensitive."
+ :type '(radio (const :tag "Case sensitive." sensitive)
+ (const :tag "Case insensitive." insensitive)
+ (const :tag "Smart case." smart))
+ :group 'evil)
+
+(defcustom evil-ex-substitute-case nil
+ "The case behaviour of the search command.
+Smart case means that the pattern is case sensitive if and only
+if it contains an upper case letter, otherwise it is case
+insensitive. If nil then the setting of `evil-ex-search-case' is
+used."
+ :type '(radio (const :tag "Same as interactive search." nil)
+ (const :tag "Case sensitive." sensitive)
+ (const :tag "Case insensitive." insensitive)
+ (const :tag "Smart case." smart))
+ :group 'evil)
+
+(defcustom evil-ex-search-interactive t
+ "If t search is interactive."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-ex-search-incremental t
+ "If t, use incremental search. Note that this only affects the
+search command if `evil-search-module' is set to `evil-search'."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-ex-search-highlight-all t
+ "If t and interactive search is enabled, all matches are
+highlighted."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-ex-substitute-highlight-all t
+ "If t all matches for the substitute pattern are highlighted."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-ex-substitute-interactive-replace t
+ "If t and substitute patterns are highlighted,
+the replacement is shown interactively."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-ex-substitute-global nil
+ "If non-nil substitute patterns are global by default.
+Standardly (if this variable is nil) a substitution works only on the
+first match of the pattern in a line unless the \"g\" flag is
+given, in which case the substitution happens on all matches in the
+line. If this option is non-nil, this behavior is reversed."
+ :type 'boolean
+ :group 'evil)
+
+(defface evil-ex-search '((t :inherit isearch))
+ "Face for interactive search."
+ :group 'evil)
+
+(defface evil-ex-lazy-highlight '((t :inherit lazy-highlight))
+ "Face for highlighting all matches in interactive search."
+ :group 'evil)
+
+(defface evil-ex-substitute-matches '((t :inherit lazy-highlight))
+ "Face for interactive substitute matches."
+ :group 'evil)
+
+(defface evil-ex-substitute-replacement '((((supports :underline))
+ :underline t
+ :foreground "red"))
+ "Face for interactive replacement text."
+ :group 'evil)
+
+(defcustom evil-command-window-height 7
+ "Height (in lines) of the command line window.
+Set to 0 to use the default height for `split-window'."
+ :type 'integer
+ :group 'evil)
+
+(defcustom evil-display-shell-error-in-message nil
+ "Show error output of a shell command in the error buffer.
+If this variable is non-nil the error output of a shell command
+goes to the messages buffer instead of being mixed with the
+regular output. This happens only if the exit status of the
+command is non-zero."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-want-abbrev-expand-on-insert-exit t
+ "If non-nil abbrevs will be expanded when leaving insert state
+like in Vim, if `abbrev-mode' is on."
+ :type 'boolean
+ :group 'evil)
+
+;;; Variables
+
+(defmacro evil-define-local-var (symbol &optional initvalue docstring)
+ "Define SYMBOL as permanent buffer local variable, and return SYMBOL.
+The parameters are the same as for `defvar', but the variable
+SYMBOL is made permanent buffer local."
+ (declare (indent defun)
+ (doc-string 3)
+ (debug (symbolp &optional form stringp)))
+ `(progn
+ (defvar ,symbol ,initvalue ,docstring)
+ (make-variable-buffer-local ',symbol)
+ (put ',symbol 'permanent-local t)))
+
+(evil-define-local-var evil-scroll-count 0
+ "Hold last used prefix for `evil-scroll-up'
+and `evil-scroll-down'.
+Determine how many lines should be scrolled.
+Default value is 0 - scroll half the screen.")
+
+(evil-define-local-var evil-state nil
+ "The current Evil state.
+To change the state, use `evil-change-state'
+or call the state function (e.g., `evil-normal-state').")
+
+;; these may be used inside `evil-define-state'
+(evil-define-local-var evil-next-state nil
+ "The Evil state being switched to.")
+
+(evil-define-local-var evil-previous-state-alist nil
+ "For Each evil state the Evil state being switched from.")
+
+(evil-define-local-var evil-previous-state nil
+ "The Evil state being switched from.")
+
+(defvar evil-execute-in-emacs-state-buffer nil
+ "The buffer of the latest `evil-execute-in-emacs-state'.
+When this command is being executed the current buffer is stored
+in this variable. This is necessary in case the Emacs-command to
+be called changes the current buffer.")
+
+(evil-define-local-var evil-mode-line-tag nil
+ "Mode-Line indicator for the current state.")
+(put 'evil-mode-line-tag 'risky-local-variable t)
+
+(defvar evil-global-keymaps-alist nil
+ "Association list of keymap variables.
+Entries have the form (MODE . KEYMAP), where KEYMAP
+is the variable containing the keymap for MODE.")
+
+(defvar evil-local-keymaps-alist nil
+ "Association list of keymap variables that must be
+reinitialized in each buffer. Entries have the form
+\(MODE . KEYMAP), where KEYMAP is the variable containing
+the keymap for MODE.")
+
+(defvar evil-minor-mode-keymaps-alist nil
+ "Association list of Evil states to minor-mode keymap alists.
+Entries have the form (STATE . MODE-MAP-ALIST), where
+MODE-MAP-ALIST is an alist taking the form of
+`minor-mode-map-alist'.")
+
+(defvar evil-state-properties nil
+ "Specifications made by `evil-define-state'.
+Entries have the form (STATE . PLIST), where PLIST is a property
+list specifying various aspects of the state. To access a property,
+use `evil-state-property'.")
+
+(evil-define-local-var evil-mode-map-alist nil
+ "Association list of keymaps to use for Evil modes.
+Elements have the form (MODE . KEYMAP), with the first keymaps
+having higher priority.")
+
+(defvar evil-change-commands '(evil-change)
+ "Commands that wrap or replace `evil-change'.
+This list exists to apply an inconsistency with vim's change command
+to commands that wrap or redefine it. See emacs-evil/evil#916.")
+
+(defvar evil-transient-vars '(cua-mode transient-mark-mode select-active-regions)
+ "List of variables pertaining to Transient Mark mode.")
+
+(defvar evil-transient-vals nil
+ "Association list of old values for Transient Mark mode variables.
+Entries have the form (VARIABLE VALUE LOCAL), where LOCAL is
+whether the variable was previously buffer-local.")
+
+(defvar evil-no-display nil
+ "If non-nil, various Evil displays are inhibited.
+Use the macro `evil-without-display' to set this variable.")
+
+(defvar evil-type-properties nil
+ "Specifications made by `evil-define-type'.
+Entries have the form (TYPE . PLIST), where PLIST is a property
+list specifying functions for handling the type: expanding it,
+describing it, etc.")
+
+(defvar evil-interactive-alist nil
+ "Association list of Evil-specific interactive codes.")
+
+(evil-define-local-var evil-motion-marker nil
+ "Marker for storing the starting position of a motion.")
+
+(evil-define-local-var evil-this-type nil
+ "Current motion type.")
+
+(evil-define-local-var evil-this-type-modified nil
+ "Non-nil iff current motion type has been modified by the user.
+If the type has been modified, this variable contains the new
+type.")
+
+(evil-define-local-var evil-this-register nil
+ "Current register.")
+
+(defvar evil-last-=-register-input nil
+ "Most recent input from the `=' register. A string.")
+
+(defvar evil-this-macro nil
+ "Current macro register.")
+
+(evil-define-local-var evil-this-operator nil
+ "Current operator.")
+
+(evil-define-local-var evil-this-motion nil
+ "Current motion.")
+
+(evil-define-local-var evil-this-motion-count nil
+ "Current motion count.")
+
+;; In light of `evil-last-recorded-register' this should probably
+;; be renamed to `evil-last-executed-register' but that may break configs
+(defvar evil-last-register nil
+ "The last executed register.")
+
+(defvar evil-last-recorded-register nil
+ "The last recorded register.")
+
+(defvar evil-inhibit-operator nil
+ "Inhibit current operator.
+If an operator calls a motion and the motion sets this variable
+to t, the operator code is not executed.")
+
+(defvar evil-inhibit-operator-value nil
+ "This variable is used to transfer the value
+of `evil-inhibit-operator' from one local scope to another.")
+
+;; used by `evil-define-operator'
+(defvar evil-operator-range-beginning nil
+ "Beginning of `evil-operator-range'.")
+
+(defvar evil-operator-range-end nil
+ "End of `evil-operator-range'.")
+
+(defvar evil-operator-range-type nil
+ "Type of `evil-operator-range'.")
+
+(defvar evil-operator-range-motion nil
+ "Motion of `evil-operator-range'.")
+
+(defvar evil-operator-start-col nil
+ "Used to restore column (where possible) after an operator has moved it.")
+
+(defvar evil-restriction-stack nil
+ "List of previous restrictions.
+Using `evil-with-restriction' stores the previous values of
+`point-min' and `point-max' as a pair in this list.")
+
+(evil-define-local-var evil-markers-alist
+ '((?\( . evil-backward-sentence-begin)
+ (?\) . evil-forward-sentence-begin)
+ (?{ . evil-backward-paragraph)
+ (?} . evil-forward-paragraph)
+ (?' . evil-jump-backward-swap)
+ (?` . evil-jump-backward-swap)
+ (?< . evil-visual-beginning)
+ (?> . evil-visual-goto-end)
+ (?. . (lambda ()
+ (let (last-command)
+ (goto-last-change nil)))))
+ "Association list for markers.
+Entries have the form (CHAR . DATA), where CHAR is the marker's
+name and DATA is either a marker object as returned by `make-marker',
+a variable, a movement function, or a cons cell (STRING NUMBER),
+where STRING is a file path and NUMBER is a buffer position.
+The global value of this variable holds markers available from
+every buffer, while the buffer-local value holds markers available
+only in the current buffer.")
+
+(defconst evil-suppress-map (make-keymap)
+ "Full keymap disabling default bindings to `self-insert-command'.")
+(suppress-keymap evil-suppress-map t)
+
+(defvar evil-read-key-map (make-sparse-keymap)
+ "Keymap active during `evil-read-key'.
+This keymap can be used to bind some commands during the
+execution of `evil-read-key' which is usually used to read a
+character argument for some commands, e.g. `evil-replace'.")
+
+;; TODO: customize size of ring
+(defvar evil-repeat-ring (make-ring 10)
+ "A ring of repeat-informations to repeat the last command.")
+
+(defvar evil-recording-repeat nil
+ "Whether we are recording a repeat.")
+
+(defvar evil-recording-current-command nil
+ "Whether we are recording the current command for repeat.")
+
+(defvar evil-repeat-changes nil
+ "Accumulated buffer changes in reverse order for change-tracking commands.")
+
+(defvar evil-repeat-info nil
+ "Information accumulated during current repeat.")
+
+(defvar evil-repeat-buffer nil
+ "The buffer in which the repeat started.
+If the buffer is changed, the repeat is cancelled.")
+
+(defvar evil-repeat-pos nil
+ "The point position at the start of a change-tracking command.")
+
+(defvar evil-repeat-keys nil
+ "The keys that invoked the current command.")
+
+(defvar evil-last-repeat nil
+ "Information about the latest repeat command.
+This is a list of three elements (POINT COUNT UNDO-POINTER),
+where POINT is the position of point before the latest repeat,
+COUNT the count-argument of the latest repeat command and
+UNDO-POINTER the head of the undo-list before the last command
+has been repeated.")
+
+(defvar evil-repeat-count nil
+ "The explicit count when repeating a command.")
+
+(defvar evil-maybe-remove-spaces nil
+ "Flag to determine if newly inserted spaces should be removed.
+See the function `evil-maybe-remove-spaces'.")
+
+(evil-define-local-var evil-insert-count nil
+ "The explicit count passed to a command starting Insert or Replace state.")
+
+(evil-define-local-var evil-insert-vcount nil
+ "The information about the number of following lines the
+insertion should be repeated. This is list (LINE COLUMN COUNT)
+where LINE is the line-number where the original insertion
+started and COLUMN is either a number or function determining the
+column where the repeated insertions should take place. COUNT is
+number of repeats (including the original insertion).")
+
+(defvar evil-insert-skip-empty-lines nil
+ "Non-nil of the current insertion should not take place on
+ lines at which the insertion point is behind the end of the
+ line.")
+
+(evil-define-local-var evil-insert-lines nil
+ "Non-nil if the current insertion command is a line-insertion
+command o or O.")
+
+(evil-define-local-var evil-insert-repeat-info nil
+ "Repeat information accumulated during an insertion.")
+
+(evil-define-local-var evil-replace-alist nil
+ "Association list of characters overwritten in Replace state.
+The format is (POS . CHAR).")
+
+(evil-define-local-var evil-echo-area-message nil
+ "Previous value of `current-message'.")
+
+(defvar evil-write-echo-area nil
+ "If set to t inside `evil-save-echo-area', then the echo area
+is not restored.")
+
+(defvar evil-last-find nil
+ "A pair (FUNCTION . CHAR) describing the lastest character
+ search command.")
+
+(defvar evil-last-paste nil
+ "Information about the latest paste.
+This should be a list (CMD COUNT POINT BEG END FIRSTVISUAL) where
+CMD is the last paste-command (`evil-paste-before',
+`evil-paste-after' or `evil-visual-paste'), COUNT is the repeat
+count of the paste, POINT is the position of point before the
+paste, BEG end END are the region of the inserted
+text. FIRSTVISUAL is t if and only if the previous command was
+the first visual paste (i.e. before any paste-pop).")
+
+(evil-define-local-var evil-last-undo-entry nil
+ "Information about the latest undo entry in the buffer.
+This should be a pair (OBJ . CONS) where OBJ is the entry as an
+object, and CONS is a copy of the entry.")
+
+(evil-define-local-var evil-current-insertion nil
+ "Information about the latest insertion in insert state.
+This should be a pair (BEG . END) that describes the
+buffer-region of the newly inserted text.")
+
+(defvar evil-last-insertion nil
+ "The last piece of inserted text.")
+
+(defvar evil-last-small-deletion nil
+ "The last piece of deleted text.
+The text should be less than a line.")
+
+(defvar evil-was-yanked-without-register t
+ "Whether text being saved to the numbered-register ring was
+not deleted and not yanked to a specific register.")
+
+(defvar evil-paste-count nil
+ "The count argument of the current paste command.")
+
+(defvar evil--cursor-after nil
+ "Internal flag for gp & gP.")
+
+(defvar evil-temporary-undo nil
+ "When undo is disabled in current buffer.
+Certain commands depending on undo use this variable
+instead of `buffer-undo-list'.")
+
+(evil-define-local-var evil-undo-list-pointer nil
+ "Everything up to this mark is united in the undo-list.")
+
+(defvar evil-in-single-undo nil
+ "Set to non-nil if the current undo steps are connected.")
+
+(defvar evil-flash-timer nil
+ "Timer for flashing search results.")
+
+(defvar evil-search-prompt nil
+ "String to use for search prompt.")
+
+(defvar evil-search-forward-history nil
+ "History of forward searches.")
+
+(defvar evil-search-backward-history nil
+ "History of backward searches.")
+
+(defvar evil-inner-text-objects-map (make-sparse-keymap)
+ "Keymap for inner text objects.")
+
+(defvar evil-outer-text-objects-map (make-sparse-keymap)
+ "Keymap for outer text objects.")
+
+(defvar evil-window-map (make-sparse-keymap)
+ "Keymap for window-related commands.")
+
+(evil-define-local-var evil-input-method nil
+ "Input method used in Insert state and Emacs state.")
+
+;;; Visual state
+
+(evil-define-local-var evil-visual-beginning nil
+ "The beginning of the Visual selection, a marker.")
+
+(evil-define-local-var evil-visual-end nil
+ "The end of the Visual selection, a marker.")
+
+(evil-define-local-var evil-visual-point nil
+ "The position of point in Visual state, a marker.")
+
+(evil-define-local-var evil-visual-mark nil
+ "The position of mark in Visual state, a marker.")
+
+(evil-define-local-var evil-visual-selection nil
+ "The kind of Visual selection.
+This is a selection as defined by `evil-define-visual-selection'.")
+
+(evil-define-local-var evil-prev-visual-point nil
+ "The previous position of point in Visual state, a marker.")
+
+(evil-define-local-var evil-prev-visual-mark nil
+ "The previous position of mark in Visual state, a marker.")
+
+(evil-define-local-var evil-prev-visual-selection nil
+ "The previous kind of Visual selection.
+This is a selection as defined by `evil-define-visual-selection'.")
+
+;; we could infer the direction by comparing `evil-visual-mark'
+;; and `evil-visual-point', but destructive operations may
+;; displace the markers
+(evil-define-local-var evil-visual-direction 0
+ "Whether point follows mark in Visual state.
+Negative if point precedes mark, otherwise positive.
+See also the function `evil-visual-direction'.")
+
+(evil-define-local-var evil-visual-properties nil
+ "Property list of miscellaneous Visual properties.")
+
+(evil-define-local-var evil-visual-region-expanded nil
+ "Whether the region matches the Visual selection.
+That is, whether the positions of point and mark have been
+expanded to coincide with the selection's boundaries.
+This makes the selection available to functions acting
+on Emacs' region.")
+
+(defvar evil-transient-mouse-selection nil
+ "Whether the region selected by the mouse is discarded by the next command.
+By default, the region is not discarded. If non-nil, exit visual state
+immediately before the next command. To use the region selected by the mouse,
+execute a command which would usually enter visual state, such as
+\\[evil-visual-char] or \\[evil-visual-block].")
+
+(defvar evil--region-from-mouse nil
+ "Whether the region was set by the mouse.")
+
+(evil-define-local-var evil-visual-overlay nil
+ "Overlay for highlighting the Visual selection.
+Not used for blockwise selections, in which case
+see `evil-visual-block-overlays'.")
+
+(evil-define-local-var evil-visual-block-overlays nil
+ "Overlays for Visual Block selection, one for each line.
+They are reused to minimize flicker.")
+
+(defvar evil-visual-alist nil
+ "Association list of Visual selection functions.
+Elements have the form (NAME . FUNCTION).")
+
+(evil-define-local-var evil-visual-x-select-timer nil
+ "Timer for updating the X selection in visual state.")
+
+(defvar evil-visual-x-select-timeout 0.1
+ "Time in seconds for the update of the X selection.")
+
+(declare-function origami-open-all-nodes "ext:origami.el")
+(declare-function origami-close-all-nodes "ext:origami.el")
+(declare-function origami-toggle-node "ext:origami.el")
+(declare-function origami-open-node "ext:origami.el")
+(declare-function origami-open-node-recursively "ext:origami.el")
+(declare-function origami-close-node "ext:origami.el")
+
+(defvar evil-fold-list
+ `(((vdiff-mode)
+ :open-all vdiff-open-all-folds
+ :close-all vdiff-close-all-folds
+ :toggle ,(lambda () (call-interactively 'vdiff-toggle-fold))
+ :open ,(lambda () (call-interactively 'vdiff-open-fold))
+ :open-rec ,(lambda () (call-interactively 'vdiff-open-fold))
+ :close ,(lambda () (call-interactively 'vdiff-close-fold)))
+ ((vdiff-3way-mode)
+ :open-all vdiff-open-all-folds
+ :close-all vdiff-close-all-folds
+ :toggle ,(lambda () (call-interactively 'vdiff-toggle-fold))
+ :open ,(lambda () (call-interactively 'vdiff-open-fold))
+ :open-rec ,(lambda () (call-interactively 'vdiff-open-fold))
+ :close ,(lambda () (call-interactively 'vdiff-close-fold)))
+ ((hs-minor-mode)
+ :open-all hs-show-all
+ :close-all hs-hide-all
+ :toggle hs-toggle-hiding
+ :open hs-show-block
+ :open-rec nil
+ :close hs-hide-block)
+ ((hide-ifdef-mode)
+ :open-all show-ifdefs
+ :close-all hide-ifdefs
+ :toggle nil
+ :open show-ifdef-block
+ :open-rec nil
+ :close hide-ifdef-block)
+ ((outline-mode
+ outline-minor-mode
+ org-mode
+ markdown-mode)
+ :open-all show-all
+ :close-all ,(lambda ()
+ (with-no-warnings (hide-sublevels 1)))
+ :toggle outline-toggle-children
+ :open ,(lambda ()
+ (with-no-warnings
+ (show-entry)
+ (show-children)))
+ :open-rec show-subtree
+ :close hide-subtree)
+ ((origami-mode)
+ :open-all ,(lambda () (origami-open-all-nodes (current-buffer)))
+ :close-all ,(lambda () (origami-close-all-nodes (current-buffer)))
+ :toggle ,(lambda () (origami-toggle-node (current-buffer) (point)))
+ :open ,(lambda () (origami-open-node (current-buffer) (point)))
+ :open-rec ,(lambda () (origami-open-node-recursively (current-buffer) (point)))
+ :close ,(lambda () (origami-close-node (current-buffer) (point)))))
+ "Actions to be performed for various folding operations.
+
+The value should be a list of fold handlers, were a fold handler has
+the format:
+
+ ((MODES) PROPERTIES)
+
+MODES acts as a predicate, containing the symbols of all major or
+minor modes for which the handler should match. For example:
+
+ \\='((outline-minor-mode org-mode) ...)
+
+would match for either outline-minor-mode or org-mode, even though the
+former is a minor mode and the latter is a major.
+
+PROPERTIES specifies possible folding actions and the functions to be
+applied in the event of a match on one (or more) of the MODES; the
+supported properties are:
+
+ - `:open-all'
+ Open all folds.
+ - `:close-all'
+ Close all folds.
+ - `:toggle'
+ Toggle the display of the fold at point.
+ - `:open'
+ Open the fold at point.
+ - `:open-rec'
+ Open the fold at point recursively.
+ - `:close'
+ Close the fold at point.
+
+Each value must be a function. A value of `nil' will cause the action
+to be ignored for that respective handler. For example:
+
+ `((org-mode)
+ :close-all nil
+ :open ,(lambda ()
+ (show-entry)
+ (show-children))
+ :close hide-subtree)
+
+would ignore `:close-all' actions and invoke the provided functions on
+`:open' or `:close'.")
+
+;;; Ex
+
+(define-obsolete-variable-alias 'evil-ex-map 'evil-ex-shortcut-map "1.15.0")
+(defvar evil-ex-shortcut-map (make-sparse-keymap)
+ "Keymap for Ex.
+Key sequences bound in this map are immediately executed.")
+
+;; Intentionally does not inherit from `minibuffer-local-map', as users
+;; are encouraged to instead set this as the parent of that keymap.
+(defvar evil-command-line-map (make-sparse-keymap)
+ "Keymap used for the various Evil command-lines.
+Modifying this keymap corresponds to using the \":cmap\" Vim command.
+See `evil-ex-completion-map' and `evil-ex-search-keymap' which inherit
+from this keymap.")
+
+(defvar evil-ex-completion-map (make-sparse-keymap)
+ "Keymap for Ex.")
+
+(defvar evil-ex-initial-input nil
+ "Additional initial content of the Ex command line.
+This content of this variable is appended to the Ex command line
+when Ex is started interactively.")
+
+(defvar evil-ex-history nil
+ "History of Ex commands.")
+
+(define-obsolete-variable-alias
+ 'evil-ex-current-buffer 'evil-ex-original-buffer "1.15.0")
+(defvar evil-ex-original-buffer nil
+ "Buffer that was current when the Evil command line was started.")
+
+(defvar evil-ex-point nil
+ "The point position when the Ex command was called.")
+
+(defvar evil-called-from-ex-p nil
+ "Non-nil if a command is currently being called as an Ex command.")
+
+(defvar evil-ex-range nil
+ "The current range of the Ex command.")
+
+(defvar evil-ex-bang nil
+ "The \"!\" argument of the current Ex command.")
+
+(defvar evil-ex-argument nil
+ "The current argument of the Ex command.")
+
+(defvar evil-previous-shell-command nil
+ "The last shell command.")
+
+;; Eval
+(defvar evil-eval-history nil
+ "History of eval input, from the `=' register.")
+
+(defvar evil-eval-map (make-sparse-keymap)
+ "Keymap for eval input.")
+
+;; Searching
+(defvar evil-ex-search-history nil
+ "The history for the search command.")
+
+(defvar evil-ex-search-direction nil
+ "The direction of the current search, either `forward' or `backward'.")
+
+(defvar evil-ex-search-count nil
+ "The count of the current search.")
+
+(defvar evil-ex-search-start-point nil
+ "The point where the search started.")
+
+(defvar evil-ex-search-overlay nil
+ "The overlay for the current search result.")
+
+(defvar evil-ex-search-pattern nil
+ "The last search pattern.")
+
+(defvar evil-ex-search-offset nil
+ "The last search offset.")
+
+(defvar evil-ex-search-match-beg nil
+ "The beginning position of the last match.")
+
+(defvar evil-ex-search-match-end nil
+ "The end position of the last match.")
+
+(defvar evil-ex-substitute-pattern nil
+ "The last substitute pattern.")
+
+(defvar evil-ex-substitute-replacement nil
+ "The last substitute replacement.")
+
+(defvar evil-ex-substitute-flags nil
+ "The last substitute flags.")
+
+(defvar evil-ex-substitute-current-replacement nil
+ "The actual replacement.")
+
+(defvar evil-ex-last-was-search nil
+ "Non-nil if the previous was a search.
+Otherwise the previous command is assumed as substitute.")
+
+;; The lazy-highlighting framework
+(evil-define-local-var evil-ex-active-highlights-alist nil
+ "An alist of currently active highlights.")
+
+(evil-define-local-var evil-ex-hl-update-timer nil
+ "Time used for updating highlights.")
+
+(defvar evil-ex-search-keymap (make-sparse-keymap)
+ "Keymap used in ex-search-mode.")
+
+(defcustom evil-want-empty-ex-last-command t
+ "Whether to default to evil-ex-previous-command at empty ex prompt."
+ :type 'boolean
+ :group 'evil)
+
+(defconst evil-version
+ (eval-when-compile
+ (with-temp-buffer
+ (let ((dir (file-name-directory (or load-file-name
+ byte-compile-current-file))))
+ ;; git repository
+ (if (and (file-exists-p (concat dir "/.git"))
+ (ignore-errors
+ (zerop (call-process "git" nil '(t nil) nil
+ "rev-parse"
+ "--short" "HEAD"))))
+ (progn
+ (goto-char (point-min))
+ (concat "evil-git-"
+ (buffer-substring (point-min)
+ (line-end-position))))
+ ;; no repo, use plain version
+ "1.15.0"))))
+ "The current version of Evil")
+
+(defcustom evil-want-integration t
+ "Whether to load evil-integration.el.
+This variable must be set before Evil is loaded."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-want-keybinding t
+ "Whether to load evil-keybindings.el.
+
+This loads a set of keybindings for evil in other modes as well as
+setting the initial evil state in those modes.
+
+This variable must be set before evil is loaded."
+ :type 'boolean
+ :group 'evil)
+
+(defcustom evil-want-minibuffer nil
+ "Whether to enable Evil in minibuffer(s)."
+ :type 'boolean
+ :group 'evil
+ :set #'(lambda (sym value)
+ (set-default sym value)
+ (if value
+ (add-hook 'minibuffer-setup-hook 'evil-initialize)
+ (remove-hook 'minibuffer-setup-hook 'evil-initialize))))
+
+(defun evil--redo-placeholder (_count)
+ (user-error "Customize `evil-undo-system' for redo functionality."))
+
+(defvar evil-undo-function #'undo
+ "Function to be used by `evil-undo'.
+Customized via `evil-undo-system'.")
+
+(defvar evil-redo-function #'evil--redo-placeholder
+ "Function to be used by `evil-redo'.
+Customized via `evil-undo-system'.")
+
+(defun evil-set-undo-system (system)
+ "Set `evil-undo-function' and `evil-redo-function' by SYSTEM."
+ (cond
+ ((not system)
+ (setq evil-undo-function #'undo
+ evil-redo-function #'evil--redo-placeholder))
+ ((eq system 'undo-redo)
+ (setq evil-undo-function #'undo-only
+ evil-redo-function #'undo-redo))
+ ((eq system 'undo-tree)
+ (setq evil-undo-function 'undo-tree-undo
+ evil-redo-function 'undo-tree-redo))
+ ((eq system 'undo-fu)
+ (setq evil-undo-function 'undo-fu-only-undo
+ evil-redo-function 'undo-fu-only-redo))
+ (t (error "Unknown undo system `%s'" system))))
+
+(defcustom evil-undo-system nil
+ "Undo system Evil should use.
+If equal to `undo-tree' or `undo-fu', those packages must be
+installed. If equal to `undo-tree', `undo-tree-mode' must also be
+activated. If equal to `undo-redo', Evil uses commands natively
+available in Emacs 28."
+ :type '(choice (const :tag "Vanilla undo" nil)
+ (const undo-redo)
+ (const undo-tree)
+ (const undo-fu))
+ :group 'evil
+ :set #'(lambda (sym value)
+ (evil-set-undo-system value)
+ (set-default sym value)))
+
+(defcustom evil-visual-update-x-selection-p t
+ "Whether to update the X PRIMARY selection with the current visual region."
+ :type 'boolean
+ :group 'evil)
+
+(defun evil-version ()
+ (interactive)
+ (message "Evil version %s" evil-version))
+
+(provide 'evil-vars)
+
+;;; evil-vars.el ends here
diff --git a/.config/emacs/lisp/evil/evil.el b/.config/emacs/lisp/evil/evil.el
new file mode 100644
index 0000000..757a564
--- /dev/null
+++ b/.config/emacs/lisp/evil/evil.el
@@ -0,0 +1,158 @@
+;;; evil.el --- Extensible vi layer -*- lexical-binding: t; -*-
+
+;; The following list of authors was kept up to date until the beginning of
+;; 2017, when evil moved under new maintainers. For authors since then, please
+;; consult the git logs.
+
+;; Alessandro Piras <laynor at gmail.com>
+;; Alexander Baier <alexander.baier at mailbox.org>
+;; Antono Vasiljev <antono.vasiljev at gmail.com>
+;; Bailey Ling <bling at live.ca>
+;; Barry O'Reilly <gundaetiapo at gmail.com>
+;; Christoph Lange <langec at web.de>
+;; Daniel Reiter <danieltreiter at gmail.com>
+;; Eivind Fonn <evfonn at gmail.com>
+;; Emanuel Evans <emanuel.evans at gmail.com>
+;; Eric Siegel <siegel.eric at gmail.com>
+;; Eugene Yaremenko <w3techplayground at gmail.com>
+;; Frank Fischer <frank-fischer at shadow-soft.de>
+;; Frank Terbeck <ft at bewatermyfriend.org>
+;; Gordon Gustafson <gordon3.14 at gmail.com>
+;; Herbert Jones <jones.herbert at gmail.com>
+;; Jonas Bernoulli <jonas at bernoul.li>
+;; Jonathan Claggett <jclaggett at lonocloud.com>
+;; José A. Romero L. <escherdragon at gmail.com>
+;; Justin Burkett <justin at burkett.cc>
+;; Lars Andersen <expez at expez.com>
+;; Lintaro Ina <tarao.gnn at gmail.com>
+;; Lukasz Wrzosek <wrzoski at mail.com>
+;; Marian Schubert <maio at netsafe.cz>
+;; Matthew Malcomson <>
+;; Michael Markert <markert.michael at googlemail.com>
+;; Mike Gerwitz <mikegerwitz at gnu.org>
+;; Nikolai Weibull <now at bitwi.se>
+;; phaebz <phaebz at gmail.com>
+;; ralesi <scio62 at gmail.com>
+;; Rodrigo Setti <rodrigosetti at gmail.com>
+;; Sanel Zukan <sanelz at gmail.com>
+;; Sarah Brofeldt <sarah at thinkmonster.(none)>
+;; Simon Hafner <hafnersimon at gmail.com>
+;; Stefan Wehr <mail at stefanwehr.de>
+;; Sune Simonsen <sune.simonsen at jayway.com>
+;; Thomas Hisch <thomas at opentech.at>
+;; Tim Harper <timcharper at gmail.com>
+;; Tom Willemse <tom at ryuslash.org>
+;; Trevor Murphy <trevor.m.murphy at gmail.com>
+;; Ulrich Müller <ulm at gentoo.org>
+;; Vasilij Schneidermann <v.schneidermann at gmail.com>
+;; Vegard Øye <vegard_oye at hotmail.com>
+;; Winfred Lu <winfred.lu at gmail.com>
+;; Wolfgang Jenkner <wjenkner at inode.at>
+;; Xiao Hanyu <xiaohanyu1988 at gmail.com>
+;; York Zhao <yzhao at telecor.com>
+
+;; The following line is included for NonGNU ELPA's build script:
+;; Maintainer: Tom Dalziel <tom.dalziel@gmail.com>
+
+;; Maintainers: The emacs-evil team. <https://github.com/orgs/emacs-evil/people>
+;; To get in touch, please use the bug tracker or the
+;; mailing list (see below).
+;; Created: 2011-03-01
+;; Version: 1.15.0
+;; Package-Requires: ((emacs "24.1") (cl-lib "0.5") (goto-chg "1.6") (nadvice "0.3"))
+;; Keywords: emulations
+;; URL: https://github.com/emacs-evil/evil
+;; Repository: https://github.com/emacs-evil/evil.git
+;; EmacsWiki: http://www.emacswiki.org/emacs/Evil
+;; Bug tracker: https://github.com/emacs-evil/evil/issues
+;; If you have bug reports, suggestions or patches, please
+;; create an issue at the bug tracker (open for everyone).
+;; Other discussions (tips, extensions) go to the mailing list.
+;; Mailing list: <implementations-list at lists.ourproject.org>
+;; Subscribe: http://tinyurl.com/implementations-list
+;; Newsgroup: nntp://news.gmane.org/gmane.emacs.vim-emulation
+;; Archives: http://dir.gmane.org/gmane.emacs.vim-emulation
+;; You don't have to subscribe to post; we usually reply
+;; within a few days and CC our replies back to you.
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Evil is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Evil. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Evil is an extensible vi layer for Emacs. It emulates the main
+;; features of Vim, and provides facilities for writing custom
+;; extensions.
+;;
+;; Evil lives in a Git repository. To obtain Evil, do
+;;
+;; git clone git://github.com/emacs-evil/evil.git
+;;
+;; Move Evil to ~/.emacs.d/evil (or somewhere else in the `load-path').
+;; Then add the following lines to ~/.emacs:
+;;
+;; (add-to-list 'load-path "~/.emacs.d/evil")
+;; (require 'evil)
+;; (evil-mode 1)
+;;
+;; Evil requires undo-redo (Emacs 28), undo-fu or undo-tree for redo
+;; functionality. Otherwise, Evil uses regular Emacs undo.
+;;
+;; https://codeberg.org/ideasman42/emacs-undo-fu
+;; https://melpa.org/#/undo-fu
+;; https://gitlab.com/tsc25/undo-tree
+;; https://elpa.gnu.org/packages/undo-tree.html
+;;
+;; Evil requires `goto-last-change' and `goto-last-change-reverse'
+;; function for the corresponding motions g; g, as well as the
+;; last-change-register `.'. One package providing these functions is
+;; goto-chg.el:
+;;
+;; https://github.com/emacs-evil/goto-chg
+;; https://melpa.org/#/goto-chg
+;; https://elpa.nongnu.org/nongnu/goto-chg.html
+;;
+;; Without this package the corresponding motions will raise an error.
+
+;;; Code:
+
+(require 'evil-vars)
+(require 'evil-common)
+(require 'evil-core)
+(require 'evil-states)
+(require 'evil-repeat)
+(require 'evil-macros)
+(require 'evil-search)
+(require 'evil-ex)
+(require 'evil-types)
+(require 'evil-commands)
+(require 'evil-jumps)
+(require 'evil-maps)
+
+(when evil-want-integration
+ (require 'evil-integration))
+
+(when evil-want-keybinding
+ (require 'evil-keybindings))
+
+(run-hooks 'evil-after-load-hook)
+
+(provide 'evil)
+
+;;; evil.el ends here
diff --git a/.config/emacs/lisp/evil/scripts/evil-extract-docstrings b/.config/emacs/lisp/evil/scripts/evil-extract-docstrings
new file mode 100755
index 0000000..55dbd79
--- /dev/null
+++ b/.config/emacs/lisp/evil/scripts/evil-extract-docstrings
@@ -0,0 +1,41 @@
+#!/usr/bin/env -S emacs --script
+
+(setq cur-path (file-name-directory load-file-name))
+
+(add-to-list 'load-path (expand-file-name ".." cur-path))
+(require 'evil)
+(require 'evil-digraphs)
+(require 'json)
+(require 'help)
+
+(defun mark-command-keys (string)
+ "Mark key bindings in STRING with the \":kbd:\" Sphinx role."
+ (when string
+ (cl-loop
+ for prev = 0 then pos until (>= prev (length string))
+ for pos = (next-single-property-change prev 'face string (length string))
+ concat
+ (let ((s (substring string prev pos)))
+ (if (eq (get-text-property prev 'face string) 'help-key-binding)
+ (format ":kbd:`%s`" s)
+ s)))))
+
+(let (vars)
+ (mapatoms
+ (lambda (sym)
+ (when (string-prefix-p "evil-" (symbol-name sym))
+ (let ((default (eval (car (get sym 'standard-value)))))
+ (push `(,sym (default . ,(cond
+ ((consp default) (format "%S" default))
+ ((symbolp default) (symbol-name default))
+ (t default)))
+ (local . ,(local-variable-if-set-p sym))
+ (default-type . ,(type-of default))
+ (var-docstring . ,(mark-command-keys (documentation-property sym 'variable-documentation)))
+ (fn-docstring . ,(ignore-errors (mark-command-keys (documentation sym))))
+ (arglist . ,(help-function-arglist sym))
+ (functionp . ,(functionp sym))
+ (macrop . ,(macrop sym)))
+ vars)))))
+ (with-temp-file (expand-file-name "../doc/docstringdb.json" cur-path)
+ (insert (json-encode vars))))
diff --git a/.config/emacs/lisp/evil/scripts/evil-release-stable b/.config/emacs/lisp/evil/scripts/evil-release-stable
new file mode 100755
index 0000000..c075903
--- /dev/null
+++ b/.config/emacs/lisp/evil/scripts/evil-release-stable
@@ -0,0 +1,52 @@
+#!/usr/bin/env ruby
+
+# Copyright (c) 2015 Frank Fischer <frank-fischer@shadow-soft.de>
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>
+
+
+# This script releases a new (minor) stable release given that some
+# new commits on the stable branch since the last tag exist.
+
+Dir.chdir File.dirname(__FILE__)
+
+def die(msg = "Failed")
+ STDERR.puts msg
+ exit 1
+end
+
+def run(cmd)
+ system(cmd) or die(cmd)
+end
+
+run 'hg pull'
+run 'hg update -r stable'
+
+tag = `hg tags`.split("\n").select{|line| line =~ /^\d+\.\d+\.\d+/}.map do |line|
+ tag, rev = line.split
+ major, minor, tiny = tag.split(/\./).map(&:to_i)
+ [major, minor, tiny, rev[/\d+/].to_i]
+end.max
+
+tag or die 'No tagged revision found'
+
+stable = `hg log -r 'branch(stable) and not file("../.hgtags") and not ..tag("re:\\d+\\.\\d+\\.\\d+")' | wc -l`.to_i != 0
+
+if stable
+ new_tag = "#{tag[0]}.#{tag[1]}.#{tag[2]+1}"
+ run "make -C .. nversion VERSION='#{new_tag}'"
+ run "hg commit -m 'update version to #{new_tag}'"
+ run "hg tag -m 'version #{new_tag}' -r stable #{new_tag}"
+ run "hg push -r stable"
+end
diff --git a/.config/emacs/lisp/evil/scripts/evilupdate b/.config/emacs/lisp/evil/scripts/evilupdate
new file mode 100755
index 0000000..27e832b
--- /dev/null
+++ b/.config/emacs/lisp/evil/scripts/evilupdate
@@ -0,0 +1,177 @@
+#!/usr/bin/emacs --script
+;;; evilupate.el -- Publishing script for Evil
+
+;;; Header:
+
+;; This file is not part of Emacs
+
+;; Author: Frank Fischer <frank-fischer@shadow-soft.de>
+;; Maintainer: Frank Fischer <frank-fischer@shadow-soft.de>
+;; Version: 1.0
+;; Package-Requires: ((emacs "24.3") (s "1.9.0") (f "0.17.2") yaoddmuse)
+
+;; The contents of this file are subject to the GPL License, Version 3.0.
+
+;; Copyright (C) 2015, 2016, Frank Fischer
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is a small script to update Evil's version at certain places:
+;;
+;; - topic of the IRC channel #evil-mode in irc.libera.chat
+;; - EmacsWiki page
+;; - header of all source files
+;; - the ELPA package file
+;;
+;; The script should be invoked with the new version string
+;;
+;; evil-update.el 1.2.3
+;;
+
+;;; Code:
+
+(package-initialize)
+
+(require 'f)
+(require 'erc)
+(require 'yaoddmuse)
+
+(defconst evilupdate-irc-nick "lyrobot")
+(defconst evilupdate-irc-channel "#evil-mode")
+(defconst evilupdate-irc-topic
+ "Evil = Extensible vi layer for Emacs | Current version: VERSION | https://github.com/emacs-evil/evil | If you don't get an answer here, please use the mailing-list implementations-list@lists.ourproject.org")
+(defconst evilupdate-wiki-page "Evil")
+(defvar evilupdate-version "1.0.0")
+(defvar evilupdate-done nil)
+
+(defun evilupdate-wait ()
+ "Wait until `evilupdate-done' is set to t."
+ (while (not evilupdate-done)
+ (sleep-for 1))
+ (setq evilupdate-done nil))
+
+(defun evilupdate-done ()
+ "Set `evilupdate-done' to t to stop the corresponding `evilupdate-wait'."
+ (setq evilupdate-done t))
+
+(defun evilupdate-update-irc ()
+ "Update the topic of the IRC channel."
+ (let ((erc-nick evilupdate-irc-nick)
+ (erc-autojoin-channels-alist nil)
+ (auth-sources nil))
+ (erc-tls :server "irc.libera.chat" :port "6697" :nick evilupdate-irc-nick)
+ (add-hook 'erc-join-hook
+ (lambda ()
+ (let (case-fold-search)
+ (erc-set-topic (replace-regexp-in-string "VERSION"
+ evilupdate-version
+ evilupdate-irc-topic
+ nil t)))
+ (erc-quit-server "")
+ (sleep-for 5)
+ (evilupdate-done)))
+ (erc-join-channel evilupdate-irc-channel)
+ (evilupdate-wait)))
+
+(defun evilupdate-wiki-trace (page-buffer-name)
+ "Callback for updating the EmacsWiki page in buffer PAGE-BUFFER-NAME."
+ (with-current-buffer page-buffer-name
+ (goto-char (point-min))
+ (when (re-search-forward "Current stable version: \\*\\*\\([^*]*\\)\\*\\*")
+ (goto-char (match-beginning 1))
+ (delete-region (match-beginning 1) (match-end 1))
+ (insert evilupdate-version)
+ (yaoddmuse-post-buffer (current-buffer) evilupdate-version nil)
+ (evilupdate-done))))
+
+(unless (require 'nadvice nil t)
+ (defadvice yaoddmuse-display-page (around evilupdate activate)
+ (evilupdate-wiki-trace (ad-get-arg 0))))
+
+(defun evilupdate-update-emacswiki ()
+ "Update the version information on the EmacsWiki page."
+ (setq yaoddmuse-wikis
+ '(("EmacsWiki" "https://www.emacswiki.org/emacs" utf-8 "uihnscuskc=1;")))
+ (when (featurep 'nadvice)
+ (advice-add 'yaoddmuse-display-page :after 'evilupdate-wiki-trace))
+ (yaoddmuse-edit "EmacsWiki" evilupdate-wiki-page t)
+ (evilupdate-wait))
+
+(defun evilupdate-update-regexp (file regexp)
+ "Update version tag in FILE.
+The version tag is defined by the REGEXP, in particular by the first
+match group."
+ (find-file file)
+ (goto-char (point-min))
+ (when (re-search-forward regexp nil t)
+ (goto-char (match-beginning 1))
+ (delete-region (match-beginning 1) (match-end 1))
+ (insert evilupdate-version)
+ (save-buffer)))
+
+(defun evilupdate-update-files ()
+ "Replace version comments in all source files."
+ (dolist (file (f-glob "*.el"))
+ (evilupdate-update-regexp file ";;\\s-*Version:\\s-*\\([^\n]+\\)")))
+
+(defun evilupdate-update-pkg ()
+ "Replace version in package file."
+ (evilupdate-update-regexp "evil-pkg.el" "\"evil\"[ \t\n\r]*\"\\([^\"]+\\)\""))
+
+(defun evilupdate-update-var ()
+ "Replace version in `evil-version' variable."
+ (evilupdate-update-regexp
+ "evil-vars.el"
+ "t \"\\([^\"]*\\)\"[) \n\r\t]*\"The current version of Evil"))
+
+(defun evilupdate-update-news ()
+ "Send an posting to the mailing list."
+ (shell-command (concat "thunderbird -compose \"newsgroups=gmane.emacs.vim-emulation,preselectid=id2,subject='[ANN] Evil version " evilupdate-version " released',body='"
+ "Evil version " evilupdate-version " has been released.
+
+The stable version can be installed from MELPA stable [1] and NonGNU ELPA [2].
+The latest development version is available from MELPA [3].
+
+The Evil developers.
+
+[1] http://stable.melpa.org
+[2] https://elpa.nongnu.org/nongnu/evil.html
+[3] http://melpa.org
+'\"")))
+
+(defun evilupdate-update (version nonews)
+ "Update Evil to VERSION.
+If NONEWS is non-nil do not post a message to the newsgroup."
+ (setq evilupdate-cnt 0)
+ (setq evilupdate-version version)
+ (evilupdate-update-emacswiki)
+ (evilupdate-update-irc)
+ (evilupdate-update-files)
+ (evilupdate-update-pkg)
+ (evilupdate-update-var)
+ (unless nonews (evilupdate-update-news)))
+
+(cond
+ ((= (length argv) 2)
+ (unless (equal (car argv) "nonews")
+ (user-error "Usage: evilupdate.el [-n] VERSION"))
+ (evilupdate-update (cadr argv) t))
+ ((= (length argv) 1)
+ (evilupdate-update (cadr argv)))
+ (t
+ (user-error "Usage: evilupdate.el [-n] VERSION")))
+
+;;; evilupdate.el ends here