Home

Awesome

CTRLF

CTRLF (pronounced "control F") is an intuitive and efficient solution for single-buffer text search in Emacs, replacing packages such as Isearch, Swiper, and helm-swoop.

<!-- toc --> <!-- tocstop -->

Installation

CTRLF is available as a package on MELPA. The easiest way to install this package is using straight.el:

(straight-use-package 'ctrlf)

However, you may install using any other package manager if you prefer.

Usage

To enable CTRLF, simply add to your init-file:

(ctrlf-mode +1)

Note that the autoloading has been configured so that enabling ctrlf-mode will not actually load CTRLF until you use one of its commands.

Now the usual Isearch bindings will use CTRLF instead:

See Customization to customize the default and alternative search styles.

User guide

The design philosophy of CTRLF is to:

As such, if you are familiar with Isearch then you will probably be at home in CTRLF.

Search flow

First you must start a search using one of the following keybindings:

During a search, the following core keybindings are available:

The following additional keybindings are available, emulating standard Emacs bindings:

CTRLF behavior toggles use the same bindings as in Isearch:

Other than this, keybindings are completely standard. For example, to delete the last word in your search query, use M-DEL, or to retrieve the previous search query in the minibuffer history, use M-p.

It is standard in Emacs for typing M-n after entering the minibuffer to insert a default value into the minibuffer. In CTRLF, this default value is the symbol at point.

Customization

You can customize the search styles of CTRLF:

You can customize the visual appearance of CTRLF:

You can also customize the keybindings:

In addition to the functions already bound in ctrlf-minibuffer-mode-map, you can choose to bind ctrlf-next-match and ctrlf-previous-match. These functions are the same as ctrlf-forward and ctrlf-backward, but they do not have the special features of inserting the previous search, changing to a literal search, or starting a new search when not already in a search session.

You can customize the behavior:

Search styles

CTRLF implements support for literal and regexp using an extensible search style system. This functionality is configured using the ctrlf-style-alist user option. End users need not touch this option unless they wish to do advanced customization or are developing a package which integrates with CTRLF.

The keys of ctrlf-style-alist define the available search styles. These styles appear in two places:

Basically, a search style defines a way to transform the user's search query into a regexp which can be passed to search-forward-regexp or search-backward-regexp. Here are the built-in search styles:

To define a custom search style, you should proceed according to the following steps:

Disabling CTRLF locally

ctrlf-mode is a globalized minor mode that enables the buffer-local minor mode ctrlf-local-mode. This makes it possible to disable it when there is a conflict, for example with pdf-isearch-minor-mode from pdf-tools:

(add-hook 'pdf-isearch-minor-mode-hook (lambda () (ctrlf-local-mode -1)))

Miscellaneous

The minibuffer history for CTRLF is stored in the variable ctrlf-search-history. You can access it during a search session using M-p and M-n. Typing M-n at the beginning of a session will perform a search for the symbol at point. Furthermore, typing C-s or C-r without any search query is a synonym for M-p.

CTRLF integrates with evil-mode's jump-list and search history features. You will be able to jump with C-o and C-i and continue a search with n and N based on your CTRLF searches.

Why use CTRLF?

This section documents why I decided to write CTRLF instead of using any of the numerous existing solutions in Emacs.

Why not Isearch?

Isearch has the right idea for buffer search, but it has serious usability problems. The main issue, for me, is that it feels extremely fragile. If you type any command that is not bound in Isearch, then you exit your search and run that command. This means editing your search query is awkward and unintuitive. Another issue is predictability. The behavior of C-g is hard to predict because it depends on not only what you have typed in what order, but also on the buffer contents and the state of the current search. The handling of wraparound exacerbates problems of predictability: the number of times you must type C-s to move to the next match is unpredictable and the minibuffer prompt changes in several different and confusing ways during this process.

CTRLF takes the basic idea of Isearch, together with most of its keybindings, but emulates the more reliable user experience of web browser text search. For example: all editing commands can be used during a search as usual; C-g always has the effect of canceling the search; and C-s always moves to the next candidate, with wraparound signaled by an overlay which indicates the current match index and the total number of matches (another UI paradigm borrowed from other programs).

Why not Swiper?

The selling point of Swiper is that it shows you an overview of the matches. Ask yourself: when was the last time you actually got anything useful out of that overview? Since all the matches are crammed together, one per line, there is not enough context for meaningful information to be communicated. Furthermore, Swiper constrains itself almost exclusively to line-based search by design, which makes it unsuitable to the task of quick movement within a line or movement to a commonly occurring search string.

Why not helm-swoop?

For basically the same reason that Swiper is not a good solution, with the added complaint that Helm is extraordinarily complex and in-your-face about this complexity. Single-buffer text search is not a terribly difficult problem, and given that CTRLF is only about 1,100 lines of code, I think that the 1,700 lines of code of helm-swoop plus the 10,600 that come with Helm is a bit overkill.

Why not M-x occur?

M-x occur implements noninteractive search, and therefore unsuitable as a tool for quickly jumping to other parts of the buffer.

Why not Avy?

It does not usefully support text search outside the currently visible window.

Contributing

Please see the contributor guide for my projects.