• Stars
    star
    271
  • Rank 151,717 (Top 3 %)
  • Language
    Emacs Lisp
  • Created about 9 years ago
  • Updated 11 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Modal editing your way

Modalka

License GPL 3 MELPA CI

What is this?

This is a building kit to help switch to modal editing in Emacs.

In this article I use Vi-inspired terms when I refer to the modes of operation:

  • In the normal mode you manipulate existing text and keystrokes typically result in editing operations instead of insertion of characters.

  • In the insert mode keystrokes insert the corresponding characters, i.e. it's how Emacs works by default.

What Modalka is not

  • Modalka does not introduce a new keyboard layout for the normal mode, you set it up yourself.

  • Modalka does not provide new commands for editing.

Why should I use it then?

Modal editing is more efficient, but most importantly, it is better for health. This package allows its users to switch from tiring Ctrl-based key combinations to editing through normal typing. The transition can be gradual and the user can define their own layout.

Installation

The package is available via MELPA, so you can just type M-x package-install RET modalka RET.

If you would like to install the package manually, download or clone it and put on Emacs' load-path. Then you can require it in your init file like this:

(require 'modalka)

Example of use

Here is a simple collection of translations that an Emacs user could easily adopt:

(modalka-define-kbd "W" "M-w")
(modalka-define-kbd "Y" "M-y")
(modalka-define-kbd "a" "C-a")
(modalka-define-kbd "b" "C-b")
(modalka-define-kbd "e" "C-e")
(modalka-define-kbd "f" "C-f")
(modalka-define-kbd "g" "C-g")
(modalka-define-kbd "n" "C-n")
(modalka-define-kbd "p" "C-p")
(modalka-define-kbd "w" "C-w")
(modalka-define-kbd "y" "C-y")
(modalka-define-kbd "SPC" "C-SPC")

One can type M-x modalka-mode to try it. When in the normal mode (modalka-mode) with such a setup, two lines of text can be killed like this: SPC n n w. Note that Modalka can translate sequential key bindings such as x ;, too.

Numeric prefixes can also be added:

(modalka-define-kbd "2" "C-2")

Now twenty-two lines can be killed with SPC 2 2 n w.

For an example of a complete setup see this.

Usage

Modalka is implemented as a minor mode called modalka-mode. This section describes how to set up efficient modal editing and provides some tips.

How to define translations

There is a set of functions to define key translations and to remove them:

  • modalka-define-key
  • modalka-remove-key

Here are the versions that wrap their arguments with kbd:

  • modalka-define-kbd
  • modalka-remove-kbd

Using these functions it's easy to setup a translation map.

Note that the target key binding cannot be a prefix key:

(modalka-define-kbd "x" "C-x") ;; will not work

Translations involving prefix keys will be ignored.

If you want to bind a command in modalka-mode without performing a keybinding translation, remember that modalka-mode is just a normal minor mode which has an associated key map called modalka-mode-map. So you can do the following:

(define-key modalka-mode-map (kbd "Q") #'my-command)

Using this approach it is possible to remap a prefix key like this:

(define-key modalka-mode-map "x" ctl-x-map)
(define-key ctl-x-map (kbd "e") #'eval-last-sexp)
(define-key ctl-x-map (kbd "s") #'save-buffer)

How to activate the minor mode

One should bind a key to toggle modalka-mode. This should be an easy key— one keystroke, easy to reach. I would even advise binding ; or Enter:

(global-set-key (kbd "<return>") #'modalka-mode)

The next thing to decide is whether modalka-mode should be enabled by default. modalka-mode can be enabled everywhere (except for the minibuffer) by activating modalka-global-mode:

(modalka-global-mode 1)

It is also possible to give Modalka a list of major modes where it should not be enabled:

(add-to-list 'modalka-excluded-modes 'magit-status-mode)

However, one may choose to enable modalka-mode only in conjunction with certain major modes:

(add-hook 'text-mode-hook #'modalka-mode)
(add-hook 'prog-mode-hook #'modalka-mode)

This is a whitelisting approach. modalka-global-mode and modalka-excluded-modes implement a blacklisting approach.

Change the cursor shape for visual feedback

modalka-mode comes with a lighter—. I don't recommend disabling it because it is nice to have an indication of whether modalka-mode is active or not. Furthermore, one can make the current editing mode even more conspicuous by changing the cursor shape. I suggest using the vertical bar cursor in the insert mode and the box cursor in the normal mode. Modalka uses the cursor specified in the modalka-cursor-type variable, so the whole setup might look like this:

(setq-default cursor-type '(bar . 1))
(setq modalka-cursor-type 'box)

Customization

modalka-mode is a normal minor mode. This means that you can use the modalka-mode-hook to define mode-specific hooks. You can use the customization interface to customize Modalka-related variables like this: M-x customize-group modalka RET.

Other solutions

In this section I describe other solutions and compare them with this package. Some of the solutions are quite popular, others are almost not used. I attempt to guess why it is so and why Modalka may be worth trying out.

Evil

Emulation of the Vi-style modal editing for Emacs is provided by several different packages, but the most advanced is Evil. What's wrong with it? Emacs is very flexible and can be Vi, with some effort, but Emacs is not Vi. Emacs has different keybindings for movement, etc. that permeate its whole ecosystem. Once evil-mode is used to edit text, one needs to either accept that text editing is done with a set of key bindings that differs from everything else, or to try to convert Emacs further. To convert Emacs further one needs more bridge packages: evil-org, evil-smartparens, etc. The sort of conversion can never be fully complete. Evil by itself is fairly complex and hooks deep into Emacs internals. It can cause incompatibilities with other packages. It also makes it harder to hack Emacs.

Control Mode

Control Mode is essentially a hack. From my experience it has the following flaws:

  • If one works with overlays that have local key maps this mode cannot handle it. One needs to disable it to interact with the overlays (packages that implement text folding are an example of that).

  • If a minor mode is activated when control-mode is already enabled, it cannot catch this change and adapt. One needs to turn control-mode off and then reactivate it or to run a special command that re-generates the key bindings.

  • Generalizing the previous points, in Emacs, a given combination of keys may have different meanings depending on the situation. The automatic generation of key bindings that control-mode uses fixes keybindings every time and thus causes all sorts of problems.

  • Control mode generates more key bindings than necessary replacing key bindings that should not be used in the normal mode.

God Mode

God Mode can be considered an improvement on control-mode. However, compared to Modalka, God Mode has certain downsides:

  • Design decisions are made for you. You can change something (because it's Emacs), but forming the entire key map is not meant to be done by the user.

  • The implementation is far more hairy without additional benefits.

  • Unlike Modalka, God Mode doesn't work with input methods.

  • You don't need to write hooks to change the shape of cursor according to current mode with Modalka, it handles this for you.

Boon

Boon is a package for modal editing with emphasis on ergonomics. This package gives you complete implementation of a modal editing system similar to Vi. It may take some time to learn it and I'm not entirely sure it will make much difference. Modal editing is easier, but ergonomic layout in the normal mode is somewhat optional for most people. I value compatibility with the Emacs ecosystem more.

Fingers

Fingers is another attempt at ergonomic modal editing. The same thoughts that have been said regarding Boon can be repeated here. The differences between these packages are not very significant except for the fact that Fingers is optimized for the Workman keyboard layout.

Xah Fly Keys

Xah Fly Keys is a package for ergonomic modal editing optimized for Dvorak. It's rather big compared to Boon and Fingers. If you look at source code you'll see that it has a peculiar collection of editing primitives. For example one can capitalize text skipping words like “and”, “to”, “or”, etc.—functionality that is rarely found in this sort of a package. Good dose of Unicode support is guaranteed, too.

Ergoemacs Mode

According to the authors, Ergoemacs Mode supports modal editing and can even emulate god-mode. And that's not all:

You can either define your own modal keymap, or tell ergoemacs-mode that the keyboard layout is the same as the current layout, but with Alt (or control pressed, or swapped, or any sort of other key combination).

License

Copyright © 2015–present Mark Karpov

Distributed under GNU GPL, version 3.

More Repositories

1

megaparsec

Industrial-strength monadic parser combinator library
Haskell
912
star
2

req

An HTTP client library
Haskell
337
star
3

zip

Efficient library for manipulating zip archives
Haskell
81
star
4

ace-popup-menu

Replace GUI popup menu in Emacs with something more efficient
Emacs Lisp
80
star
5

modern-uri

Modern library for working with URIs
Haskell
68
star
6

typit

Typing game for Emacs similar to the tests on 10 fast fingers
Emacs Lisp
65
star
7

ghc-syntax-highlighter

Syntax highlighter for Haskell using the lexer of GHC
Haskell
59
star
8

facts

Refined types
Haskell
58
star
9

parser-combinators

Lightweight package providing commonly useful parser combinators
Haskell
52
star
10

text-metrics

Calculate various string metrics efficiently in Haskell
Haskell
43
star
11

common-lisp-snippets

Yasnippets for Common Lisp
YASnippet
42
star
12

nushell-mode

Emacs major mode for Nushell scripts
Emacs Lisp
42
star
13

lpnes

Learn Prolog Now! Proper and elegant exercise solutions
Prolog
41
star
14

fix-word

Transform words in Emacs (upcase, downcase, capitalize, etc.)
Emacs Lisp
40
star
15

forma

Parse and validate forms in JSON format
Haskell
38
star
16

path-io

Operations on files and directories with typed paths
Haskell
30
star
17

cyphejor

Shorten major mode names by using a set of user-defined rules
Emacs Lisp
30
star
18

ebal

*DEPRECATED* Emacs interface to Cabal and Stack
Emacs Lisp
29
star
19

kill-or-bury-alive

Precise control over buffer killing in Emacs
Emacs Lisp
26
star
20

flac

Complete high-level Haskell binding to libFLAC
Haskell
26
star
21

zzz-to-char

Fancy replacement for zap-to-char in Emacs
Emacs Lisp
24
star
22

dot-emacs

Emacs configuration
Emacs Lisp
23
star
23

char-menu

Create a menu for fast insertion of arbitrary symbols
Emacs Lisp
22
star
24

htaglib

Haskell bindings for TagLib, an audio meta-data library
Haskell
21
star
25

avy-menu

An Avy-powered popup menu
Emacs Lisp
18
star
26

hspec-megaparsec

Utility functions for testing Megaparsec parsers with Hspec
Haskell
17
star
27

markkarpov.com

My personal web site
Haskell
16
star
28

mmt

Missing macro tools for Emacs Lisp
Emacs Lisp
16
star
29

identicon

Flexible generation of identicons in Haskell
Haskell
16
star
30

mupdf-page

Script to remember page when you quit MUPDF
Shell
16
star
31

JuicyPixels-extra

Efficiently scale, crop, flip images with JuicyPixels
Haskell
13
star
32

pagination

Framework-agnostic pagination boilerplate
Haskell
11
star
33

nixos-config

My NixOS configurations
Emacs Lisp
9
star
34

fix-input

Make input methods play nicely with alternative keyboard layouts on OS level
Emacs Lisp
9
star
35

wave

Work with WAVE and RF64 files in Haskell
Haskell
8
star
36

slug

*DEPRECATED* Type-safe slugs for Yesod ecosystem
Haskell
7
star
37

tagged-identity

Trivial monad transformer that allows identical monad stacks have different types
Haskell
6
star
38

req-conduit

Conduit utilities that work with the Req HTTP client library
Haskell
6
star
39

alga

*DEPRECATED* Algorithmic automation for various DAWs (Ardour, Cubase)
Haskell
5
star
40

para

*DEVELOPMENT SUSPENDED* Fast and stateless package to deal with pairs
Emacs Lisp
5
star
41

lame

A high-level Haskell binding to the LAME encoder
Haskell
5
star
42

emacs-package-flake

A Nix library that facilitates definition of flakes for Emacs packages
Nix
5
star
43

mida

*DEPRECATED* Minimalistic language for algorithmic generation of MIDI files
Haskell
5
star
44

plan-b

*DEPRECATED* Failure-tolerant file and directory editing for Haskell
Haskell
5
star
45

mkm3u

Playlist generator (m3u)
Python
4
star
46

openmw-automation

Ansible playbook to build, install, and setup OpenMW just the way I like it
4
star
47

cue-sheet

Support for construction, rendering, and parsing of CUE sheets
Haskell
4
star
48

flac-picture

Support for writing pictures into FLAC metadata blocks with JuicyPixels
Haskell
4
star
49

parsers-bench

Real-life parsers implemented in Attoparsec and Megaparsec with performance comparisons
Haskell
4
star
50

imprint

*DEPRECATED* Serialization of arbitrary Haskell expressions
Haskell
4
star
51

megaparsec-site

*DEPRECATED* Site of Megaparsec project that provides educational materials
Haskell
4
star
52

modern-path

Type-safe path and file system operations with batteries included
Haskell
3
star
53

liaison

Nix as a configuration language
Haskell
3
star
54

lsa

List properties of audio files
C
3
star
55

html-entity-map-gen

A tool to generate code for the html-entity-map library
Haskell
3
star
56

html-entity-map

Map from HTML5 entity names to the corresponding Unicode text
Haskell
3
star
57

snake

Classic snake game in Clojure
Clojure
3
star
58

lightning

*SUSPENDED* A rewrite of Megaparsec using backpack
Haskell
2
star
59

haskell-docker

A generic docker image for Haskell (CircleCI, etc.)
Dockerfile
2
star
60

data-check

*DEPRECATED* Library for checking and normalization of data (e.g. from web forms)
Haskell
2
star
61

mk-abbrev

*DEPRECATED* Peculiar way to use Emacs abbrevs
Emacs Lisp
2
star
62

http-client-blowup

A complete repro that causes http-client hang and leak memory indefinitely
Haskell
2
star
63

mrkkrp.github.io

*DEPRECATED* My blog with random stuff
Haskell
2
star
64

arch-workstation

*DEPRECATED* Ansbile playbooks and installation instructions to recreate my Arch Linux workstation
Shell
2
star
65

painting-notes

My notes about painting
1
star
66

glass

Minimalistic forum written in Python using Django
Python
1
star
67

github-actions-issue

A repo to reproduce an issue with GitHub workflows
1
star
68

containers-bug

It looks like I found a bug in containers-0.6.0.1
Haskell
1
star
69

ion

*DEPRECATED* Interface of Nature
Pascal
1
star
70

wav2

*DEPRECATED* Smart converter from WAV to FLAC and/or MP3 format
Python
1
star
71

flacize

Convert any audio files into properly tagged CDDA quality FLAC tracks
Python
1
star
72

md-bench

Comparison of various markdown libraries in Haskell (speed and memory usage)
Haskell
1
star
73

chemin

Well typed file paths and associated operations
Haskell
1
star
74

mk-dvorak-russian

*DEPRECATED* Type Russian in Emacs with Dvorak layout on system level
Emacs Lisp
1
star
75

project-jumper

A utility for jumping to local project directories
Haskell
1
star
76

spit-haskell-rules

Generate dummy rules for rules_haskell with the aim of using them for profiling
Haskell
1
star
77

playing-with-servant

This repository is for me to play with Servant framework as I go through the tutorial
Haskell
1
star
78

shtookovina-config

My own Шτookωвiнα configuration files
NewLisp
1
star
79

assignment

A solution to the assignment problem
Haskell
1
star