;;; 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 recored 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 or 'post depending 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.
;; Those functions are called in different situations before and after
;; the execution of a command. Each function should take one argument
;; which can be either 'pre, 'post, 'pre-operator or 'post-operator
;; specifying when the repeat function has been called. If the command
;; is a usual command the function is called with 'pre before the
;; command is executed and with 'post after the command has been
;; executed.
;;
;; 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:
; ... minibuffer activated
;; called from `evil-normal-state-exit-hook'
;; called from `pre-command-hook'
;; called from `post-command-hook'
;; called from the `after-change-functions' hook
;; 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'?
;; Keep the compiler happy - this is a buffer local var
;; TODO: the same issue concering disabled undos as for `evil-paste-pop'
;;; evil-repeat.el ends here