• Stars
    star
    184
  • Rank 204,767 (Top 5 %)
  • Language
    Scheme
  • License
    Apache License 2.0
  • Created almost 3 years ago
  • Updated 2 months ago

Reviews

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

Repository Details

Tree-sitter powered textobjects for evil mode in Emacs

evil-textobj-tree-sitter

MELPA test

Tree-sitter powered textobjects for Emacs. You can use them with evil-mode or with thing-at-point.

gif

This package will let you create evil textobjects using tree-sitter grammars. You can easily create function,class,comment etc textobjects in multiple languages. It also make additional things available in thing-at-point like function, class, loop, comment etc.

It can work with either elisp-tree-sitter or the builtin treesit library.

Installation

You can install evil-textobj-tree-sitter from melpa. Here is how you would do it using use-package and package.el:

(use-package evil-textobj-tree-sitter :ensure t)

Or you can use straight.el:

(use-package evil-textobj-tree-sitter :straight t)

Or using straight.el and el-get to pull from source:

(use-package evil-textobj-tree-sitter
  :straight (evil-textobj-tree-sitter :type git
                      :host github
                      :repo "meain/evil-textobj-tree-sitter"
                      :files (:defaults "queries" "treesit-queries")))

You will also have to setup tree-sitter.

Usage

thing-at-point additions

The package adds more "things" to thing-at-point. You can find all the things that it adds in the source.

