Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions extensions/vi-mode/README.md
Original file line number Diff line number Diff line change
@@ -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`
102 changes: 55 additions & 47 deletions extensions/vi-mode/options.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)))
6 changes: 2 additions & 4 deletions extensions/vi-mode/vi-mode.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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))