clojure-emacs / clojure-emacs/clojure-ts-mode

`beginning/end-of-defun` doesn't work if point is in docstring or regex

Open
#115 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Emacs Lisp
Stars
188
Forks
21
Avg merge
12m
Merged PRs (30d)
1

Description

## Expected behavior

Executing `C-M-e` (`end-of-defun`) or `C-M-a` (`beginning-of-defun`) from any place inside of a defun navigates to a proper position.

## Actual behavior

Point is not moved or moved to some random place inside of a docstring or a regex.

## Steps to reproduce the problem

The issue is reproducible only if any of the embedded parsers is enabled (either `markdown-inline` or `regex`). When `end-of-defun` is called Emacs delegates its execution to `treesit-end-of-defun`, which tries to operate on "things", but if parser at point is not `clojure` it tries to navigate to the end of defun of embedded parser.

It also affects CIDER: currently it's not possible to evaluate form if point is in a docstring, because CIDER uses `end-of-defun` internally.

## Possible solutions

We can either defun custom `clojure-ts-[beginning|end]-of-defun` functions and remap `treesit-*` versions or we can add advice before `treesit-*` functions to jump out of an embedded node before using an actual navigation command:

```emacs-lisp
(defun clojure-ts--ensure-not-embedded (&rest args)
(when (and (derived-mode-p 'clojure-ts-mode)
(not (equal (treesit-language-at (point)) 'clojure)))
(backward-up-list 1 t)))

(advice-add 'treesit-end-of-defun :before #'clojure-ts--ensure-not-embedded)
(advice-add 'treesit-beginning-of-defun :before #'clojure--ts-ensure-not-embedded)
```

I tested both options locally, both work fine and solve the issue.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.