(in-package :editor) (defun vim-var-key (name type) (cons name type)) (defun vim-var-lookup (name type #| &optional create |#) (let* ((key (vim-var-key name type)) (var (gethash key *vim-vars*))) (cond (var var) #+nil (create (setf (gethash key *vim-vars*) (make-instance 'vim-var :name name :type type))) (t (error "vim-var-lookup: vim-var ~S of type ~S not found" name type))))) (defun vim-var-selector (type) (multiple-value-bind (selector present) (gethash type *vim-var-selectors*) (if present (funcall selector) (error "vim-var-selector: unknown selector: ~S" type)))) (defun vim-var (name type) (let ((var (vim-var-lookup name type))) (if var (let ((selector (vim-var-selector type))) (multiple-value-bind (selected-val present) (gethash selector (values-of var)) (if present selected-val (setf (gethash selector (values-of var)) (funcall (init-func-of var)))))) (error "vim-var: vim-var ~S of type ~S not found" name type)))) (defun vim-var-set (name type value) (setf (gethash (vim-var-selector type) (values-of (vim-var-lookup name type))) value)) (defsetf vim-var vim-var-set) (defmacro def-vim-var-definer (definer-name type selector) `(progn (setf (gethash ,type *vim-var-selectors*) (lambda () ,selector)) (defmacro ,definer-name (name init-code &optional (doc "Vim variable")) `(progn (setf (gethash (vim-var-key ',name ,,type) *vim-vars*) (make-instance 'vim-var :name ',name :type ,,type :values (make-hash-table) :init-func (lambda () ,init-code) :doc ,doc)) (eval-when (:compile-toplevel :load-toplevel :execute) (define-symbol-macro ,name (vim-var ',name ,,type))))))) (def-vim-var-definer def-vim-var :global t) (def-vim-var-definer def-vim-buffer-var :buffer (current-buffer)) (def-vim-buffer-var b-vim-point-before-movement (copy-point (current-point)) "The point before a movement command.") (def-vim-buffer-var b-vim-point-after-movement (copy-point (current-point)) "The point after a movement command.") (def-vim-buffer-var b-vim-exclusiveness :exclusive "Defines the in/exclusiveness of the current movement command.") (def-vim-buffer-var b-vim-wiseness :linewise "Defines the :linewise/characterwise-ness of the current movement command.") (def-vim-buffer-var b-vim-pending-command nil "Run this command after a movement command. Used to implement things like dj.") (def-vim-var v+hlsearch t "Are searches highlighted?") #+nil ; I don't use this just yet. (def-vim-var v+search-expr nil "String to highlight")