You can use these like any other thing-at-point entries. For example in case of functions, we make the following available:

  • (thing-at-point 'function)
  • (function-at-point)

Mapping textobjects

By default, the library does not provide any keybindings, but it should be relatively easy to add them.

;; bind `function.outer`(entire function block) to `f` for use in things like `vaf`, `yaf`
(define-key evil-outer-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.outer"))
;; bind `function.inner`(function block without name and args) to `f` for use in things like `vif`, `yif`
(define-key evil-inner-text-objects-map "f" (evil-textobj-tree-sitter-get-textobj "function.inner"))

;; You can also bind multiple items and we will match the first one we can find
(define-key evil-outer-text-objects-map "a" (evil-textobj-tree-sitter-get-textobj ("conditional.outer" "loop.outer")))

Custom textobjects

If you are not able to find the text object that you are looking for in the builtin list, you can create custom text objects by passing the a custom query with captures.

For example if you want to create text object to select import statements, you can write something like below. You will have to provide the tree-sitter queries for all the languages that you want it to work for

;; The first arguemnt to `evil-textobj-tree-sitter-get-textobj' will be the capture group to use
;; and the second arg will be an alist mapping major-mode to the corresponding query to use.
(define-key evil-outer-text-objects-map "m" (evil-textobj-tree-sitter-get-textobj "import"
                                              '((python-mode . [(import_statement) @import])
                                                (rust-mode . [(use_declaration) @import]))))

Goto

We have also added support for for a fancier version of goto-char. You can use this to go to the next function, previous class or do any motions like that.

You can use the evil-textobj-tree-sitter-goto-textobj function to invoke goto. You can either use this in other function or just bound to a key. The first argument is the textobj that you want to use, the second one specifies if you want to search forward or backward and the last one is for specifying weather to go to the start or end of the textobj.

Below are some sample binding that you can do. You can use any textobj that is available here.

;; Goto start of next function
(define-key evil-normal-state-map
            (kbd "]f")
            (lambda ()
              (interactive)
              (evil-textobj-tree-sitter-goto-textobj "function.outer")))

;; Goto start of previous function
(define-key evil-normal-state-map
            (kbd "[f")
            (lambda ()
              (interactive)
              (evil-textobj-tree-sitter-goto-textobj "function.outer" t)))

;; Goto end of next function
(define-key evil-normal-state-map
            (kbd "]F")
            (lambda ()
              (interactive)
              (evil-textobj-tree-sitter-goto-textobj "function.outer" nil t)))

;; Goto end of previous function
(define-key evil-normal-state-map
            (kbd "[F")
            (lambda ()
              (interactive)
              (evil-textobj-tree-sitter-goto-textobj "function.outer" t t)))

Finding and contributing to textobjects

evil-textobj-tree-sitter work with both builtin treesit and elisp-tree-sitter. The queries in use are a bit different in both cases with the elisp-tree-sitter version currently being more feature complete. In both cases we pull the queries from external sources. For elisp-tree-sitter, we source them from nvim-treesitter/nvim-treesitter-textobjects and is places into queries directory. And for treesit queries, it is sourced from helix and placed in treesit-queries. You can check these files to see what all is available. If you are interesting in contributing additional textobjects, you can do so by submitting to the respective projects. If there is enough interest, I don't mind starting to manage queries ourselves.

If you are adding a completely new language, there is two other things that you will have to do to make sure everything will work well.

  1. Make sure the lang is available in emacs-tree-sitter/tree-sitter-langs or treesit.
  2. Make sure we have a major-mode mapping in evil-textobj-tree-sitter-major-mode-language-alist

If you would like to test out new textobjects, I would suggest using custom textobjects. If you want to edit the query files, you can edit them in evil-textobj-tree-sitter--queries-dir or by forking the repo, and using the forked version with your edits.

License

The primary codebase is licensed under Apache-2.0. The queries have be taken from nvim-treesitter/nvim-treesitter-textobjects which is also licensed under the same license.

More Repositories

1

dotfiles

If there is a shell, there is a way!
Emacs Lisp
228
star
2

vim-package-info

Vim plugin to quickly view info about the packages you use
JavaScript
71
star
3

vim-printer

Quickly print/log the variable in your favourite language
Vim Script
44
star
4

s3-mounter

Mount s3 buckets into pods in k8s
Dockerfile
38
star
5

scopeline.el

Show info about the block at the end of the block
Emacs Lisp
33
star
6

vim-colorswitch

Cycle between hex, rgb, hsl colors defined in current line
Python
29
star
7

gloc

Run a shell command in all the git repos in a directory.
Go
22
star
8

stag

Tag your local music using spotify api
Python
17
star
9

gourcer

Shell
15
star
10

ytdd

Go
15
star
11

gh-issues-to-rss

Convert github issues and prs into rss feed
Go
10
star
12

startpage

Custom startpage and newtabpage
JavaScript
9
star
13

hima-theme

A minimal theme with pretty colors
Emacs Lisp
9
star
14

vim-jsontogo

Vim plugin to convert from json to go struct
Vim Script
8
star
15

temper

A small utility to show presentation in shell
Shell
7
star
16

logseq-plugin-runjs

Run arbitrary JS in your LogSeq pages
TypeScript
7
star
17

mucri

Quickly fetch a lot of pages/apis using python asyncio
Python
6
star
18

toffee

Universal(in future) test picker
Rust
6
star
19

logseq-plugin-refile

A LogSeq plugin to refile items in your graph
JavaScript
6
star
20

ppl

The progress bar library that started with the idea of looking pretty
Python
6
star
21

emacsconf-talk-tree-sitter

Slides/Files for EmacsConf 2022 talk "Tree-sitter beyond syntax highlighting"
Rust
5
star
22

v

Quick access to recent files in any Vim clone
Shell
5
star
23

pbbui

A UI for Pure Bash Bible by dylanaraps
JavaScript
5
star
24

quif

Electron app to share files from your laptop via QR codes
JavaScript
5
star
25

hima-vim

Minimal light colorschme with good GUI element colors
Vim Script
5
star
26

marker

Markdown based presentation tool, the good parts.
JavaScript
4
star
27

programmingfonts-screenshots

Shell
2
star
28

vroom

Run VIM macros from cli
Rust
2
star
29

react-quick-select

Quick inline select for react
JavaScript
2
star
30

meain.github.io

Personal website. Nothing fancy.
JavaScript
1
star
31

tint

Tree-sitter powered linter
Go
1
star
32

push

Push notes or files to pushbullet
Go
1
star
33

nur-packages

Personal NUR packages
Nix
1
star
34

rust-errors-talk

Rust
1
star
35

venv

Easier workflow for python virtualenvs
Shell
1
star
36

nn

Quick little bot to run shell commands on servers via matrix
Go
1
star
37

cusat-exam-scraper

I was bored one day
Python
1
star
38

tojson

Convert between toml, yaml and json
Rust
1
star
39

kudo

Manage your todos in Kubernetes using CRD
Shell
1
star
40

minimal-dotfiles

Quickly setup a working environment in servers
Shell
1
star
41

vim-searcher

Search from right within vim
Vim Script
1
star
42

logseq-plugin-noisy

Enhance your LogSeq experience with sounds
JavaScript
1
star
43

depman

Terminal UI for dependency management
Rust
1
star
44

gn

JavaScript
1
star
45

webpageget

Get webpage content in different formats
JavaScript
1
star
46

asin

Just taking care of a small annoyance
HTML
1
star
47

dopy

Simple bash script to download and put files in a specified location
Shell
1
star
48

logseq-plugin-favorite-jump

Use shortcuts to switch between favorite pages
JavaScript
1
star
49

cachehandler

Cache api function callbacks or image links
Python
1
star
50

bridge

Bridging the link between teachers and students
Python
1
star
51

kabarna

In browser model training using tensorflow.js
JavaScript
1
star
52

sleed

Speed up or slow down any video on the internet
JavaScript
1
star