-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvimpulse.el
executable file
·7210 lines (6626 loc) · 280 KB
/
vimpulse.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;;; vimpulse.el --- emulates Vim's most useful features -*- coding: utf-8 -*-
;; Copyright (C) 2007 Brad Beveridge
;; Copyright (C) 2007, 2009 Alessandro Piras
;; Copyright (C) 2008 Frank Fischer
;; Copyright (C) 2009 Jason Spiro <http://www.jspiro.com/>
;; Copyright (C) 2010 Vegard Øye
;; Copyright (C) 2010 Štěpán Němec
;;
;; Author: Brad Beveridge et al.
;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
;; Please send bug reports to the mailing list (see below).
;; Created: 23 Aug 2007
;; Version: 0.5
;; Keywords: emulations, viper
;; Human-Keywords: vim, visual-mode, rsi, ergonomics, emacs pinky
;; URL: http://www.emacswiki.org/emacs/vimpulse.el
;; Gitorious project: http://gitorious.org/vimpulse
;; For the latest developmental version, clone the repo with:
;; git clone git://gitorious.org/vimpulse/vimpulse.git
;; 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. We usually reply within a few
;; days and CC our replies back to you.
;; Related: viper.el, viper-in-more-modes.el
;;
;; Thanks to our old maintainers:
;; Alessandro Piras
;; Jason Spiro
;; We'll miss you as maintainers :)
;;
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Vimpulse emulates Vim's most popular features, like Visual mode
;; and text objects. Vimpulse is a set of modifications to Viper, the
;; standard library that emulates vi. Vimpulse is not a minor mode;
;; as soon as it is loaded, Viper will start working in a more
;; Vim-like way.
;;
;; Vimpulse is under active development. It works quite well with
;; GNU Emacs 22.3 and 23.2, as well as XEmacs 21.4.22. Patches and
;; feature requests are welcome (see also the file CONTRIBUTE in the
;; repository).
;;; Installation:
;; If you checked out from Git, run `make' to produce
;; vimpulse-big.el. If on Windows, you can run compile.bat. Then:
;;
;; 1. Copy vimpulse.el (or vimpulse-big.el) to somewhere in your
;; `load-path'.
;;
;; 2. Add the following to your init file:
;;
;; (require 'vimpulse)
;;
;; If you use Windows, see
;; http://www.gnu.org/software/emacs/windows/faq3.html
;;
;; The rest is optional:
;;
;; 3. For linear undo/redo and undo branches, install
;; undo-tree.el: http://www.emacswiki.org/emacs/UndoTree
;;
;; Just place it in `load-path', and Vimpulse will load it
;; automatically. On XEmacs, you can use redo.el instead.
;;
;; Vimpulse automatically enables Viper. You can temporarily disable
;; Viper (and Vimpulse) with the "C-z" key.
;;; Usage:
;; To use Visual mode, press "v" in vi (command) mode. Then use the
;; motion commands to expand the selection. Press "d" to delete, "c"
;; to change, "r" to replace, or "y" to copy. You can use "p" to
;; paste. For Line selection, press "V" instead of "v"; then you can
;; copy and paste whole lines. For Block selection, press "C-v"; now
;; you can copy and paste the selected rectangle. In Block selection,
;; you may use "I" or "A" to insert or append text before or after the
;; selection on each line.
;;
;; Other features:
;;
;; Vimpulse supports text objects: "daw", "daW", "das", "dap", "dab",
;; "daB", "da(", "da[", "da{", "da<", "da"", "da'", as well as "diw",
;; "diW", "dis", etc. To change an object: "caw", "cas", etc. To yank
;; it: "yaw", "yas", etc. To select it: "vaw", "vas", etc.
;;
;; The extended documentation is still in its early stages, but you
;; can view drafts at: http://gitorious.org/vimpulse/pages/Home
;;
;; The documentation that comes with Vim -- which is online at
;; http://vimdoc.sf.net/ -- may also be helpful.
;;
;; Tips:
;;
;; - Vimpulse makes "C-r" run Redo in command mode, but you can
;; still get reverse isearch by pressing "C-s" and then "C-r".
;;
;; - To change the color of search, add something like the following
;; to .emacs:
;;
;; (set-face-foreground isearch nil)
;; (set-face-background isearch "lightgoldenrod2")
;;
;; - To change the color of Visual mode (`zmacs-region' in XEmacs):
;;
;; (set-face-background 'region "blue")
;;
;; For more tips, see: http://gitorious.org/vimpulse/pages/Tips
;;; News:
;; Version 0.5 [2010-09-12]
;; [vegard_oye at hotmail.com:]
;; - [NEW] "/" and "?" use isearch. Matches are highlighted while
;; typing; also, isearch shortcuts apply, like "M-c" to toggle
;; case-sensitivity. Type "C-h k /" for more details.
;; - [NEW] :undolist or :ul shows the undo history as a tree. This
;; uses undo-tree.el, which replaces redo.el for undo/redo
;; (see installation instructions).
;; - [NEW] Keybinding functions: `vimpulse-global-set-key',
;; `vimpulse-local-set-key', `vimpulse-define-key'. State bindings
;; can now be assigned to both minor and major Emacs modes,
;; which is useful for writing extensions.
;; - [NEW] Keys: "gi", "g0", "g$", "]P", "]p".
;; - [NEW] Lower-case marks are buffer-local -- thanks, Štěpán Němec.
;; - [NEW] If `viper-auto-indent' is t, then "RET" extends the
;; comment prefix to the next line (with `comment-indent-new-line'
;; from newcomment.el).
;; - [NEW] "C-w" has its own prefix map, `vimpulse-window-map'.
;; - [FIX] Replace mode's appearance is now more similar to Vim's.
;; - [FIX] Byte compilation errors.
;; - [FIX] Various bugs submitted to the mailing list --
;; thanks, everyone.
;; - Operator commands are now defined with the
;; `vimpulse-define-operator' macro.
;; - To pacify the compiler, all variables are initially defined
;; in one place.
;; - For readability and consistency, "Yoda conditions" are
;; universally banned: e.g., (= var 0), not (= 0 var).
;; - "Change Log" is renamed to "News".
;;
;; Version 0.4 [2010-04-26]
;; [vegard_oye at hotmail.com:]
;; - [NEW] Operator-Pending mode: the cursor's appearance
;; changes temporarily after "y", "d", "c", etc.
;; - [NEW] Motion type system: one can change how a motion is
;; "interpreted" with "v", "V" and "C-v". For example, "dvj" will
;; delete a characterwise range (the default is linewise).
;; - [NEW] Keys: "gq", "gu", "gU", "g~", "g?".
;; - [NEW] Keybinding functions: `vimpulse-omap' and
;; `vimpulse-omap-local'.
;; - [FIX] Vimpulse's text objects handle whitespace
;; more like Vim's.
;; - [FIX] Various bugs submitted to the mailing list --
;; thanks, everyone.
;; - The code for applying an "operator" like "d" to a "motion"
;; like "w" is completely rewritten. Operators are simple
;; to define (with `vimpulse-range'), and can be applied
;; to regular Emacs movement commands as well.
;; - The text objects have been redefined in terms of the new
;; framework. They are implemented as selection commands;
;; see the `vimpulse-define-text-object' macro for details.
;; - The code for adding Viper states is generalized.
;; Both Visual mode and Operator-Pending mode are
;; defined with the `vimpulse-define-state' macro.
;; - The comments use a more conventional format: ;;;; for major
;; headings (one per file), ;;; for subsections (within each file),
;; ;; for individual pieces of code and ; for trailing comments.
;; This is easier to maintain and complies with section D.7 of
;; the GNU Emacs Lisp Reference Manual.
;;
;; Version 0.3.1 [2010-03-09]
;; [vegard_oye at hotmail.com:]
;; - [NEW] Emacs-compatible Visual selection.
;; It is now a Viper state proper, with a user map
;; and a major mode extension map.
;; [NEW] Visual keys: "u", "U", "~", ">", "<", "J", "O", "gv" --
;; thanks, Frank Fischer.
;; - [NEW] Movement keys: "C-o", "C-i", "C-w hjkl", "gb", "gd", "+", "_".
;; - [NEW] Keybinding functions: `vimpulse-map',
;; `vimpulse-imap' and `vimpulse-vmap'.
;; - [NEW] Backspace in Replace mode restores text.
;; - [NEW] Basic vi navigation in help buffers.
;; - [NEW] Vimpulse has its own customization group.
;; - [FIX] Improved text objects support, including Visual mode.
;; - [FIX] Various bugs listed at EmacsWiki or submitted to the
;; mailing list or bug tracker -- thanks.
;; - All Vimpulse bindings are now in `viper-vi-basic-map',
;; leaving `viper-vi-global-user-map' for the user.
;; The same is true of Visual mode.
;; - Easier installation. rect-mark.el is no longer needed,
;; nor is cl.el.
;; - All tabs are replaced by spaces.
;; - The file encoding is UTF-8.
;; [laynor at gmail.com:]
;; - Added some small fixes, and promoted the experimental stuff to
;; stable, as it seems to work well and not loading it caused
;; problems.
;;
;; Version 0.3.0 [2009-07-03]
;; [laynor at gmail.com:]
;; - [NEW] Register support on text object commands.
;; - [NEW] Issuing ":" in Visual mode has a behavior closer
;; to Vim's.
;; [jasonspiro3 at gmail.com:]
;; - [FIX] The Enter key now does what it should do -- insert a
;; newline -- even when longlines-mode is on.
;; - Comment changes.
;;
;; Version 0.2.6.9 [2009-06-24]
;; [laynor at gmail.com:]
;; - [FIX & NEW] Text objects support fixed and integrated with Viper.
;; Now count works (e.g., you can do "3caw" and it works correctly),
;; and it's possible to repeat the commands with ".".
;;
;; Version 0.2.6.8 [2009-06-22]
;; [laynor at gmail.com:]
;; - [NEW] Text object support: paren blocks, sentences, word, Words,
;; quoted expressions, paragraphs. Delete and change commands.
;; Example commands: "diw", "ci(", "das", etc.
;; - [FIX] It's now possible to exit Visual mode by pressing
;; "ESC" or "^[".
;;
;; Version 0.2.6.7
;; [jasonspiro3 at gmail.com:]
;; - No code changes.
;; - Fixed up "thanks" section below to mention Mieszko
;; <sillyfox at yahoo.com>'s full name. He wrote a small patch
;; which was included long ago. I must have forgotten to include it
;; in the changelog.
;;
;; Version 0.2.6.6
;; [laynor at gmail.com:]
;; - Fixed pasting in Visual mode, works like in Vim now
;; (experimental, see point 6 of installation instructions).
;;
;; Version 0.2.6.5
;; [laynor at gmail.com:]
;; - Fixed some major suckage with the change command. Still alpha,
;; comments welcome. To use it, see the installation instructions,
;; point 6 (it's still experimental).
;; - Cleaned namespace, hope there are no hidden bugs.
;; - Fixed loading on Emacs snapshot.
;;
;; Version 0.2.6.4
;; [laynor at gmail.com:]
;; - This can probably be considered a major release.
;; - [FIX & NEW] Rewritten Visual mode, "v" and "V" variants (no
;; changes to Visual Block still). It does not use the region like
;; before: highlighting is done through overlays, and the region is
;; set inside the command code before calling the Viper commands.
;; "=" in Visual mode calls `vimpulse-visual-indent-command'. The
;; Visual mode (apart from Block mode) looks and feels like Vim.
;; - [NEW] Enhanced paren-matching. Moving the cursor on a closing
;; paren in Normal mode now highlights the opening paren.
;; - [NEW] Pressing "RET" in Insert mode automatically indents
;; the new line.
;; - [NEW] "^[" works.
;; - [FIX] "a<ESC>" leaves the cursor in the same location as it was
;; before (it advanced the cursor 1 character before --
;; `viper-exit-insert-state's fault).
;; - [FIX] "cW" doesn't suck anymore at the end of a line.
;;
;; Version 0.2.6.3:
;; [frank.fischer at s2001.tu-chemnitz.de:]
;; - Support more Visual Block mode features: insert, append, delete,
;; yank, change.
;; - Change some Vimpulse and Viper functions to handle Block mode
;; properly.
;; - Update documentation to reflect Visual Block mode.
;; - The "=" key in Visual mode calls `indent-region'.
;;
;; Version 0.2.6.2:
;; [jasonspiro3 at gmail.com:]
;; - Improved XEmacs compatibility.
;; - Small documentation improvements.
;;
;; Version 0.2.6.1:
;; [jasonspiro3 at gmail.com:]
;; - Removed duplicate definition of `vimpulse-detect-mark-deactivate'
;; and duplicate `add-hook' call to add the hook. I must have added
;; the extra copies by accident when doing my last big merge; now
;; they are gone.
;;
;; Version 0.2.6.0:
;; [jasonspiro3 at gmail.com:]
;; - Merged a patch for the function that powers "*" and "#". Based on
;; Ryoichi's patch and a cleaned-up version of Weihua's patch --
;; thanks. Now "*" and "#" will search for entire symbol at point,
;; including underscores, not just word at point.
;; - TODO addition.
;;
;; Version 0.2.5.1:
;; [jasonspiro3 at gmail.com:]
;; - Redefined viper-adjust-undo to do nothing. This way, in Insert
;; mode, typing then moving the cursor then typing more counts as
;; two separately undoable actions instead of one. Thanks to Weihua
;; JIANG and to max_ from IRC #emacs for the idea.
;; - Small extra TODO.
;;
;; Version 0.2.5.0:
;; [jasonspiro3 at gmail.com:]
;; I've ignored my local changes for too long. Here they are:
;; - Added keybindings from a Usenet post by Samuel Padgett.
;; - Made change ("cw", etc.) commands work more like Vim (my code).
;; - I removed (setq ex-cycle-other-window nil); although it is very
;; useful, it merely works around a problem with Viper. I plan to
;; discuss it with the Viper maintainer instead.
;; - Other changes and bugfixes from various people.
;;
;; Version 0.2.0.3:
;; [jasonspiro3 at gmail.com:]
;; - Added Brad's `viper-jump-to-tag-at-point'.
;;
;; Version 0.2.0.2:
;; [jasonspiro3 at gmail.com:]
;; - Small "C-w" keys and doc fixes.
;;
;; Version 0.2.0.1:
;; [cppjavaperl:]
;; - Added support for Visual Block mode (i.e., rectangle selection).
;; - Made "C-p" look for matches PRIOR to the cursor and added "C-n"
;; binding to look for matches BEFORE the cursor. This works more
;; like Vim does.
;; [jasonspiro3 at gmail.com:]
;; - Since Vimpulse has no website, I added a prominent pointer at
;; the top to the installation instructions.
;;
;; Version 0.2.0.0: Brad merged in several changes, including:
;; - Exit Visual mode when the mark deactivates.
;; - Changed the window manipulation to be global.
;; - Added "gf" (goto file at point).
;; - Added "\C-]" and "\C-t", tag jump & pop.
;; - Added a helper function for defining keys.
;; - Commented out `show-paren-function', what is it meant to do?
;;
;; Version 0.1.0.1: No code changes. Small documentation changes,
;; including updates on moving-left bug.
;;
;; Version 0.1: Initial release.
;;; Acknowledgements:
;; Special thanks to Brad Beveridge, the original author of Vimpulse.
;;
;; Thanks to:
;;
;; cppjavaperl <cppjavaperl at yahoo.com>
;; Fabian Brännström <f.braennstroem at gmx.de>
;; Frank Fischer <frank.fischer at s2001.tu-chemnitz.de>
;; John <jn at ngedit.com>
;; John J Foerch <jjfoerch at earthlink.net>
;; José Alfredo Romero L. <escherdragon at gmail.com>
;; Mieszko <sillyfox at yahoo.com>
;; rhinoryan
;; Rick Sladkey, author of rect-mark.el
;; Ryoichi Kanetaka <ryoichi.kanetaka at gmail.com>
;; Samuel Padgett
;; Štěpán Němec <stepnem at gmail.com>
;; Stephen Bach <stephen at sjbach.com>
;; Stian S.
;; Tim Harper <timcharper at gmail.com>
;; Toby Cubitt
;; Wang Xin
;; Weihua Jiang <weihua.jiang at gmail.com>
;;
;; and all the other people who have sent in bug reports and feedback.
;; Also, thanks to Michael Kifer and Viper's contributors.
;;
;; We love patches. Would you like to see your name here?
;; Please send code and/or documentation patches to the maintainer.
;; Ideas, comments, and test results are appreciated too.
;;; Bugs:
;; (We would appreciate it very much if you report bugs.)
;;
;; Known bugs:
;;
;; - Undo has problems in XEmacs.
;;; Development and documentation TODOs:
;; - Make sure I have added all stuff in Brad's Viper additions and
;; from my collection, then start documenting already. Once there
;; are even the simplest of docs (a nice keymap), people will have a
;; far easier time using Vimpulse and so I bet more will contribute.
;;
;; - Folding. This should be implemented as a separate Lisp library
;; usable for even non-Viper users. Which foldmethods to do first?
;; I personally only use foldmethod=marker, and even that rarely.
;;
;; - i_C-(I forgot the letter) should do (copy-from-above-command 1)
;; from misc.el.
;;
;; - Add :set spell / :set nospell that uses flyspell-mode.
;;
;; - Add support for tabs.el, a tabs mode that works sensibly (get it
;; from Emacs Lisp List).
;; - Minimum needed: :tabedit, :tabnext, :tabprevious.
;; - Since I'm emulating Vim, emulate its tab pages feature. So a
;; tab page should be able to hold one or more buffers.
;;
;; - Add Customize option to let users stop "C-r" from being Redo?
;;
;; - Copy more features from Brad's work in darcs and from vimpact
;; into Vimpulse.
;;
;; - Doc: look in Google chat log, find description of one-char-off
;; bug, see if it applies to this or to the not-yet-released
;; viper-x, and if to this, mention under Bugs.
;;
;; - Doc: list all new keys (and maybe all differences from Viper) in
;; Usage section.
;;
;; - Doc: describe all new keys in Usage section; can look at Vim
;; manual for ideas.
;;
;; - Modify how tramp works so it also automatically handles URLs
;; typed in the netrw syntax, e.g., http:// etc. But first ask tramp
;; upstream if they could please make those changes themselves.
;;
;; - Improve "CTRL-O" for jumping back in the jumplist and "CTRL-I" for
;; jumping forwards (for undoing one "CTRL-O"). The global mark ring
;; is not what I want. I wonder if Emacs' tags functionality allows
;; a jumplist. I wonder if Viper does tags like nvi does.
;; - Try code.google.com/p/ejumplist/source/browse/trunk/jumplist.el
;;
;; - On my PC (I run Ubuntu), if you start plain Vim and then press
;; "CTRL-O" many times, it starts opening recently opened files. Is
;; that useful? Should Vimpulse have persistent jump table
;; functionality like that, and if so, should it use recentf or
;; Vim's .viminfo file or some tag functionality in Emacs? How will
;; it interact with the fact that in Emacs, it's not traditional to
;; suddenly close files without warning?
;;
;; - Make sentence movement work like in Vim. I wonder if this can be
;; done by setting Viper options.
;; - In Vim, according to :help sentence, end of sentence is:
;; - ".", "?", or "!"
;; - then (optionally) one or more """, "'", ")", and "]"
;; characters
;; - then a newline, space, or tab.
;; - A paragraph or section boundary is also a sentence
;; boundary, but I bet Viper handles that, and if it doesn't,
;; it should.
;; - A paragraph begins after each truly empty line (no
;; whitespace chars on it) or after certain col-1 nroff
;; macros. A sentence begins after a form feed (^L), or
;; certain nroff macros, in column 1.
;; - The characters "{" and "}" sometimes affect paragraph
;; definitions. See :help paragraph.
;; - In Viper, on the other hand, I bet sentences are like in vi,
;; where tabs aren't whitespace, and you need at least two spaces
;; after the punctuation mark.
;;
;; - Try to get Vimpulse included with upstream Viper; also, ideally,
;; if you pressed "v" in Viper, Viper would offer to load Vimpulse.
;; (Likely to happen? Consider that Michael Kifer, the Viper
;; maintainer, told me he doesn't need Vim keys. Then again, maybe I
;; could convince him that it's worth it to ship Vim keys, for other
;; people's benefit. Also, consider that some of the code (like
;; Operator-Pending mode) addresses problems mentioned in viper.el.)
;;
;; - E-mail ridip <rdp at inthefaith.net> and ask him for his Vimpulse
;; contribs and his DVORAK stuff.
;;
;; - E-mail to Tromey for upload into ELPA? We'd have to redo this
;; when a new major version comes out. Or maybe we should just
;; contribute some auto-ELPA-management code. By the way, should we
;; move Vimpulse into CVS somewhere?
;;
;; - Maybe merge all feature requests that anyone has ever sent into a
;; "Feature requests" section here.
;;; Development plans:
;; The design plan for Vimpulse is for it to only emulate features
;; that are in Vim. Therefore, other features do not belong in
;; Vimpulse unless one can get the Vim people to implement those
;; features too.
;;
;; At the same time, Vimpulse should strive for customizability and
;; extensibility, so that the user can modify it just as easily as the
;; rest of Emacs.
;;; Undecided development questions:
;; - In Vimpulse, like in real Vim, "C-r" only does Redo in vi (command)
;; mode; in Insert mode it does something else. (In Vimpulse that
;; "something else" is reverse isearch.) Should it do reverse
;; isearch in Insert mode too?
;;
;; - With some delete commands, Viper shows a message like "Deleted 50
;; characters" in the minibuffer. Is that annoying?
;; - Update 1 month later: I hardly notice the message.
;; - Dear users: Do you think I should disable the message?
;;
;; - I want to allow buffer-switching without using the "C-x" key, since
;; "C-x b RET" an extremely large amount of times per day is
;; uncomfortable for my right pinky, which presses RET. There's
;; already :b, which seems to just invoke `switch-to-buffer'. Is this
;; right? Is it bad if I make Vimpulse emulate set autowrite=on
;; then write new multi-buffer code? What should the code's user
;; interface be like? I really should switch back to Vim for a day,
;; learn more about how it deals with multiple buffers at once (and
;; maybe also with tab pages) and emulate whatever of Vim's is most
;; convenient. What do you think of all the above?
;; - Update: IIRC, :set hidden lets you switch buffers w/o saving
;; - Update from Sebastien Rocca Serra: :set wildmenu plus
;; tab-completion makes :b very pleasant to use when you have
;; 50+ buffers open. Wildmenu is almost like iswitchb or ido.
;; - I wonder how well that stuff works with just a few buffers open.
;;
;; - Simulate Vim's set virtualedit=onemore option to make "C-x C-e"
;; possible without first advancing to next line?
;;
;; - Would it be bad to edit users' .viminfo files without asking
;; permission, or should some variable have to be customized on to do
;; such a thing?
;;
;; - Is there any need to implement Vim's new
;; [count]dk-can-go-past-top-of-file-without-error functionality (to
;; me, no need) or any related functionality?
;;
;; - What to do about XEmacs? It doesn't ship with woman. I wonder
;; if woman is in some XEmacs package?
;;; License:
;; 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 2 of the
;; License, or 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, write to the Free Software
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
;; 02111-1307, USA.
;;; Code:
(defconst vimpulse-version "0.5"
"The current version of Vimpulse")
(defun vimpulse-version ()
(interactive)
(message "Vimpulse version is %s" vimpulse-version))
;; load Viper
(defvar viper-mode t)
(defvar viper-inhibit-startup-message t)
(defvar viper-expert-level 5)
(defvar viper-want-ctl-h-help t)
(defvar viper-search-wrap-around t)
(require 'viper)
;; load undo-tree.el if available, with redo.el as fall-back
(unless (featurep 'undo-tree)
(condition-case nil
(require 'undo-tree)
(error (condition-case nil
(require 'redo)
(error nil)))))
(and (fboundp 'global-undo-tree-mode)
(global-undo-tree-mode 1))
;;; Customization group for Vimpulse
(defgroup vimpulse nil
"Vim emulation within Emacs."
:group 'emulations
:link '(custom-group-link "viper")
:prefix 'vimpulse-)
(defcustom vimpulse-want-change-state nil
"Whether commands like \"cw\" invoke Replace state, vi-like.
The default is to delete the text and enter Insert state,
like in Vim."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-change-undo t
"Whether commands like \"cw\" are undone in a single step.
On by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-C-u-like-Vim nil
"Whether C-u scrolls like in Vim, off by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-C-i-like-Vim t
"Whether C-i jumps forward like in Vim, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-quit-like-Vim t
"Whether :q quits the editor like in Vim, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-enhanced-paren-matching t
"Enhanced matching of parentheses, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-operator-pending-cursor t
"Whether the cursor changes in Operator-Pending mode, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-visual-block-untabify nil
"Whether Block mode may change tabs to spaces for fine movement.
Off by default."
:type 'boolean
:group 'vimpulse-visual)
(defcustom vimpulse-incremental-search t
"Use isearch for / and ?, on by default.")
(defcustom vimpulse-flash-delay 2
"Number of seconds to flash search matches.")
(defvar vimpulse-flash-timer nil
"Timer for flashing search results.")
(defcustom vimpulse-want-vi-keys-in-apropos t
"Whether to use vi keys in Apropos mode, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-vi-keys-in-buffmenu t
"Whether to use vi keys in Buffer menu, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-vi-keys-in-dired t
"Whether to use vi keys in Dired mode, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-vi-keys-in-Info t
"Whether to use vi keys in Info mode, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-want-vi-keys-in-help t
"Whether to use vi keys in Help mode, on by default."
:group 'vimpulse
:type 'boolean)
(defcustom vimpulse-fold-level 0
"Default fold level."
:type 'integer
:group 'vimpulse)
;; the secrets discovered from untold diggings among
;; the ruins of Customize code
(defun vimpulse-custom-value-p (symbol)
"Non-nil if SYMBOL has a customized value."
(or (get symbol 'customized-value)
(get symbol 'customized-face)
(get symbol 'saved-value)))
(defmacro vimpulse-setq-custom (sym val &rest body)
"Set the customized value of SYM to VAL."
`(progn
(prog1 (setq ,sym ,val) ; return VAL
(when (get ',sym 'custom-autoload)
(custom-load-symbol ',sym))
(put ',sym 'customized-value (list (custom-quote ,val))))
,(when body
`(vimpulse-setq-custom ,@body))))
(defmacro vimpulse-setq-custom-default (symbol value &rest body)
"Set the customized default value of SYMBOL to VALUE."
`(progn
(prog1 ,value ; return VALUE
(when (get ',symbol 'custom-autoload)
(custom-load-symbol ',symbol))
(put ',symbol 'standard-value (list (custom-quote ,value))))
,(when body
`(vimpulse-setq-custom-default ,@body))))
(defmacro vimpulse-setq (sym val &rest body)
"Set SYM to VAL, defaults included, unless SYM is customized.
SYM is unquoted. Returns VAL."
`(progn
(cond
;; customized value: just set custom standard value
((vimpulse-custom-value-p ',sym)
(vimpulse-setq-custom-default ,sym ,val))
;; customized variable: set custom and regular values
((custom-variable-p ',sym)
(vimpulse-setq-custom-default ,sym ,val)
(vimpulse-setq-custom ,sym ,val)
(setq-default ,sym ,val)
(setq ,sym ,val))
;; regular variable; set default and local values
(t
(setq-default ,sym ,val)
(setq ,sym ,val)))
,@(when body
`((vimpulse-setq ,@body)))))
;;; Declare and/or initialize variables
(defvar dabbrev--last-abbrev-location)
(defvar dabbrev--last-abbreviation)
(defvar dabbrev--last-direction)
(defvar dabbrev--last-expansion)
(defvar dabbrev--last-expansion-location)
(defvar isearch-forward)
(defvar isearch-lazy-highlight-end)
(defvar isearch-lazy-highlight-last-string)
(defvar isearch-lazy-highlight-start)
(defvar isearch-lazy-highlight-wrapped)
(defvar isearch-regexp)
(defvar isearch-string)
(defvar killed-rectangle nil) ; rect.el
(defvar show-paren-delay)
(defvar undo-tree-visualizer-map)
(defvar woman-use-own-frame)
(defvar woman-use-topic-at-point)
(defvar ex-token-alist) ; viper-ex.el
(defvar viper-mode-string)
(defvar vimpulse-viper-movement-cmds
'(viper-backward-Word viper-backward-char viper-backward-paragraph
viper-backward-sentence viper-backward-word
viper-beginning-of-line viper-command-argument
viper-digit-argument viper-end-of-Word viper-end-of-word
viper-exec-mapped-kbd-macro viper-find-char-backward
viper-find-char-forward viper-forward-Word viper-forward-char
viper-forward-paragraph viper-forward-sentence viper-forward-word
viper-goto-char-backward viper-goto-char-forward viper-goto-eol
viper-goto-line viper-line-to-bottom viper-line-to-middle
viper-line-to-top viper-next-line viper-previous-line
viper-scroll-down-one viper-scroll-down viper-scroll-up
viper-scroll-up-one viper-window-bottom viper-window-middle
viper-window-top vimpulse-end-of-previous-word
vimpulse-goto-first-line vimpulse-goto-definition
vimpulse-goto-line vimpulse-search-backward-for-symbol-at-point
vimpulse-search-forward-for-symbol-at-point vimpulse-jump-backward
vimpulse-jump-forward vimpulse-visual-toggle-char
vimpulse-visual-toggle-line vimpulse-visual-toggle-block)
"List of Viper/Vimpulse movement commands.")
(defvar vimpulse-core-movement-cmds
'(viper-backward-char
viper-next-line
viper-previous-line
viper-forward-char
viper-ex)
"List of Viper \"core\" movement commands.
These should be present in every mode, to avoid confusion.")
(defvar vimpulse-mark-list nil
"List of mark positions to jump to with `vimpulse-jump-forward'.
They are stored as markers, the current position first:
(car vimpulse-mark-list) = current position (last popped)
(cdr vimpulse-mark-list) = future positions (previously popped)
(cadr vimpulse-mark-list) = next position (to jump to)
In other words, a sort of \"reverse mark ring\": marks that are
popped off the mark ring, are collected here.")
(viper-deflocalvar vimpulse-local-marks-alist nil
"Association list of local marks.
Entries have the form (CHAR (FILE . POS)), where POS is a marker
or a character position.")
(defvar vimpulse-global-marks-alist nil
"Association list of global marks.
Entries have the form (CHAR (FILE . POS)), where POS is a marker
or a character position.")
(viper-deflocalvar vimpulse-replace-alist nil
"Alist of characters overwritten in Replace mode.
Used by `vimpulse-replace-backspace' to restore text.
The format is (POS . CHAR).")
(viper-deflocalvar vimpulse-exit-point nil
"Like `viper-insert-point', but when exiting Insert mode.")
(defvar vimpulse-last-command-event nil
"Value for overwriting `last-command-event'.
Used by `vimpulse-careful-pre-hook'.")
(defvar vimpulse-careful-alist nil
"Key bindings for which `vimpulse-careful-pre-hook' is active.
That is, `last-command-event' and `read-char' work differently
for these bindings. The format is (KEY-VECTOR . COMMAND).")
(defvar vimpulse-careful-map (make-sparse-keymap)
"Keymap of bindings overwritten by `vimpulse-map' et al.")
(defvar vimpulse-paren-overlay-open nil
"Overlay used to highlight the opening paren.")
(defvar vimpulse-paren-overlay-close nil
"Overlay used to highlight the closing paren.")
(defvar vimpulse-operators nil
"Operator commands defined with `vimpulse-define-operator'.")
(viper-deflocalvar vimpulse-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 vimpulse-operator-basic-map)
(defvar vimpulse-operator-remap-map (make-sparse-keymap))
(defvar vimpulse-operator-remap-alist nil
"Association list of command remappings in Operator-Pending mode.")
(defvar vimpulse-this-operator nil
"Current operator.
In general, motions and operators are orthogonal, with some exceptions:
\"cw\" and \"dw\" work on slightly different ranges, for example.
Motions can check this variable if they need to know what
operator receives their range. See also `vimpulse-this-motion'.")
(defvar vimpulse-this-motion nil
"Current motion.
In general, motions and operators are orthogonal, with some exceptions:
\"cc\" may indent the current line while \"cw\" may not, for example.
Operators may check this variable if they need to know what
motion produced the current range. See also `vimpulse-this-operator'.")
(defvar vimpulse-this-count nil
"Current count (operator count times motion count).")
(defvar vimpulse-this-motion-type nil
"Current motion type.
May be `block', `line', `inclusive', `exclusive' or nil.")
(defvar vimpulse-last-motion-type nil
"Last repeated range type.
May be `block', `line', `inclusive', `exclusive' or nil.")
(defvar vimpulse-last-operator nil
"Last repeated operator.
Used by `vimpulse-operator-repeat'.")
(defvar vimpulse-last-motion nil
"Last repeated motion.
Used by `vimpulse-operator-repeat'.")
(defvar vimpulse-visual-basic-map)
(defvar vimpulse-visual-remap-alist nil
"Association list of command remappings in Visual mode.")
(put 'vimpulse-visual-basic-map
'remap-alist 'vimpulse-visual-remap-alist)
(viper-deflocalvar vimpulse-visual-mode nil
"Current Visual mode: may be nil, `char', `line' or `block'.")
(viper-deflocalvar vimpulse-visual-global-vars nil
"List of variables that were global.")
(viper-deflocalvar vimpulse-visual-local-vars
'(cua-mode
mark-active
transient-mark-mode
zmacs-regions)
"System variables that are reset for each Visual session.")
(viper-deflocalvar vimpulse-visual-vars-alist nil
"Alist of old variable values.")
(viper-deflocalvar vimpulse-visual-last nil
"Last active Visual mode.
May be `char', `line', `block' or nil.")
(viper-deflocalvar vimpulse-visual-previous-state 'viper-state
"Previous state before enabling Visual mode.
This lets us revert to Emacs state in non-vi buffers.")
(viper-deflocalvar vimpulse-visual-region-expanded nil
"Whether region is expanded to the Visual selection.")
(viper-deflocalvar vimpulse-visual-point nil
"Last expanded `point' in Visual mode.")
(viper-deflocalvar vimpulse-visual-mark nil
"Last expanded `mark' in Visual mode.")
(viper-deflocalvar vimpulse-visual-overlay nil
"Overlay for Visual selection.
In XEmacs, this is an extent.")
(viper-deflocalvar vimpulse-visual-block-overlays nil
"Overlays for Visual Block selection.")
(viper-deflocalvar vimpulse-visual-whitespace-overlay nil
"Overlay encompassing text inserted into the buffer
to make Block selection at least one column wide.")
(viper-deflocalvar vimpulse-undo-list-pointer nil
"Everything up to this mark is united in the undo-list.")
(defvar vimpulse-visual-height nil
"Height of last Visual selection.")
(defvar vimpulse-visual-width nil
"Width of last Visual selection.")
(defvar vimpulse-visual-insert-coords nil
"List with (I-COM UL-POS COL NLINES), where
I-COM is the insert command (?i, ?a, ?I or ?A),
UL-POS is the position of the upper left corner of the region,
COL is the column of insertion, and
NLINES is the number of lines in the region.")
(defvar vimpulse-movement-cmds
'(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
cua-cancel digit-argument 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 keyboard-quit mouse-drag-region
mouse-save-then-kill mouse-set-point mouse-set-region
move-beginning-of-line move-end-of-line next-line previous-line
scroll-down scroll-up undo universal-argument up-list
vimpulse-end-of-previous-word vimpulse-goto-definition
vimpulse-goto-first-line vimpulse-goto-line
vimpulse-visual-block-rotate vimpulse-visual-exchange-corners
vimpulse-visual-reselect vimpulse-visual-restore
vimpulse-visual-toggle-block vimpulse-visual-toggle-line
vimpulse-visual-toggle-char viper-backward-Word
viper-backward-char viper-backward-paragraph
viper-backward-sentence viper-backward-word
viper-beginning-of-line viper-digit-argument viper-end-of-Word
viper-end-of-word viper-exec-mapped-kbd-macro
viper-find-char-backward viper-find-char-forward
viper-forward-Word viper-forward-char viper-forward-paragraph
viper-forward-sentence viper-forward-word viper-goto-char-backward
viper-goto-char-forward viper-goto-eol viper-goto-line
viper-insert viper-intercept-ESC-key viper-line-to-bottom
viper-line-to-middle viper-line-to-top viper-next-line
viper-paren-match viper-previous-line viper-search-Next
viper-search-backward viper-search-forward viper-search-next
viper-window-bottom viper-window-middle viper-window-top)
"List of commands that move point.
If listed here, the region is not expanded to the
Visual selection before the command is executed.")
(defvar vimpulse-newline-cmds
'(cua-copy-region cua-cut-region cua-delete-region delete-region
exchange-point-and-mark execute-extended-command kill-region
kill-ring-save vimpulse-Put-and-indent vimpulse-put-and-indent
vimpulse-visual-exchange-corners viper-Put-back viper-put-back)
"Non-operator commands needing trailing newline in Visual Line mode.
In most cases, it's more useful not to include this newline in
the region acted on.")
(defvar vimpulse-search-prompt nil
"String to use for vi-like searching.")
(defvar vimpulse-auxiliary-modes nil
"List of Emacs modes with state bindings.
The topmost modes have the highest priority.")
(defvar vimpulse-auxiliary-modes-alist
'((vi-state . viper-vi-auxiliary-modes)
(insert-state . viper-insert-auxiliary-modes)
(replace-state . viper-replace-auxiliary-modes)
(emacs-state . viper-emacs-auxiliary-modes)))
(defvar viper-vi-auxiliary-modes nil)
(defvar viper-insert-auxiliary-modes nil)
(defvar viper-replace-auxiliary-modes nil)
(defvar viper-emacs-auxiliary-modes nil)
;;; Carefully set Viper/woman variables
(defun vimpulse-configure-variables ()
"Set various variables, unless customized."
;; can backspace past start of insert/line