From 4abf032369fcdfa65559dfa150773d9a89343d0e Mon Sep 17 00:00:00 2001 From: Eitaro Fukamachi Date: Mon, 14 Aug 2023 22:47:30 +0900 Subject: [PATCH] Add "number" option to show line numbers in vi-mode. Also, stop defining functions for each option, because 'number' conflicts with the 'cl' package. (ref #908) --- extensions/vi-mode/README.md | 36 ++++++++++- extensions/vi-mode/options.lisp | 102 +++++++++++++++++--------------- extensions/vi-mode/vi-mode.lisp | 6 +- 3 files changed, 91 insertions(+), 53 deletions(-) diff --git a/extensions/vi-mode/README.md b/extensions/vi-mode/README.md index 715bf0a0d..64e163b2d 100644 --- a/extensions/vi-mode/README.md +++ b/extensions/vi-mode/README.md @@ -1,8 +1,40 @@ # vi-mode +## Usage -To enable,add `~/.lem/init.lisp` +To enable, add the following code to `~/.lem/init.lisp`: -``` +```common-lisp (lem-vi-mode:vi-mode) ``` + +## Defining keymaps + +```common-lisp +;; NORMAL mode +(define-key lem-vi-mode:*command-keymap* "q" 'quit-window) +(define-key lem-vi-mode:*command-keymap* "Space @" 'paredit-splice) + +;; INSERT mode +(define-key lem-vi-mode:*insert-keymap* "(" 'paredit-insert-paren) +(define-key lem-vi-mode:*insert-keymap* ")" 'paredit-close-parenthesis) +``` + +## Options + +Vi-mode options are global settings, similarly to Vim. + +They can be set with `:set` command, or a function `vi-option-value` in `~/.lem/init.lisp`, like: + +```common-lisp +(setf (lem-vi-mode:vi-option-value "autochdir") t) +``` + +Here's a list of all options currently implemented: + +* `autochdir`: Boolean to change the current directory to the buffer's directory automatically. + * Default: `nil` (don't change the current directory) + * Aliases: `acd` +* `number`: Boolean to show the line number. + * Default: `nil` (don't show) + * Aliases: `nu` diff --git a/extensions/vi-mode/options.lisp b/extensions/vi-mode/options.lisp index dec0981dc..7dd0248d4 100644 --- a/extensions/vi-mode/options.lisp +++ b/extensions/vi-mode/options.lisp @@ -24,10 +24,7 @@ :vi-option-documentation :reset-vi-option-value :toggle-vi-option-value - :execute-set-command - - ;; Options - :autochdir)) + :execute-set-command)) (in-package :lem-vi-mode/options) (defstruct vi-option @@ -57,27 +54,34 @@ (lem:editor-error "Unknown option: ~A" name)) option))) +(defun ensure-option (name-or-option &optional (error-if-not-exists t)) + (etypecase name-or-option + (vi-option name-or-option) + (string (get-option name-or-option error-if-not-exists)))) + (defun vi-option-value (option) - (values - (if-let (getter (vi-option-getter option)) - (funcall getter) - (vi-option-%value option)) - (vi-option-name option))) + (let ((option (ensure-option option))) + (values + (if-let (getter (vi-option-getter option)) + (funcall getter) + (vi-option-%value option)) + (vi-option-name option)))) (defun (setf vi-option-value) (new-value option) - (with-slots (type set-hook) option - (unless (typep new-value type) - (lem:editor-error "Option '~A' accepts only ~S, but given ~S" - (vi-option-name option) type new-value)) - (let ((old-value (vi-option-value option))) - (multiple-value-prog1 - (values - (setf (vi-option-%value option) new-value) - (vi-option-name option) - old-value - t) - (when set-hook - (funcall set-hook new-value)))))) + (let ((option (ensure-option option))) + (with-slots (type set-hook) option + (unless (typep new-value type) + (lem:editor-error "Option '~A' accepts only ~S, but given ~S" + (vi-option-name option) type new-value)) + (let ((old-value (vi-option-value option))) + (multiple-value-prog1 + (values + (setf (vi-option-%value option) new-value) + (vi-option-name option) + old-value + t) + (when set-hook + (funcall set-hook new-value))))))) (defun reset-option-value (option) (setf (vi-option-value option) @@ -130,38 +134,34 @@ (setf (vi-option-value option) t)))))) (defmacro define-vi-option (name (default &key (type t) aliases) &rest others) + (check-type name string) (once-only (default) - (with-gensyms (option alias new-value) - (let ((name-str (string-downcase name))) - `(progn - (check-type ,default ,type) - (dolist (,alias ',aliases) - (setf (gethash ,alias *option-aliases*) ,name-str)) - (let ((,option - (make-vi-option :name ,name-str - :%value ,default - :default ,default - :type ',type - :aliases ',aliases - :getter ,(when-let (getter-arg (find :getter others :key #'car)) - `(lambda () ,@(rest getter-arg))) - :set-hook ,(when-let (set-hook-arg (find :set-hook others :key #'car)) - `(lambda ,@(rest set-hook-arg))) - :documentation ,(when-let (doc-arg (find :documentation others :key #'car)) - (second doc-arg))))) - (setf (gethash ,name-str *options*) ,option) - (defun ,name () - (vi-option-value (get-option ,name-str))) - (defun (setf ,name) (,new-value) - (setf (vi-option-value (get-option ,name-str)) ,new-value)))))))) + (with-gensyms (option alias) + `(progn + (check-type ,default ,type) + (dolist (,alias ',aliases) + (setf (gethash ,alias *option-aliases*) ,name)) + (let ((,option + (make-vi-option :name ,name + :%value ,default + :default ,default + :type ',type + :aliases ',aliases + :getter ,(when-let (getter-arg (find :getter others :key #'car)) + `(lambda () ,@(rest getter-arg))) + :set-hook ,(when-let (set-hook-arg (find :set-hook others :key #'car)) + `(lambda ,@(rest set-hook-arg))) + :documentation ,(when-let (doc-arg (find :documentation others :key #'car)) + (second doc-arg))))) + (setf (gethash ,name *options*) ,option)))))) (defun auto-change-directory (buffer-or-window) (change-directory (etypecase buffer-or-window (lem:buffer (lem:buffer-directory buffer-or-window)) (lem:window (lem:buffer-directory (lem:window-buffer buffer-or-window)))))) -(define-vi-option autochdir (nil :type boolean :aliases ("acd")) - (:documentation "A flag on whether change the current directory to the buffer directory automatically. +(define-vi-option "autochdir" (nil :type boolean :aliases ("acd")) + (:documentation "Boolean to change the current directory to the buffer's directory automatically. Default: nil Aliases: acd") (:set-hook (new-value) @@ -176,3 +176,11 @@ (dolist (window (lem:window-list)) (lem:remove-hook (lem-core::window-switch-to-buffer-hook window) 'auto-change-directory) (lem:remove-hook (lem-core:window-leave-hook window) 'auto-change-directory)))))) + +(define-vi-option "number" (nil :type boolean :aliases ("nu")) + (:documentation "Boolean to show the line number. + Default: nil + Aliases: nu") + (:getter (lem:variable-value 'lem/line-numbers:line-numbers :global)) + (:set-hook (new-value) + (setf (lem:variable-value 'lem/line-numbers:line-numbers :global) new-value))) diff --git a/extensions/vi-mode/vi-mode.lisp b/extensions/vi-mode/vi-mode.lisp index e313d7286..48024e078 100644 --- a/extensions/vi-mode/vi-mode.lisp +++ b/extensions/vi-mode/vi-mode.lisp @@ -4,12 +4,10 @@ :lem-vi-mode/core :lem-vi-mode/ex) (:import-from :lem-vi-mode/options - :autochdir) + :vi-option-value) (:export :vi-mode :define-vi-state :*command-keymap* :*insert-keymap* :*ex-keymap* - - ;; Options - :autochdir)) + :vi-option-value))