├── bin └── vim ├── plugin ├── vimacs │ └── vim ├── tab-indent.vim └── vimacs.vim ├── INSTALL ├── doc ├── tab-indent.txt └── vimacs.txt └── README.md /bin/vim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # real path to vim 4 | VIM_CMD=${VIM_CMD:-/usr/bin/vim} 5 | GVIM_CMD=${GVIM_CMD:-/usr/bin/gvim} 6 | 7 | # what program name was i run as? 8 | argv0=`basename $0` 9 | 10 | # turn off software flow control so and will work. you can add 11 | # extra stty settings by setting $VIM_STTY (i use 'erase ^?' here) 12 | [ -t 0 ] && stty -ixon -ixoff $VIM_STTY 13 | 14 | case "$argv0" in 15 | g*) 16 | VIM_CMD="$GVIM_CMD" 17 | ;; 18 | esac 19 | 20 | case "$argv0" in 21 | *diff) 22 | VIM_CMD="${VIM_CMD}diff" 23 | ;; 24 | esac 25 | 26 | case "$argv0" in 27 | # This case has to come before vim 28 | *vm*|*vimacs*) 29 | exec $VIM_CMD --cmd "let g:VM_Enabled = 1" \ 30 | --cmd "set insertmode" \ 31 | "$@" 32 | ;; 33 | *vim*) 34 | exec $VIM_CMD --cmd "let g:VM_Enabled = 1" \ 35 | "$@" 36 | ;; 37 | esac 38 | 39 | -------------------------------------------------------------------------------- /plugin/vimacs/vim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # real path to vim 4 | VIM_CMD=${VIM_CMD:-/usr/bin/vim} 5 | GVIM_CMD=${GVIM_CMD:-/usr/bin/gvim} 6 | 7 | # what program name was i run as? 8 | argv0=`basename $0` 9 | 10 | # turn off software flow control so and will work. you can add 11 | # extra stty settings by setting $VIM_STTY (i use 'erase ^?' here) 12 | [ -t 0 ] && stty -ixon -ixoff $VIM_STTY 13 | 14 | case "$argv0" in 15 | g*) 16 | VIM_CMD="$GVIM_CMD" 17 | ;; 18 | esac 19 | 20 | case "$argv0" in 21 | *diff) 22 | VIM_CMD="${VIM_CMD}diff" 23 | ;; 24 | esac 25 | 26 | case "$argv0" in 27 | # This case has to come before vim 28 | *vm*|*vimacs*) 29 | exec $VIM_CMD --cmd "let g:VM_Enabled = 1" \ 30 | --cmd "set insertmode" \ 31 | "$@" 32 | ;; 33 | *vim*) 34 | exec $VIM_CMD --cmd "let g:VM_Enabled = 1" \ 35 | "$@" 36 | ;; 37 | esac 38 | 39 | -------------------------------------------------------------------------------- /plugin/tab-indent.vim: -------------------------------------------------------------------------------- 1 | """ 2 | "" TabIndent (1.0) 3 | " 4 | " Overloads to either insert a tab, or perform indentation 5 | " 6 | 7 | " 8 | " Copyright (C) 2002 Andre Pang 9 | " 10 | " Please see the documentation (tab-indent.txt) for installation and usage 11 | " notes. 12 | " 13 | 14 | if exists("loaded_TabIndent") 15 | finish 16 | endif 17 | 18 | " Load Vimacs tab-indent? 19 | if v:progname =~ '^vi$' 20 | " Never load Vimacs if user wants true Vi! (We're not _that_ evil 8) 21 | finish 22 | elseif v:progname =~ 'vimacs' || v:progname =~ 'vemacs' || v:progname =~ 'vm' 23 | let g:TabIndentStyle = "emacs" 24 | elseif !exists("g:TabIndentStyle") || g:TabIndentStyle == 0 25 | " A user should explicitly enable tab-indent style 26 | finish 27 | endif 28 | 29 | inoremap =TabOrIndent() 30 | 31 | function! TabOrIndent() 32 | 33 | let saved_cpoptions = &cpoptions 34 | set cpoptions-=<,C,k 35 | set cpoptions+=B 36 | 37 | let indent_blank_line = "\x\==\\\" 38 | let indent = "\==" 39 | let real_tab = "\" 40 | 41 | let &cpoptions = saved_cpoptions 42 | 43 | if &cindent || &indentexpr != "" 44 | 45 | if g:TabIndentStyle == 1 || g:TabIndentStyle == "emacs" || g:TabIndentStyle == "always" 46 | if getline('.') =~ '^\s*$' 47 | return indent_blank_line 48 | else 49 | return indent 50 | endif 51 | 52 | elseif g:TabIndentStyle == 2 || g:TabIndentStyle == "whitespace" 53 | if virtcol('.') <= indent(line('.')) 54 | return indent 55 | else 56 | return real_tab 57 | endif 58 | 59 | elseif g:TabIndentStyle == 3 || g:TabIndentStyle == "startofline" 60 | if virtcol('.') <= indent(line('.')) || virtcol('.') == 1 61 | return indent 62 | else 63 | return real_tab 64 | endif 65 | 66 | endif 67 | 68 | else 69 | return real_tab 70 | endif 71 | 72 | endfunction 73 | 74 | let loaded_TabIndent = 1 75 | 76 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | *vimacs-unix-quickstart* 2 | 3 | Firstly, you'll need Vim 6 installed. Vimacs won't work on older 4 | versions. So, make sure you're running Vim 6: 5 | > 6 | vim --version | head -1 7 | < 8 | The reply you get should say "VIM - Vi IMproved 6.0" (or higher). 9 | 10 | To install Vimacs, execute the following commands in your shell: 11 | > 12 | mkdir -p $HOME/.vim/doc 13 | mkdir -p $HOME/.vim/plugin 14 | cp -R doc plugin $HOME/.vim 15 | echo 'let g:VM_Enabled = 1' >> $HOME/.vimrc 16 | < 17 | Run the following command in a shell to make Vim rescan your documentation 18 | directory: 19 | > 20 | vim --cmd "helptags $HOME/.vim/doc" --cmd "q" 21 | < 22 | That's it. If you're a Vim user, Emacs key mappings will now be enabled 23 | whenever you're in Vim's Insert mode. If you're an Emacs user and have 24 | never used Vim before, you probably want to always keep Vim in Insert 25 | Mode, and use Select mode rather than Visual mode: 26 | > 27 | echo 'set insertmode' >> $HOME/.vimrc 28 | echo 'set selectmode += cmd' >> $HOME/.vimrc 29 | < 30 | Vimacs is now completely installed. However ... 31 | 32 | If you want to have a more sophisticated setup, where you can type a 33 | different command (such as 'vimacs') to always start in Insert mode, but 34 | typing 'vim' starts Vim in Normal mode, read on. 35 | 36 | Put the shell script located at bin/vim somewhere in your $PATH, and 37 | symlink it to the appropriate files. Change the $myscriptdir variable 38 | below to whatever directory you use for scripts; if you don't currently 39 | have one, you'll need to mkdir the directory and add it to your $PATH. 40 | (Consult your local Unix expert on adding directories to your $PATH if you 41 | don't know how to do this.) 42 | > 43 | myscriptdir=$HOME/bin 44 | mkdir -p $myscriptdir 45 | cp plugin/vimacs/vim $myscriptdir 46 | chmod 755 $myscriptdir/vim 47 | ln -s $myscriptdir/vim $myscriptdir/gvim 48 | ln -s $myscriptdir/vim $myscriptdir/vm 49 | ln -s $myscriptdir/vim $myscriptdir/gvm 50 | ln -s $myscriptdir/vim $myscriptdir/vimacs 51 | ln -s $myscriptdir/vim $myscriptdir/gvimacs 52 | myscriptdir= 53 | < 54 | For more detailed installation instructions, see |vimacs-installation| in 55 | the Vimacs help file. 56 | 57 | -------------------------------------------------------------------------------- /doc/tab-indent.txt: -------------------------------------------------------------------------------- 1 | *tab-indent.txt* Tab Indentation for Vim 2 | 3 | |TabIndent.01| Introduction 4 | |TabIndent.02| Usage 5 | |TabIndent.03| Options 6 | |TabIndent.04| Revision History (ChangeLog) 7 | |TabIndent.05| Contact, Help, Credits 8 | 9 | 10 | ============================================================================== 11 | *TabIndent.01* Introduction 12 | 13 | The TabIndent plugin allows you use the key in Insert mode to indent the 14 | current line, as well as retain its usual task of inserting a real 15 | character. TabIndent exhibits a bit of intelligence by making sure that the 16 | current line is only indented if you're editing source code, by checking the 17 | 'cindent' and 'indentexpr' options. Editing text files will never cause the 18 | key to perform indentation. 19 | 20 | You can also change the behaviour of when indentation is performed; some 21 | people prefer to always perform indentation, and others may want to 22 | indent only if the cursor is at the start of the line. TabIndent is designed 23 | to make every user work the way they want to. 24 | 25 | 26 | ============================================================================== 27 | *TabIndent.02* Usage 28 | 29 | To install the TabIndent plugin, put the tab-indent.vim file into the plugin 30 | subdirectory, contained in one of the directories in your 'runtimepath'. 31 | (Such as /usr/share/vim/vimfiles/ on UNIX, or "C:\Vim\vimfiles" on Win32). 32 | You'll need Vim 6.0 or above. 33 | 34 | Once the TabIndent plugin is installed, simply press the key in Insert 35 | mode to indent the line. will perform an indent if the current buffer 36 | has the 'cindent' or 'indentexpr' options set, otherwise it will act as if you 37 | had pressed normally. (Whether it inserts a real, physical is 38 | dependent upon other options such as 'softtabstop'; the TabIndent plugin 39 | doesn't touch these options). 40 | 41 | To install the TabIndent documentation, copy this textfile (tab-indent.txt) to 42 | the "doc" directory in your 'runtimepath'. (e.g. "$HOME/.vim/doc" on UNIX), 43 | then run the |helptags| command on that directory from inside Vim. (e.g. 44 | ":helptags ~/.vim/doc"). See |add-local-help| for details. 45 | 46 | 47 | ============================================================================== 48 | *TabIndent.03* Options 49 | 50 | TabIndent can change its behaviour to your liking by setting variables in your 51 | Vim startup file ("$HOME/.vimrc" in Unix; "C:\Vim\_vimrc" in Windows; see 52 | |.vimrc| for more information). You can set variables using |:let| command, 53 | e.g. 54 | > 55 | let g:TabIndentStyle = "emacs" 56 | < 57 | 58 | *TabIndent-option-list* 59 | 60 | *'g:TabIndentStyle'* 61 | 62 | 'g:TabIndentStyle' number or string (default "emacs") 63 | 64 | Changes the behaviour of the key if the TabIndent plugin is 65 | loaded. No matter what you set this variable to, indentation will 66 | only occur if either the 'cindent' or 'indentexpr' option is set for 67 | the current buffer. If both those options are not set, pressing 68 | will always act as if you pressed the key without the plugin 69 | loaded. 70 | 71 | setting behaviour ~ 72 | 73 | "0" or "never" always inserts a real tab 74 | 75 | "1" or "emacs" always indents 76 | or "always" 77 | 78 | "2" or "whitespace" will indent if the cursor is in 79 | whitespace (space or tab character) at 80 | the start of the line 81 | 82 | "3" or "startofline" will indent if the cursor is in 83 | whitespace (space or tab character) at 84 | the start of the line, or at the very 85 | start of the line 86 | 87 | 88 | ============================================================================== 89 | *TabIndent.04* Revision History (ChangeLog) 90 | 91 | *TabIndent-history* 92 | 93 | I originally had the tab-or-indent functionality in Vimacs, a completely 94 | separate plugin for Vim; the actual idea is borrowed from c-mode in (X)Emacs. 95 | It was pointed out to me that I should make the behaviour of the key 96 | customisable; it was at that point that I decided to make it a completely 97 | separate plugin. Since I couldn't find any comparable script on the Vim 98 | Online website which did this, I decided to make it a real Vim plugin and 99 | release it to the world. 100 | 101 | *TabIndent-changelog* 102 | 103 | *TabIndent-1.0* 104 | 105 | Initial release. 106 | 107 | 108 | ============================================================================== 109 | *TabIndent.05* Contact, Help, Credits 110 | 111 | *TabIndent-help* *TabIndent-author* 112 | 113 | The author of the TabIndent plugin is Andre Pang . 114 | 115 | Just email me directly if you have any queries about the plugin. I don't bite 116 | :). 117 | 118 | *TabIndent-webpage* 119 | 120 | There isn't a webpage for the plugin at the moment. You can always find the 121 | latest version at the Vim Online website, at http://vim.sourceforge.net/. 122 | TabIndent also comes bundled with Vimacs, which is locate at 123 | http://www.vimacs.cx/. 124 | 125 | *TabIndent-thanks* 126 | 127 | TabIndent wouldn't be as useful as it is without the help of the following 128 | people (whether they realise it or not ;): 129 | 130 | Charles E. Campbell ~ 131 | For writing an excellent document on how to write "proper" Vim plugins. 132 | 133 | Michelle Wibisono ~ 134 | For making me realise that the tab-or-indent functionality in Vimacs 135 | should be made customisable, and put into its own Vim plugin. Yay 136 | modularity! 137 | 138 | Thanks! 139 | 140 | 141 | ============================================================================== 142 | vim:tw=78:sts=0:ts=8:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl: 143 | 144 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | What is Vimacs? 2 | =============== 3 | 4 | * Conrad Parker: "Dude, I gotta get you doing some serious hacking projects." 5 | * Erik de Castro Lopo: "Oh, so you're the insane guy that K was talking about." 6 | * Wichert Akkerman: "Gross. Horror. Vim abuse. Mind if I include this as an example in the Debian vim packages? :)" 7 | * Henry Gebhardt: "Vimacs, as ridiculously as it sounds, is a great idea." 8 | 9 | The Nutshell Version 10 | -------------------- 11 | 12 | Vimacs (Vim-Improved eMACS) brings Emacs's extensive key bindings and modeless 13 | editing features to the Vim world, while completely retaining Vim's powerful 14 | moded editing style. 15 | 16 | Vimacs is based on the keymaps of GNU Emacs 21 and XEmacs, so if you are 17 | familiar with them, you'll feel right at home in Vimacs. For Emacs users, you 18 | won't take long to get used to Emacs's keys: just like Vim, Emacs's key layout 19 | has been designed so that commonly used keys are quick to access. 20 | 21 | Vimacs is a standard Vim plugin, so just put the `vimacs.vim` file in your plugin 22 | directory, and put `vimacs.txt` in your documentation directory. That's it! If 23 | you're using Unix, you should also read the INSTALL text file that comes with 24 | Vimacs for notes on how to run Vim with or without Vimacs. 25 | 26 | 27 | Why use Vimacs? 28 | --------------- 29 | 30 | If you're a long-time Vim user, you retain Vi's powerful moded editing paradigm while gaining all the benefits of Emacs's modeless editing. You have nothing to lose! Since Vimacs only emulates Emacs when you're in Insert mode, you may not even notice that it's there. 31 | 32 | Of course, after a while, you may find that the `` and `` keys become second nature to you, just as you're used to the _h_, _j_, _k_, and _l_ keys for movement. Some of the keys familiar to you in Insert mode have been changed, but you won't take long to get used to Emacs's keys: just like Vim, Emacs's initially obscure key layout will reward you later on for its efficiency. Emacs experts are just as fast as Vim experts in manipulating text, and as a bonus, you start becoming familiar with Emacs keybindings, which are gradually becoming more pervasive in Unix applications. (Even Mac OS X supports some Emacs keys in its dialog boxes!) 33 | 34 | If you're an Emacs user, you'll find that Vimacs offers most of the comforts that you're used to in Emacs, with one significant advantage: blazing speed. Vim is optimised for efficient text editing, whereas Emacs is optimised for extensibility, and sacrifices speed because of it. In addition, I feel that Vim is much more straightforward to customise than Emacs, it has better documentation, and has better cross-platform support. 35 | 36 | Of course, a major disadvantage of Vim compared to Emacs is that you don't have the enormous number of Emacs add-ons that have been integrated into the editor over the last few decades. However, you may be surprised at how many of those add-ons are incorporated into Vim itself, for speed. For example, dynamic abbreviation, parenthesis highlighting, and C indenting are all built into Vim. Even complex add-ons, such as Emacs' Grand Unified Debugger, have been implemented in Vim via add-on scripts. Vim does offer its own scripting language if you want to extend it, and if that isn't enough, Vim 6.1 supports Perl, Python, Tcl, OLE, and Ruby as scripting languages: far more choices than just LISP! 37 | 38 | Ultimately, the differences between the two editors come down to different design goals: Emacs is aimed at being everything for everyone, and Vim is aimed at being a pure text editor. Vimacs opens up Vim to Emacs users (and everyone else) by allowing you to work with it without having to press `` all the time, so you aren't forced to work with Vi's moded editing style. If you've shied away from Vim because of its Vi-style editing, give Vimacs a shot! 39 | 40 | The History of Vimacs 41 | --------------------- 42 | 43 | In classic open-source spirit, Vimacs was created to "scratch an itch". I used to use Emacs all the time; it's a fantastic tool for doing all kinds of things (even text editing...). However, it suffers from some problems which I feel are unsolvable without a drastic redesign: 44 | 45 | * Speed. Emacs doesn't even begin to approach Vim for raw speed; Vim can load and fully syntax-colour a file before Emacs even displays its window. (Using gnuclient doesn't count!) One of the reasons for Emacs's slow speed compared to many other text editors is that it uses LISP for everything. Now, using LISP for everything has many advantages, including making Emacs completely extensible. I'm all for extensibility, but in this case, Emacs is too slow (for me) because of it. In my eyes, you use an editor so much in the UNIX environment that you really want it to be as fast as possible. Even though Emacs is extensible++, it's slow enough that I never load it for quick editing jobs. 46 | 47 | * Customisation is too hard. Emacs exposed so much of its complexity and internals to you that it would befuddle your average user who just wanted to change a few settings. I didn't feel like learning LISP just to customise the editor a bit; `M-x customize` made this much better, but it's still still unnecessarily hard to change something which isn't in that list of options. Try writing your own syntax file or colour scheme, for instance; other editors usually make this much easier. Of course, you can argue that learning the language of Emacs (i.e. LISP) leads to learning a powerful generic language which can be used in many places outside of Emacs, but hey, some of us want to get other work done, too. 48 | 49 | Please don't get me wrong--I'm not flaming Emacs, and I'm definitely not saying that it's a bad editor. It's a fantastic editor; it's arguably one of the most powerful pieces of software on the planet. It's just not the kind of editor that I like to use on a daily basis. I don't need most of its ninja-fu abilities, but some of them are incredibly helpful. I can't live without things like dynamic abbreviation (the magical `M-/` key), and having the editor understand the syntax of the file you're editing. Once you're used to those features, life is simply miserable without them. 50 | Vimacs was created because I was looking for an alternative to Emacs, and I found none. I wanted a cross-platform editor, since I work a lot on both Win32 and UNIX systems, and I wanted it to be fast and easy to customise, yet still have most of the power that Emacs gave me when I was editing text files, or coding. I tried every single editor I found on Freshmeat and Ibiblio, but I still couldn't find one that I liked. Vim would have been perfect, but I could never get used to the moded style of editing. Pressing <Esc> all the time drove me nuts. (I'm not saying that moded editing sucks, mind you, I'm just saying that I personally hated being forced into that kind of editing style.) 51 | After toying around with Vim's scripting language, I decided to do something to end my misery, and I figured that Vim's scripting capabilities were powerful enough that it could be used to emulate Emacs quite well. I wouldn't be able to emulate everything, of course, but I'd be able to emulate Emacs well enough that it'd have all the key bindings that I was used to. So, Vimacs was born. Vim by itself is a powerful editor; I loved everything about it except for the moded editing paradigm. Vimacs is simply something which makes Vim more accessible to the non-Vi crowd, and it does so in a way which impacts existing Vim users in a very small way. 52 | -------------------------------------------------------------------------------- /plugin/vimacs.vim: -------------------------------------------------------------------------------- 1 | """ 2 | "" Vimacs (0.96) 3 | " 4 | " Vim-Improved eMACS 5 | " 6 | " (Oh dear, what have I got myself into?) 7 | " 8 | 9 | " 10 | " Copyright (C) 2002 Andre Pang 11 | " 12 | " Please see the documentation (vimacs.txt) for the README, installation 13 | " notes, and the ChangeLog. 14 | " 15 | 16 | " 17 | " This program is free software; you can redistribute it and/or modify 18 | " it under the terms of the GNU General Public License as published by 19 | " the Free Software Foundation; either version 2 of the License, or 20 | " (at your option) any later version. 21 | " 22 | " This program is distributed in the hope that it will be useful, 23 | " but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | " GNU General Public License for more details. 26 | " 27 | " You should have received a copy of the GNU General Public License 28 | " along with this program; if not, write to the Free Software 29 | " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30 | " 31 | " This General Public License does not permit incorporating your program into 32 | " proprietary programs. If your program is a subroutine library, you may 33 | " consider it more useful to permit linking proprietary applications with the 34 | " library. If this is what you want to do, use the GNU Library General 35 | " Public License instead of this License. 36 | " 37 | 38 | " TODO: :h map-script 39 | " :h cpoptions 40 | " :h mapleader 41 | " :h map- 42 | " :h 43 | " :h undo? 44 | " :h write-plugin 45 | 46 | " Have for all maps? 47 | 48 | " Load Vimacs? 49 | if v:progname =~ '^vi$' 50 | " Never load Vimacs if user wants true Vi! (We're not _that_ evil 8) 51 | if !exists("g:VM_Enabled") 52 | let g:VM_Enabled = 0 53 | endif 54 | finish 55 | elseif v:progname =~ 'vimacs' 56 | let g:VM_Enabled = 1 57 | elseif v:progname =~ 'vemacs' || v:progname == 'vm' 58 | let g:VM_Enabled = 1 59 | set insertmode 60 | elseif !exists("g:VM_Enabled") || g:VM_Enabled == 0 61 | " A vim user should explicitly enable Vimacs 62 | finish 63 | endif 64 | 65 | 66 | if version < 600 67 | " We require Vim 6 to work :( 68 | echoerr 'Vimacs requires Vim 6 to run :(' 69 | finish 70 | endif 71 | 72 | " We want to be able to remap <> key codes and do line continuation 73 | let s:saved_cpoptions = &cpoptions 74 | set cpoptions-=<,C 75 | 76 | 77 | " Set a default value for a variable only if it doesn't exist 78 | " (like "$foo |= 'bar'" in Perl) 79 | " 80 | " Thanks to Piet Delport for this solution, and Benji Fisher for 81 | " additional comments :) 82 | " 83 | 84 | function! LetDefault(var_name, value) 85 | if !exists(a:var_name) 86 | execute 'let ' . a:var_name . '=' . a:value 87 | endif 88 | endfunction 89 | 90 | command! -nargs=+ LetDefault call s:LetDefault() 91 | 92 | 93 | " Developers may want to turn this on, to always load the file 94 | LetDefault g:VM_Dev 0 95 | 96 | if (exists("loaded_vimacs") && g:VM_Dev == 0) || &cp 97 | finish 98 | endif 99 | 100 | 101 | " 102 | " Function to mark a cursor position and restore it afterward -- used in a few 103 | " functions, like FillParagraph(). Blatantly stolen from foo.vim by Benji 104 | " Fisher :) 105 | " 106 | 107 | function! Mark(...) 108 | if a:0 == 0 109 | let mark = line(".") . "G" . virtcol(".") . "|" 110 | normal! H 111 | let mark = "normal!" . line(".") . "Gzt" . mark 112 | execute mark 113 | return mark 114 | elseif a:0 == 1 115 | return "normal!" . a:1 . "G1|" 116 | else 117 | return "normal!" . a:1 . "G" . a:2 . "|" 118 | endif 119 | endfun 120 | 121 | 122 | " 123 | " set virtualedit=all (or onemore in Vim 7) is necessary 124 | " for consistent word movement 125 | " 126 | 127 | function! SetVirtualedit() 128 | let s:saved_virtualedit = &virtualedit 129 | set virtualedit=all 130 | endfunction 131 | 132 | function! RestoreVirtualedit() 133 | let &virtualedit = s:saved_virtualedit 134 | endfunction 135 | 136 | 137 | " 138 | " It's a good idea to have a command height of at least 2 if showmode is on, 139 | " because many important messages will be overwritten by the mode display. 140 | " e.g. , which saves the file, will display that the file has been 141 | " saved, but the notice will be immediately overwritten by the modeline when 142 | " this happens. 143 | " 144 | 145 | " Don't fork around with cmdheight? 146 | LetDefault g:VM_CmdHeightAdj 1 147 | 148 | if &cmdheight == 1 && &showmode == 1 && g:VM_CmdHeightAdj 149 | set cmdheight=2 150 | endif 151 | 152 | 153 | " 154 | " Vim options essential for emulating Emacs-ish behaviour 155 | " 156 | 157 | " Turn off / pulling down GUI menu 158 | set winaltkeys=no 159 | " Emacs normally wraps everything 160 | LetDefault g:VM_Wrap 2 161 | LetDefault g:VM_WrapHL 1 162 | if g:VM_Wrap==2 163 | set whichwrap=b,s,<,>,[,],~ 164 | if g:VM_WrapHL 165 | set whichwrap+=h,l 166 | endif 167 | elseif g:VM_Wrap==1 168 | set whichwrap+=[,] 169 | endif 170 | " Emacs always has 'hidden buffers' 171 | " The 'g:VM_Hidden option' also affects bindings of etc 172 | LetDefault g:VM_Hidden 1 173 | if g:VM_Hidden 174 | set hidden 175 | endif 176 | " Backspace in Emacs normally backspaces anything :) 177 | set backspace=indent,eol,start 178 | " Want to be able to use within our mappings 179 | " (This has got to be the coolest option name ever, btw) 180 | set wildcharm= 181 | " Recognise key sequences that start with in Insert Mode 182 | set esckeys 183 | 184 | 185 | " 186 | " For the UNIX console -- make x == 187 | " 188 | 189 | " Pressing sends x? (As Unix terminals often do) 190 | LetDefault g:VM_UnixConsoleMetaSendsEsc 1 191 | 192 | " One or two s required to go back to Normal mode? 193 | LetDefault g:VM_SingleEscToNormal 1 194 | 195 | if has("unix") && !has("gui_running") && g:VM_UnixConsoleMetaSendsEsc 196 | " x maps to 197 | "let charCode = 65 198 | "while charCode <= 122 199 | " exec "set =\" . nr2char(charCode) 200 | " let charCode = charCode + 1 201 | "endwhile 202 | "unlet charCode 203 | set =1 204 | set =2 205 | set =3 206 | set =4 207 | set =5 208 | set =6 209 | set =7 210 | set =8 211 | set =9 212 | set =0 213 | set =a 214 | set =b 215 | set =c 216 | set =d 217 | set =e 218 | set =f 219 | set =g 220 | set =h 221 | set =i 222 | set =j 223 | set =k 224 | set =l 225 | set =m 226 | set =n 227 | set =o 228 | set =p 229 | set =q 230 | set =r 231 | set =s 232 | set =t 233 | set =u 234 | set =v 235 | set =w 236 | set =x 237 | set =y 238 | set =z 239 | set = 240 | set =/ 241 | " Doing "set >=^[>" throws up an error, so we be dodgey and use Char-190 242 | " instead, which is ASCII 62 ('>' + 128). 243 | set => 244 | " Probably don't need both of these ;) 245 | set =< 246 | set =< 247 | set =0 248 | 249 | set =% 250 | set =* 251 | set =. 252 | set =^ 253 | " Can't set right now :( 254 | "set = 255 | " 256 | endif 257 | 258 | 259 | " 260 | " One or two s to get back to Normal mode? 261 | " 262 | 263 | function! NormalModeKey() 264 | if &insertmode 265 | return "\" 266 | else 267 | return "\" 268 | endif 269 | endfunction 270 | 271 | " on CmdwinLeave? 272 | if g:VM_SingleEscToNormal == 1 273 | if &insertmode 274 | if has('unix') && !has('gui_running') && g:VM_UnixConsoleMetaSendsEsc 275 | inoremap :UseF1ForNormal 276 | else 277 | inoremap 278 | endif 279 | endif 280 | 281 | set notimeout 282 | set ttimeout 283 | set timeoutlen=50 284 | else 285 | inoremap =NormalModeKey() 286 | vnoremap 287 | " for some reason, double in Select mode wasn't working 288 | " until I added a second explicit select-mode map...? 289 | if version >= 700 290 | snoremap 291 | endif 292 | nnoremap 293 | set notimeout 294 | set nottimeout 295 | endif 296 | 297 | command! UseF1ForNormal echoerr "Use F1 or to return to Normal mode. :help vimacs-unix-esc-key" 298 | 299 | 300 | " 301 | " Insert mode <-> Normal mode <-> Command mode 302 | " 303 | 304 | inoremap : 305 | inoremap : 306 | inoremap =NormalModeKey() 307 | inoremap 308 | inoremap 309 | inoremap =NormalModeKey():echo "Returning to Normal mode; press again to suspend Vimacs" 310 | nnoremap :call Suspend() 311 | " M-` isn't defined in Emacs 312 | 313 | inoremap 1 314 | inoremap 2 315 | inoremap 3 316 | inoremap 4 317 | inoremap 5 318 | inoremap 6 319 | inoremap 7 320 | inoremap 8 321 | inoremap 9 322 | 323 | LetDefault g:VM_NormalMetaXRemap 1 324 | 325 | if g:VM_NormalMetaXRemap == 1 326 | nnoremap : 327 | endif 328 | 329 | function! Suspend() 330 | suspend! 331 | if &insertmode 332 | startinsert 333 | endif 334 | endfunction 335 | 336 | 337 | " 338 | " Leaving Vim 339 | " 340 | 341 | inoremap :confirm qall 342 | 343 | 344 | " 345 | " Files & Buffers 346 | " 347 | 348 | if g:VM_Hidden 349 | inoremap :hide edit 350 | else 351 | inoremap :edit 352 | endif 353 | inoremap :update 354 | inoremap s :wall 355 | inoremap i :read 356 | "what does C-x C-v do? 357 | inoremap :write 358 | inoremap :set invreadonly 359 | if g:VM_Hidden 360 | inoremap :hide view 361 | else 362 | inoremap :view 363 | endif 364 | 365 | 366 | " 367 | " Help Sistemmii (hi Finns) 368 | " 369 | "inoremap :help 370 | 371 | 372 | " 373 | " Error Recovery 374 | " 375 | 376 | inoremap u 377 | inoremap u 378 | "lots of other stuff :( 379 | 380 | 381 | " 382 | " Incremental Searching and Query Replace 383 | " 384 | 385 | inoremap :call StartSearch('/')/ 386 | inoremap :call StartSearch('?')? 387 | inoremap :cnext 388 | " not in Emacs: next in QuickFix 389 | inoremap :cprevious 390 | " not in Emacs: previous in QuickFix 391 | inoremap :call StartSearch('/')/ 392 | inoremap :call StartSearch('?')? 393 | inoremap :set invhls 394 | inoremap :call QueryReplace() 395 | inoremap :call QueryReplaceRegexp() 396 | cnoremap ? 397 | 398 | command! QueryReplace :call QueryReplace() 399 | command! QueryReplaceRegexp :call QueryReplaceRegexp() 400 | 401 | " Searching is a bit tricky because we have to emulate Emacs's behaviour of 402 | " searching again when or is pressed _inside_ the search 403 | " commandline. Vim has no equivalent to this, so we must use a bit of 404 | " on-the-fly remap trickery (popular in Quake-style games) to provide 405 | " different functionality for , depending on whether you're in 'search 406 | " mode' or not. 407 | " 408 | " We must map and because we have to undo the map trickery that we 409 | " set up when we abort/finish the search. All in all, it's not too complex 410 | " when you actually look at what the code does. 411 | " 412 | " Note that in Emacs is functionally the same as . 413 | 414 | LetDefault g:VM_SearchRepeatHighlight 0 415 | 416 | function! StartSearch(search_dir) 417 | let s:incsearch_status = &incsearch 418 | let s:lazyredraw_status = &lazyredraw 419 | let s:hit_boundary = 0 420 | set nowrapscan 421 | set incsearch 422 | set lazyredraw 423 | cmap 424 | cnoremap :call SearchAgain()/ 425 | cnoremap :call SearchAgain()? 426 | cnoremap :call StopSearch() 427 | cnoremap :call AbortSearch() 428 | cnoremap :call AbortSearch() 429 | if a:search_dir == '/' 430 | cnoremap :set invhls/ 431 | else 432 | cnoremap :set invhls? 433 | endif 434 | let s:before_search_mark = Mark() 435 | endfunction 436 | 437 | function! StopSearch() 438 | cunmap 439 | cunmap 440 | cunmap 441 | cunmap 442 | cunmap 443 | cnoremap 444 | if exists("s:incsearch_status") 445 | let &incsearch = s:incsearch_status 446 | unlet s:incsearch_status 447 | endif 448 | if g:VM_SearchRepeatHighlight == 1 449 | if exists("s:hls_status") 450 | let &hls = s:hls_status 451 | unlet s:hls_status 452 | endif 453 | endif 454 | endfunction 455 | 456 | function! AbortSearch() 457 | call StopSearch() 458 | if exists("s:before_search_mark") 459 | execute s:before_search_mark 460 | unlet s:before_search_mark 461 | endif 462 | endfunction 463 | 464 | function! SearchAgain() 465 | 466 | "if (winline() <= 2) 467 | " normal zb 468 | "elseif (( winheight(0) - winline() ) <= 2) 469 | " normal zt 470 | "endif 471 | 472 | let current_pos = Mark() 473 | if search(@/, 'W') == 0 474 | " FIXME 475 | set wrapscan 476 | if s:hit_boundary == 1 477 | let s:hit_boundary = 2 478 | endif 479 | let s:hit_boundary = 1 480 | else 481 | if s:hit_boundary == 2 482 | let s:hit_boundary = 0 483 | endif 484 | execute current_pos 485 | endif 486 | 487 | cnoremap :call SearchAgain()/ 488 | cnoremap :call SearchAgain()? 489 | 490 | if g:VM_SearchRepeatHighlight == 1 491 | if !exists("s:hls_status") 492 | let s:hls_status = &hls 493 | endif 494 | set hls 495 | endif 496 | 497 | endfunction 498 | 499 | " Emacs' `query-replace' functions 500 | 501 | function! QueryReplace() 502 | let magic_status = &magic 503 | set nomagic 504 | let searchtext = input("Query replace: ") 505 | if searchtext == "" 506 | echo "(no text entered): exiting to Insert mode" 507 | return 508 | endif 509 | let replacetext = input("Query replace " . searchtext . " with: ") 510 | let searchtext_esc = escape(searchtext,'/\^$') 511 | let replacetext_esc = escape(replacetext,'/\') 512 | execute ".,$s/" . searchtext_esc . "/" . replacetext_esc . "/cg" 513 | let &magic = magic_status 514 | endfunction 515 | 516 | function! QueryReplaceRegexp() 517 | let searchtext = input("Query replace regexp: ") 518 | if searchtext == "" 519 | echo "(no text entered): exiting to Insert mode" 520 | return 521 | endif 522 | let replacetext = input("Query replace regexp " . searchtext . " with: ") 523 | let searchtext_esc = escape(searchtext,'/') 524 | let replacetext_esc = escape(replacetext,'/') 525 | execute ".,$s/" . searchtext_esc . "/" . replacetext_esc . "/cg" 526 | endfunction 527 | 528 | 529 | " 530 | " Command line editing 531 | " 532 | 533 | " Navigation 534 | cmap 535 | cmap 536 | cnoremap 537 | cnoremap 538 | cmap 539 | cmap 540 | 541 | " Editing 542 | cmap 543 | cmap 544 | cmap 545 | cnoremap " 546 | cnoremap 547 | cnoremap 548 | cnoremap d$ 549 | "Should really use &cedit, not just -- but how? 550 | 551 | 552 | " 553 | " Navigation 554 | " 555 | 556 | function! ForwardWord() 557 | if col('.')>1 || line('.')>1 558 | return "normal! hel" 559 | else 560 | return "normal! el" 561 | endif 562 | endfunction 563 | 564 | inoremap ForwardWord :call SetVirtualedit() 565 | \:execute ForwardWord() 566 | \:call RestoreVirtualedit() 567 | 568 | onoremap OForwardWord :call SetVirtualedit() 569 | \execute ForwardWord() 570 | \call RestoreVirtualedit() 571 | 572 | " Weird. In Vim 7, if insertmode is on, if you exit visual mode in a mapping, 573 | " things get weird unless you do some normal command, even a no-op 574 | nmap Nop 575 | function! ExitVisual() 576 | if ! &insertmode 577 | startinsert 578 | else 579 | normal! Nop 580 | endif 581 | endfunction 582 | 583 | function VForwardWord1() 584 | if col('.')>=col('$') 585 | let s:vforward_fix = 1 586 | else 587 | let s:vforward_fix = 0 588 | endif 589 | endfunction 590 | 591 | function VForwardWord2() 592 | if s:vforward_fix 593 | return "\gv``\" 594 | else 595 | return "\gv``" 596 | endif 597 | endfunction 598 | 599 | function AdjustVisualModeExitPosition(backwards) 600 | if line('.')==line("'>") && col('.')+1 == col("'>") 601 | if !a:backwards || line('.')!=line("'<") || col('.') != col("'<") 602 | return "\" 603 | endif 604 | elseif line('.')==line("'<") && col('.')+1 == col("'<") 605 | return "\" 606 | endif 607 | return "" 608 | endfunction 609 | 610 | if version >= 700 611 | vnoremap VForwardWord 612 | \:call ExitVisual() 613 | \=AdjustVisualModeExitPosition(0) 614 | \:call SetVirtualedit() 615 | \:execute ForwardWord() 616 | \:call VForwardWord1() 617 | \m` 618 | \:call RestoreVirtualedit() 619 | \=VForwardWord2() 620 | else 621 | vnoremap VForwardWord 622 | \i 623 | \=AdjustVisualModeExitPosition(0) 624 | \:call SetVirtualedit() 625 | \:execute ForwardWord() 626 | \:call VForwardWord1() 627 | \m` 628 | \:call RestoreVirtualedit() 629 | \=VForwardWord2() 630 | endif 631 | 632 | function! BackwardWord() 633 | let l:line = line('.') 634 | let l:getline = getline(l:line) 635 | if col('.')==1 || strpart(l:getline,0,col('.')-1) =~ '^\s*$' 636 | let l:count = l:line-1 - prevnonblank(l:line-1) 637 | if l:count > 0 638 | return "normal! " . l:count . "kb" 639 | endif 640 | endif 641 | if col('.')>=col('$') && line('.') BackwardWord :call SetVirtualedit() 649 | \:execute BackwardWord() 650 | \:call RestoreVirtualedit() 651 | 652 | onoremap OBackwardWord :call SetVirtualedit() 653 | \execute BackwardWord() 654 | \call RestoreVirtualedit() 655 | 656 | if version >= 700 657 | vnoremap VBackwardWord 658 | \:call ExitVisual() 659 | \=AdjustVisualModeExitPosition(1) 660 | \:call SetVirtualedit() 661 | \:execute BackwardWord() 662 | \m` 663 | \:call RestoreVirtualedit() 664 | \gv 665 | \`` 666 | else 667 | vnoremap VBackwardWord 668 | \i 669 | \=AdjustVisualModeExitPosition(1) 670 | \:call SetVirtualedit() 671 | \:execute BackwardWord() 672 | \m` 673 | \:call RestoreVirtualedit() 674 | \gv 675 | \`` 676 | endif 677 | 678 | " Insert/Visual/Operator mode maps 679 | imap 680 | vmap 681 | omap 682 | imap 683 | vmap 684 | omap 685 | imap 686 | vmap 687 | omap 688 | imap 689 | vmap 690 | omap 691 | inoremap