223 lines
6.8 KiB
EmacsLisp
223 lines
6.8 KiB
EmacsLisp
;;; vim.el --- a VIM-emulation for Emacs
|
|
|
|
;; Copyright (C) 2009, 2010 Frank Fischer
|
|
|
|
;; Author: Frank Fischer <frank.fischer@mathematik.tu-chemnitz.de>,
|
|
;; Maintainer: Frank Fischer <frank.fischer@mathematik.tu-chemnitz.de>,
|
|
;; URL: http://www.emacswiki.org/emacs/VimMode
|
|
;; License: GPLv2 or later, as described below under "License"
|
|
;; Compatibility: Emacs 22, 23, XEmacs 21.4
|
|
;; Version: 0.3.0
|
|
;; Keywords: emulation, vim
|
|
;; Human-Keywords: vim, emacs
|
|
;;
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
;;; Acknowledgements:
|
|
|
|
;; This package contains code from several other packages:
|
|
;;
|
|
;; - rect-mark.el
|
|
;; - viper
|
|
;; - vimpulse.el
|
|
;; - windmove.el
|
|
;;
|
|
;; Special thanks go to the authors of those packages.
|
|
|
|
;;; Commentary:
|
|
|
|
;; A simple VIM-mode for Emacs
|
|
;;
|
|
;; This project is in a VERY early development state and many function
|
|
;; have not been implemented yet.
|
|
;;
|
|
;; If you want to try, open this file in your Emacs and evaluate the buffer.
|
|
;; The mode can be activated by 'M-x vim-mode'.
|
|
;;
|
|
;; Don't forget to disable Viper if you want to try vim-mode.
|
|
;;
|
|
;; The project is divided into many files. Each file implements some
|
|
;; almost-independent feature. If you want to learn how to implement
|
|
;; new commands or motions, look at the files vim-commands.el and
|
|
;; vim-motions.el.
|
|
;;
|
|
;; Here is a short description of the contents of each file:
|
|
;;
|
|
;; - vim.el: This file just sets up the mode and loads the other files.
|
|
;;
|
|
;; - vim-compat.el: Compatibility layer for different Emacsen.
|
|
;;
|
|
;; - vim-keymap.el: A few functions for defining keymaps for vim-mode.
|
|
;;
|
|
;; - vim-vim.el: This file contains the macros for defining motions
|
|
;; and commands as well as some utility functions for
|
|
;; calling them.
|
|
;;
|
|
;; - vim-modes.el: Each VIM-mode (normal-mode, insert-mode, ...) corresponds
|
|
;; to an Emacs-minor-mode. This file contains some macros and
|
|
;; functions to define new vim-modes in this context.
|
|
;;
|
|
;; - vim-insert-mode.el: The implementation of insert-mode.
|
|
;;
|
|
;; - vim-normal-mode.el: The implementation of normal-mode.
|
|
;;
|
|
;; - vim-visual-mode.el: The implementation of visual-mode.
|
|
;;
|
|
;; - vim-ex-mode.el: The implementation of ex-mode.
|
|
;;
|
|
;; - vim-commands.el: The implementations of commands like 'delete',
|
|
;; 'yank', 'paste' and so on.
|
|
;;
|
|
;; - vim-motions.el: The implementations of motion commands like 'h',
|
|
;; 'i', 'j', 'k', 'f', 'w', ...
|
|
;;
|
|
;; - vim-scroll.el: The implementation of scrolling commands like
|
|
;; 'zz', 'Ctrl-F'.
|
|
;;
|
|
;; - vim-window-el: The implementation of window commands like 'C-w s'.
|
|
;;
|
|
;; - vim-ex-commands.el: The implementations of commands like ':edit'
|
|
;; or ':buffer'.
|
|
;;
|
|
;; - vim-search.el: The implementation of '/' and ':substitute'.
|
|
;;
|
|
;; - vim-undo.el: Some variables and functions for undo/redo.
|
|
;;
|
|
;; - vim-maps.el: The definition of the basic keymaps. This file
|
|
;; connects the keymaps with the commands and motions
|
|
;; defined in vim-commands.el and vim-motions.el.
|
|
;;
|
|
;; TODO:
|
|
;;
|
|
;; HAVE:
|
|
;; - framework for keymaps, motions, commands and command-mappings
|
|
;; - insert-mode, normal-mode, visual-mode and ex-mode
|
|
;; - simple motions
|
|
;; - deletion, yank, paste, change, replace
|
|
;; - undo/redo
|
|
;; - repeat
|
|
;;
|
|
;; MISSING:
|
|
;; - better Emacs integration (modes, buffer local variables, ...)
|
|
;; - text objects
|
|
;; - several commands
|
|
;; - marks and register
|
|
;; - ...
|
|
|
|
;; - several calls 'looking-back' may be inefficient
|
|
|
|
;;; Code:
|
|
|
|
(eval-when-compile
|
|
(require 'cl))
|
|
|
|
(defgroup vim-mode nil
|
|
"A VIM emulation mode."
|
|
:group 'emulations)
|
|
|
|
(defcustom vim:default-initial-mode
|
|
'normal
|
|
"The default initial vim sub-mode."
|
|
:type '(symbol :tag "vim-mode start mode")
|
|
:group 'vim-mode)
|
|
|
|
(defcustom vim:initial-modes
|
|
'((debugger-mode . window)
|
|
(compilation-mode . window)
|
|
(grep-mode . window)
|
|
(gud-mode . window)
|
|
(sldb-mode . window)
|
|
(slime-repl-mode . window)
|
|
(reftex-select-bib-mode . window)
|
|
(completion-list-mode . window)
|
|
(help-mode . motion)
|
|
(Info-mode . motion))
|
|
"Associated list of (major-mode . vim:mode) which specifies the
|
|
vim sub-mode in which vim-mode should start when a buffer with the
|
|
given major-mode is created."
|
|
:type '(repeat (cons (symbol :tag "major mode") (symbol :tag "vim-mode start mode")))
|
|
:group 'vim-mode)
|
|
|
|
|
|
(defmacro vim:deflocalvar (name &rest args)
|
|
"Defines a buffer-local variable."
|
|
(declare (indent defun))
|
|
`(progn
|
|
(defvar ,name ,@args)
|
|
(make-variable-buffer-local ',name)))
|
|
(font-lock-add-keywords 'emacs-lisp-mode '("vim:deflocalvar"))
|
|
|
|
(defvar vim:emulation-mode-alist nil
|
|
"List of all keymaps used by some modes.")
|
|
|
|
(let ((load-path (cons (expand-file-name ".") load-path)))
|
|
(eval-when-compile
|
|
(load "vim-compat")
|
|
(load "vim-keymap")
|
|
(load "vim-modes")
|
|
(load "vim-vim")
|
|
(load "vim-normal-mode")
|
|
(load "vim-insert-mode")
|
|
(load "vim-visual-mode")
|
|
(load "vim-commands")
|
|
(load "vim-motions")
|
|
(load "vim-scroll")
|
|
(load "vim-window")
|
|
(load "vim-undo")
|
|
(load "vim-ex")
|
|
(load "vim-ex-commands")
|
|
(load "vim-search")
|
|
(load "vim-maps"))
|
|
|
|
(require 'vim-compat)
|
|
(require 'vim-keymap)
|
|
(require 'vim-modes)
|
|
(require 'vim-vim)
|
|
(require 'vim-normal-mode)
|
|
(require 'vim-insert-mode)
|
|
(require 'vim-visual-mode)
|
|
(require 'vim-commands)
|
|
(require 'vim-motions)
|
|
(require 'vim-scroll)
|
|
(require 'vim-window)
|
|
(require 'vim-undo)
|
|
(require 'vim-ex)
|
|
(require 'vim-ex-commands)
|
|
(require 'vim-search)
|
|
(require 'vim-maps))
|
|
|
|
(define-minor-mode vim-local-mode
|
|
"VIM emulation mode."
|
|
:lighter " VIM"
|
|
:init-value nil
|
|
:global nil
|
|
|
|
(if vim-local-mode
|
|
(progn
|
|
(make-local-variable 'vim:emulation-mode-alist)
|
|
(vim:initialize-keymaps t))
|
|
(progn
|
|
(vim:initialize-keymaps nil)
|
|
(setq global-mode-string
|
|
(delq 'vim:mode-string global-mode-string ))
|
|
(vim:activate-mode nil))))
|
|
|
|
(define-globalized-minor-mode vim-mode vim-local-mode vim:initialize)
|
|
|
|
(defun vim:initialize ()
|
|
(unless (vim:minibuffer-p)
|
|
(let ((mode (cdr (or (assoc major-mode vim:initial-modes)
|
|
(cons t vim:default-initial-mode)))))
|
|
(when mode
|
|
(setq vim:active-mode nil)
|
|
(vim-local-mode 1)
|
|
(vim:intercept-ESC-mode 1)
|
|
(vim:activate-mode mode)
|
|
(unless (memq 'vim:mode-string global-mode-string)
|
|
(setq global-mode-string
|
|
(append '("" vim:mode-string) (cdr global-mode-string))))))))
|
|
|
|
|
|
(provide 'vim)
|
|
|
|
;;; vim.el ends here
|