(in-package :editor) (defmethod bind-vim ((name string) key mode) (pushnew key *bound-vim-commands*) (bind-key name key :mode mode)) (defmethod bind-vim ((name string) (keys list) mode) (dolist (key keys) (bind-vim name key mode))) (defmethod bind-vim ((name string) (keys string) mode) (bind-vim name (make-array (list (length keys)) :initial-contents keys) mode)) (defun bind-vim-command (name arg) (bind-vim name arg "Vim Command")) (defun bind-vim-insert (name arg) (bind-vim name arg "Vim Insert")) ;; Enter / Exit the modes ;; Under Windows use Ctrl-Alt-Escape. (bind-key "Vim Command Mode" #\Shift-Ctrl-Escape :global :emacs) ; (bind-key "Vim Mode" #\Ctrl-[ :global :emacs) (bind-vim-command "Exit Vim Mode" #\Shift-Ctrl-Escape) (bind-vim-command "Vim Insert Mode" #\i) (bind-vim-insert "Vim Command Mode" #\Ctrl-[) ;; Bind keys ;;; counts; may change later; for now just use Argument Digit ; (bind-vim-command "Argument Digit" '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)) ;;; motion (def-vim-move "Vim Next Line" (p) :linewise :inclusive "" "" (next-line-command p)) (def-vim-move "Vim Previous Line" (p) :linewise :inclusive "" "" (previous-line-command p)) (bind-vim-command "Vim Next Line" '(#\j #\down #\ctrl-\j #\return #\ctrl-\n)) (bind-vim-command "Vim Previous Line" '(#\k #\up #\ctrl-\p)) (bind-vim-command "Backward Character" '(#\h #\left #\ctrl-\h #\backspace)) (bind-vim-command "Forward Character" '(#\l #\right #\space)) (bind-vim-command "Forward Word" #\w) (bind-vim-command "Backward Word" #\b) (def-vim-move "Vim Goto Line or End of File" (p) :linewise :inclusive "" "" (if p (editor::goto-line-command p) (editor::end-of-buffer-command nil))) (bind-vim-command "Vim Goto Line or End of File" #\G) (bind-vim-command "Scroll Window Down" #\Ctrl-\f) (bind-vim-command "Scroll Window Up" #\Ctrl-\b) (bind-vim-command "Vim Scroll Window Up" '(#\Ctrl-\y #\Shift-\Up)) (bind-vim-command "Vim Scroll Window Down" '(#\Ctrl-\e #\shift-\Down)) (bind-vim-command "Top of Window" #\H) (bind-vim-command "Bottom of Window" #\L) (bind-vim-command "Move to Window Line" #\M) (bind-vim-command "Line to Top of Window" "zt") (def-vim-change "Vim Delete Next Character" (p) "" "" (delete-next-character-command p)) (bind-vim-command "Vim Repeat" #\.) (bind-vim-command "Vim Delete Next Character" #\x) (bind-vim-command "Delete Previous Character" #\X) (bind-vim-command "Forward Form" #\)) (bind-vim-command "Backward Form" #\() (bind-vim-command "Forward List" #\Ctrl-\)) (bind-vim-command "Backward List" #\Ctrl-\() (bind-vim-command "Vim Append Text at End of Line" #\A) (bind-vim-command "Vim Insert Text at Beginning of Line" #\I) ;(bind-vim-command "What Cursor Position" '(#(#\g #\Ctrl-\Meta-\g))) ; (bind-vim-command "vim beginning of line or collect count" #\0) (bind-vim-command "Beginning of Line" '(#\Home #\0)) (bind-vim-command "End of Line" '(#\$ #\end)) ;; action + motion commands (def-vim-movement-pending "Vim Delete Motion" (begin end) "" "" (format t "~S ~S~%" begin end) ; (set-current-mark end) ; #+nil ; (save-excursion (set-current-mark begin) (move-point (current-point) end) (kill-region-command nil) ; ) (move-point (current-point) begin)) (bind-vim-command "Vim Delete Motion" #\d) ;; repeat ;(bind-vim-command "Vim Repeat Previous Command" #\.) ;; registers ;(bind-vim-command "Vim Read Register Name" #\") (bind-vim-command "Vim Open Line Down" #\o) (bind-vim-command "Vim Open Line Up" #\O) (bind-vim-command "Undo" #\u) (bind-vim-command "Lowercase Word" "~w") (bind-vim-command "Lowercase Region" "vu") (bind-vim-command "Uppercase Region" "vU") (bind-vim-command "Indent Rigidly" ">>") (bind-vim-command "Delete Indentation" #\J) (bind-vim-command "Back to Indentation" #\^) (bind-vim-command "New Buffer" ":n") (bind-vim-command "New Window" #(#\Ctrl-\w #\n)) (bind-vim-command "Next Ordinary Window" #(#\Ctrl-\w #\j)) (bind-vim-command "Previous Window" #(#\Ctrl-\w #\k)) (bind-vim-command "Delete Window" #(#\Ctrl-\w #\c)) (bind-vim-command "ISearch Forward Regexp" #\/) (bind-vim-command "ISearch Backward Regexp" #\?) (bind-vim-command "List Matching Lines" ":gp") ; not in Vim, exactly (bind-vim-command "Delete Matching Lines" ":gd") ; not in Vim (bind-vim-command "Regexp Forward Search" #\Ctrl-\/) (bind-vim-command "Regexp Reverse Search" #\Ctrl-\?) ;;; Yank/Put aka Cut/Paste aka Kill/Yank (bind-vim-command "Kill Line" #\D) (bind-vim-command "Un-Kill" #\p) ; (bind-vim-command "Kill Next Word" "dw") (defun add-return (&rest list) (apply #'concatenate 'string (mapcar #'string (append list '(#\Return))))) (bind-vim-command "Save File" (add-return ":w")) ; (bind-vim-command "Save File" '((":w" #\Return))) (bind-vim-command "Vim Save All Files" (add-return ":wa")) (bind-vim-command "Vim Save All Files And Exit" (add-return ":wqa")) (bind-vim-command "Write File" ":w ") (bind-vim-command "Wfind file" ":e ") (bind-vim-command "Revert Buffer" ":e!") (bind-vim-command "Insert File" ":r ") (bind-vim-command "List Buffers" (add-return ":ls")) (bind-vim-command "Select Buffer" ":b ") (bind-vim-command "Circulate Buffers" (add-return ":bn")) (bind-vim-command "Beginning of Defun" "[\\") (bind-vim-command "End of Defun" "]\\") (bind-vim-command "Find Source" #\Ctrl-\]) (bind-vim-command "Continue Tags Search" (add-return ":tn")) (bind-vim-command "View Source Search" (add-return ":ts")) (defun restore-default-highlighting () ;; There may be a better way to do this. Like remembering all the ;; highlighting we delete and replace, and restoring it. But this seems ;; to work pretty well and pretty quickly, on the small files I've edited ;; so far. (font-lock-fontify-buffer-command nil)) (defun highlight-search () (when *last-search-string* (restore-default-highlighting) (let* ((buffer (current-buffer)) (start (buffers-start buffer)) (end (buffers-end buffer))) ;; For some reason the highlighting doesn't show up unless I use this macro. ??? (with-hidden-font-lock-changes buffer (with-point ((point start :temporary) (form-start start :temporary)) (let ((pattern (make-fsa *last-search-string*))) (loop (let ((length (find-regexp-pattern point pattern t end))) (unless length (return)) (move-point form-start point) (character-offset point length) (font-lock-unfontify-region form-start point) (font-lock-apply-highlight form-start point *font-lock-inverse-face*))))) ) ))) ;;; Not Vim (bind-vim-command "Evaluate Defun" ",x") ;;; Vim Insert mode ; (bind-vim-insert "Indent New Line" #\Return) ; (bind-vim-insert "New Line" #\Newline) ; (bind-vim-insert "New Line" #\Return) ;;; Larry's favorite mappings (bind-vim-command "Vim Save All Files" #\Ctrl-F12) (bind-vim-insert "Vim Save All Files" #\Ctrl-F12) (bind-vim-command "List Buffers" #\F7) (bind-vim-insert "List Buffers" #\F7) (bind-vim-command "Circulate Buffers" #\Ctrl-F10) ;;; Ignore everything not defined (defun vim-command-char-p (char &optional (seq *bound-vim-commands*)) (find-if (lambda (item) (or (eql char item) (and (not (characterp item)) (not (keywordp item)) (vim-command-char-p char item)))) seq)) (defmethod vim-ignore ((char character)) (unless (vim-command-char-p char) ; (format t "Ignoring ~S~%" char) (bind-key "Illegal" char :mode "Vim Command"))) (defmethod vim-ignore ((char integer)) (vim-ignore (code-char char))) (loop for char across "abcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()_-+=[]{}\\|;':\",./<>?" do (vim-ignore char) if (both-case-p char) do (vim-ignore (char-upcase char))) ; Neither of these work; both expect Major Modes. :( ; (pushnew "Vim Command" *default-new-buffer-modes*) ; (pushnew "Vim Command" (variable-value "Default Modes")) #+nil (progn (defun foo (buffer enter) (format t "buffer is ~S, enter is ~S~%" buffer enter)) (add-hook 'foo 'vim-insert-mode-hook) (add-global-hook vim-insert-mode-hook 'foo) (remove-global-hook vim-insert-mode-hook 'foo) ) ; progn (defadvice (incremental-search-somehow after :after) (direction) (declare (ignorable direction)) (when v+hlsearch (highlight-search)))