Skip to content
A very simple simulation of the kakoune editor inside of emacs.
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
LICENSE Add license Mar 6, 2019
README.org
kakoune-exchange.el Change prefix from kak/ to kakoune- and add requires to all files Apr 24, 2019
kakoune-unimpaired.el
kakoune-utils.el Change prefix from kak/ to kakoune- and add requires to all files Apr 24, 2019
kakoune.el Change prefix from kak/ to kakoune- and add requires to all files Apr 24, 2019

README.org

kakoune.el

A very simple simulation of kakoune inside of emacs. Most of the heavy lifting is provided by ryo-modal-mode, multiple-cursors.el, and expand-region. For extended customization, it is recommended that you install these packages and customize their interfaces directly.

Installation

Users of use-package and straight.el users can simply call

(use-package kakoune
  :straight (kakoune :host github :repo "jmorag/kakoune.el"))

Once this package hopefully makes its way to MELPA, the straight argument will be omittable. Otherwise, you can manually add kakoune.el to your load-path and call (require 'path/to/kakoune.el).

Goals

This is not meant to be a feature-complete emulation of kakoune, like evil is to vim. Evil is a massive undertaking, which reimplements a huge number of editing primitives from scratch. By contrast, kakoune.el uses emacs’s native behavior wherever possible. In particular, it binds absolutely no keys in “insert mode,” letting you gradually adjust to “normal mode” at your own pace. To actually access normal mode, you can either call (ryo-modal-mode) with M-x, or bind a key globally. For the true modal experience: (global-set-key (kbd "<escape>") 'ryo-modal-mode).

Notable differences from Kakoune

  • The ‘v’ family of commands is not implemented here. By default, ‘v’ is bound to expand-region, which I personally find vastly more useful.
  • Searching is very different. A cursory glance at evil’s evil-search-forward function suggests that implementing a search model where ‘n’ and ‘N’ take you forwards and backwards in the search ring while not in isearch-mode is non-trivial. I just use emacs’s native incremental search with C-s and C-r. If I’m wrong about getting ‘n’ and ‘N’ functionality being difficult, though, please let me know.
  • This package also includes a couple bindings from evil-unimpaired and evil-exchange that aren’t present in the original.
  • ‘q’ and ‘Q’ don’t toggle and execute macros. This emacswiki article seems to suggest that it’s possible to have one key start and end a macro, but it’s been buggy in my experience, so I just use the default C-x ( and friends.
  • ’;’ doesn’t shrink regions by default. This is simply my personal preference. You can get this behavior with (ryo-modal-key ";" 'kakoune-deactivate-mark).
  • ‘>’ and ‘<’ behave normally on when the region is active, but when given a count when the region is inactive, they indent that many lines instead of indenting the current line that many times. This is also my personal preference, but if anyone wants kakoune’s default behavior for this, open an issue and I’ll change it.
  • I was never a full time Kakoune user, so there will certainly be many other small things that aren’t covered here. Please open issues or PR’s if you feel that including omissions would be useful to you or others.

Configuration

The following is my entire configuration that I use every day with respect to overriding and extending the functionality provided by this package.

(use-package kakoune
  :straight (kakoune :host github :repo "jmorag/kakoune.el")
  ;; fd to escape insert mode is something I picked up from trying Spacemacs and can't shake
  :chords ("fd" . ryo-enter)
  ;; Having a non-chord way to escape is important, since key-chords don't work in macros
  :bind ("C-z" . ryo-modal-mode)
  :hook (after-init . my/kakoune-setup)
  :config
  (defun my/kakoune-setup ()
      "Call kakoune-setup-keybinds and then add some personal config."
      (kakoune-setup-keybinds)
      (setq ryo-modal-cursor-type 'box)
      (add-hook 'prog-mode-hook #'ryo-enter)
      (define-key ryo-modal-mode-map (kbd "SPC h") 'help-command)
      ;; Access all C-x bindings easily
      (define-key ryo-modal-mode-map (kbd "z") ctl-x-map)
      (ryo-modal-keys
       ("," save-buffer)
       ("P" counsel-yank-pop)
       ("m" mc/mark-next-like-this)
       ("M" mc/skip-to-next-like-this)
       ("n" mc/mark-previous-like-this)
       ("N" mc/skip-to-previous-like-this)
       ("M-m" mc/edit-lines)
       ("*" mc/mark-all-like-this)
       ("v" er/expand-region)
       ("C-v" set-rectangular-region-anchor)
       ("M-s" mc/split-region)
       (";" (("q" delete-window)
             ("v" split-window-horizontally)
             ("s" split-window-vertically)))
       ("C-h" windmove-left)
       ("C-j" windmove-down)
       ("C-k" windmove-up)
       ("C-l" windmove-right)
       ("C-u" scroll-down-command :first '(deactivate-mark))
       ("C-d" scroll-up-command :first '(deactivate-mark)))))

;; This overrides the default mark-in-region with a prettier-looking one,
;; and provides a couple extra commands
(use-package visual-regexp
  :ryo
  ("s" vr/mc-mark)
  ("?" vr/replace)
  ("M-/" vr/query-replace))

;; Emacs incremental search doesn't work with multiple cursors, but this fixes that
(use-package phi-search
  :bind (("C-s" . phi-search)
         ("C-r" . phi-search-backward)))

;; Probably the first thing you'd miss is undo and redo, which requires an extra package
;; to work like it does in kakoune (and almost every other editor).
(use-package undo-tree
  :config
  (global-undo-tree-mode)
  :ryo
  ("u" undo-tree-undo)
  ("U" undo-tree-redo)
  ("SPC u" undo-tree-visualize)
  :bind (:map undo-tree-visualizer-mode-map
              ("h" . undo-tree-visualize-switch-branch-left)
              ("j" . undo-tree-visualize-redo)
              ("k" . undo-tree-visualize-undo)
              ("l" . undo-tree-visualize-switch-branch-right)))

It’s kind of a lot, but it does provide a good example of how to override defaults and bind your own keys to your own commands. I use this daily, along with the rest of the commands provided by the package, and am very happy with it.

Known bugs

  • There will be many commands that, when run for the first time with multiple active selections, will prompt you “Run <command> for all cursors? (y/n).” Hitting ‘y’ will add the command to an .mc-lists file in your .emacs.d and save your preference. There should be a way to add all the kakoune-* functions to this list by default, but because ryo adds hashes to the beginnings of commands, this isn’t as easy as it could be. This problem is usually just a one-time annoyance, but it can be irritating. I would gladly accept a PR to fix it.
  • Certain commands, like kakoune-replace-char and kakoune-select-to-char prompt for input once per cursor, instead of using the first input for each one. This behavior is unlike Kakoune’s but shouldn’t be. Fixing it shouldn’t be too difficult, but requires more knowledge of multiple-cursors.el’s implementation than I have.
  • When you first download this package, it is possible that non-primary cursors will have a weird color in insert mode. I have no idea why that is, but restarting emacs should take care of it.
You can’t perform that action at this time.