expreg

:emacs:
Mar 31, 2026

Lately, I stumbled across the nice package expreg. It allows to enlarge or shrink a region based on semantic units and it is quite similar to expand-region. In contrast to expand-region it uses tree-sitter in the background and has no mode specific definitions.

1. Should I switch?

The first draft of the package was at a time where tree-sitter was still in the early adoption among the Emacs modes and the expand-region worked well. Thus, a change seemed to be unnecessary.

In the last couple of month the package got some care and I tried it. It works well in all major modes I tried and its support in org-mode is better than expand-region.

2. Configuration

The configuration for the package is fairly simple.

(use-package expreg
  :ensure t
  :custom (expreg-restore-point-on-quit t)
  :hook (text-mode-hook . (lambda ()
                            (add-to-list 'expreg-functions #'expreg--sentence)))
  :general (jj-general-definer 'global-map
             "C-+" '(expreg-expand :wk "expand region")
             "C--" '(expreg-contract :wk "contract region")))

The function jj-general-definer is a macro which sets some defaults I use for the general package.

expand-region sets a repeat map which allows to repeatedly press + or - which is nice to use. Add the following code to get the same behavior for expreg:

(defvar expreg-repeat-map
  (define-keymap
    "+" #'expreg-expand
    "-" #'expreg-contract))
(put #'expreg-expand 'repeat-map 'expreg-repeat-map)
(repeat-mode t)

2.1. Update 03.04.2026

I looked into the use-package documentation and found a better way to define the repeat map.

:bind (:repeat-map jj-expreg-repeat-map
                   ("+" . expreg-expand)
                   ("-" . expreg-contract))

The symbol :repeat-map defines the following symbol as a repeat map and adds all bindings in the scope to the :repeat-map.

If somebody knows a way to declare a repeat map with general.el feel free to reach out.