GithubHelp home page GithubHelp logo

rrethy / nvim-treesitter-textsubjects Goto Github PK

View Code? Open in Web Editor NEW
461.0 4.0 19.0 66 KB

Location and syntax aware text objects which *do what you mean*

License: Apache License 2.0

Lua 25.11% Scheme 74.77% Vim Script 0.11%
treesitter tree-sitter nvim neovim lua

nvim-treesitter-textsubjects's Introduction

Location and syntax aware text objects which *do what you mean*

Screen.Recording.2022-01-09.at.11.34.26.PM.mov

Quick Start

require('nvim-treesitter.configs').setup {
    textsubjects = {
        enable = true,
        prev_selection = ',', -- (Optional) keymap to select the previous selection
        keymaps = {
            ['.'] = 'textsubjects-smart',
            [';'] = 'textsubjects-container-outer',
            ['i;'] = 'textsubjects-container-inner',
            ['i;'] = { 'textsubjects-container-inner', desc = "Select inside containers (classes, functions, etc.)" },
        },
    },
}

This will enable the . (this is the mapping I use but <cr> is quite ergonomic too) and ; text objects which will select a different part of the syntax tree depending on your location in it. See below for what each query matches.

Whether the selection is by character or by line will also depend on your location in the syntax tree (handled by a few simple heuristics). See below for more details on what parts of the syntax tree are matched.

Note: I know these names are a bit confusing, but naming them is quite difficult.

Text Subjects

Note: I'm open to adding more queries or support for another language, just open and issue or a PR and I can work with you to get the query working.

container-inner container-outer smart
c ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
cpp ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
elixir โฌœ ๐ŸŸฉ ๐ŸŸฉ
foam โฌœ ๐ŸŸฉ ๐ŸŸฉ
go ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
javascript / jsx โฌœ ๐ŸŸฉ ๐ŸŸฉ
julia โฌœ ๐ŸŸฉ ๐ŸŸฉ
lua ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
php ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
python ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
r ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
ruby ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
rust ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
scss โฌœ โฌœ ๐ŸŸฉ
typescript / tsx โฌœ ๐ŸŸฉ ๐ŸŸฉ
fennel ๐ŸŸฉ ๐ŸŸฉ ๐ŸŸฉ
nix โฌœ โฌœ ๐ŸŸฉ

textsubjects-smart

Patterns: comments, consecutive line comments, function calls, function definitions, class definitions, loops, if statements, return values, arguments.

See queries/*/textsubjects-smart.scm for full information on the query.

textsubjects-container-outer

Patterns: Classes, structs, functions, methods.

See queries/*/textsubjects-container-outer.scm for full information on the query.

textsubjects-container-inner

Patterns: Inside Classes, structs, functions, methods.

See queries/*/textsubjects-container-inner.scm for full information on the query.

Custom Query

You can create your own text subjects by creating a Tree-sitter query that has ranges named range. This query file name can be provided in the keymaps about.

Ranges can be created as follows:

((comment) @_start @_end
     (#make-range! "range" @_start @_end))

See queries/*/textsubjects-smart.scm for examples or open an issue if you need any help writing a query.

Alternatives

  • nvim-treesitter-textobjects: I still use this and it's a great plugin (especially the lookahead feature ๐Ÿ˜‰). If you want to target the textobject exactly then this plugin is the way to go. However, it can quickly lead to having too many text object mappings (I had 8 before making this plugin) and it will always deal with whitespace based on the way you invoked it rather than handling this heuristically.
  • nvim-treesitter-incremental-selection-mod: This is similar but doesn't act as a text objects. When incrementing the selection it will do so strictly by scope or by looking at the parent node which is often way too strict for practical use. For example, it will select all the arguments in (,) then can be expanded a few times to reach the next scope inside {,}, but these can both be selected more directly with ib and iB respectively so it would make more sense to skip them since the user probably doesn't want to select them. Incremental selection sounds nice but often isn't how people edit text (at least not me). On top of all this, it's strict with whitespace whereas this plugin will try to handle it heuristically.

nvim-treesitter-textsubjects's People

Contributors

aspeddro avatar bbbert avatar foamscience avatar gelio avatar iasoon avatar lf- avatar muniftanjim avatar nitper avatar rktjmp avatar rrethy avatar smoka7 avatar stephenprater avatar timoleistner avatar younger-1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

nvim-treesitter-textsubjects's Issues

BUG: Vanilla vim motion for repeating f/t operation etc... stops working in visual mode

Consider this piece of text:

http://www.test.com/asd/asd.

Let's say I want to visual select from http to the last slash.
I would go to the beginning of the line and press v to enter visual mode and then press f/.
This will highlight http:/. However, if I want to repeat this search while in visual mode, I have to press
; repeatedly to highlight to the /, but that operation does not work with this plugin (i.e. it doesn't
move the cursor forward and highlight the up to the next /)

Feature request: support move to textobjects

Appreciate the great work here! This plugin is exactly what I was looking for, as it solved the exact pain points I was experiencing with treesitter-textobjects (which is otherwise great, but in practice requires too many unique key bindings to cover all the cases I am looking for).

I understand this might not be your intended use case for this plugin, but would it be difficult to include support for moving to the next/previous "smart" object. Not sure if there would be any technical limitations to support this.

This might be good to at least discuss how this might be possible either here or in a separate plugin if you believe it is out of scope (no pun intended ๐Ÿ˜‰ ).

Julia TS node names have changed

I'm not sure why , but right now julia textsubjects is broken.
it looks like the node names are different , changing to appropriate node names in the queries scm seems to make it work.

comment is now line_comment
array_expression is now vector_expression ,

i dont have much of an idea on Treesitter, but i can make a PR with the changes that i did to get it working , may i ?

support textsubjects-smart-inner

if use textsubjects-smart, will be select $range, if support textsubjects-smart-inner like textsubjects-function-inner, maybe pretty goods. or use textsubjects-smart, don't skip inner, just extend to textsubjects-inner first, press again, to textsubjects

Undo support

Hello, thank you for the plugin. I have a feature idea in mind that I'm not sure the feasibility of.

Would it be possible to store previous selections so they can be undone via another keymap? Something like:

  • opt-in
  • stores X number of previous selections
  • keybind to restore previous selection

Use case: Butterfingers and accidentally selecting one too far

Adding keymap descriptions

Hello,

is there a way to add keymap descriptions? I can add keymap descriptions for textobjects like this:

textobjects = {
    select = {
        keymaps = {
            ['af'] = { query = '@function.outer', desc = 'outer function' },
            ['if'] = { query = '@function.inner', desc = 'inner function' },
        },
    },
    move = {
        goto_next_start = {
            [']m'] = { query = '@function.outer', desc = 'next method start' },
        },
        goto_next_end = {
            [']M'] = { query = '@function.outer', desc = 'next method end' },
        },
    },
}

Is there also a way for textsubjects?

Elegant fallback to incremental selection?

I love the ergonomics of treesitter's incremental selection by node, and textsubjects feels like a great drop-in enhancement for this. I like \ and <BS> for initiating/incrementing and decrementing, so my config is something like this (not exactly lazy.nvim):

return {
  plugins = {
    {
      'RRethy/nvim-treesitter-textsubjects',
      event = { 'BufReadPost', 'BufNewFile' },
    }
  },
  ts_opts = {
    textsubjects = {
      enable = true,
      prev_selection = '<BS>',
      keymaps = {
          ['\\'] = 'textsubjects-smart',
      },
    },
    incremental_selection = {
      enable = true,
      keymaps = {
        init_selection = 'g\\',
        node_incremental = 'g\\',
        scope_incremental = false,
        node_decremental = 'g<BS>',
      },
    },
  },
  config = function()
    vim.keymap.set('n', '\\', 'V\\', { remap = true })
  end,
}

I'm using g prefixes to retain access to incremental_selection because I work in an assortment of languages, some of which have textsubjects support and some which do not. I would love to be able to have textsubjects fallback to treesitter's increment/decrement when textsubject support is not available.

Are there any ways that this could be done more elegantly? I could see defining keymaps which conditionally call either textsubjects or incremental_selection based on whether the current treesitter node is supported by textsubjects or not, but this seems like it would be fragile with nested languages and I don't know how to query textsubjects to determine which languages support textsubjects-smart. Ideally, I think textsubjects would transparently fallback to treesitter node increments and retain the prev_selection functionality throughout.

A text-subject mapping jupyter cell divider pattern: #%%

Hi I am newbie in lua and completely confused with text-objects. I hope you can help:

I use #%% inside my python files to quickly jump between code blocks. It also helps if i convert the .py file to .ipynb, in that it uses the #%% string to define cell boundaries in jupyter. Can you help create a tree-sitter text subject which recognises this pattern and a keymapping to help me jump from one occurence of #%% to next (and backwards)?

Thanks.

`nvim-treesitter.ts_utils` deprecation warning

Thank you for the great plugin, it is awesome!

I am using the nightly version

NVIM v0.9.0-dev-935+g3a5dddf24-dirty
Build type: Release
LuaJIT 2.1.0-beta3

and I see the treesitter deprecation warning

nvim-treesitter.ts_utils.is_in_node_range is deprecated: use vim.treesitter instead

probably in this import.

It may be useful to address it at some point :)

Documentation for `#make-range`?

I'm trying to define a capture that grabs a function in Go and (optionally) comments. I'm sorry to bug you with this, but is there fuller documentation somewhere for #make-range? I'm unsure where and how to place the @start and @end tokens. Thanks.

Probably stupid question

Hi. I'm very new to using vim/neovim at higher level rather than basic editing and :w to save.

I've been trying to jump into neovim with Lua, and I found this plugin, being used with treesitter. However, I'm wondering what this one does that is significantly different/better from the default incremental_selection feature built into treesitter.

With incremental_selection, I use v to start selecting a character, or more, then say I press whatever the key mapped to do node_incremental to continue to increment the selection. That eventually select a line, then an if inner block, then the if outer block, then the function, etc.

With textsubjects, pressing . by default, would select the whole line, then the if outer block. It takes 2 key strokes instead of 5-6 like above.

So is the main point here is to save the key strokes, or there's something obvious to anyone else and not to me?

Again, I'm totally new to any of this, so I'm sorry if this is too naive of a question or something. Not that I don't appreciate the work here. I just want to understand more of what is going on.

Also, in the README of the plugin, there's a mentions lookahead feature from textobjects plugin, but in the config of the author of packer.nvim, I see it also being used for this plugin. I'm a little confused if it's available in this plugin as well, or not. Not that I really understand what it does, though...

https://github.com/wbthomason/dotfiles/blob/linux/neovim/.config/nvim/plugin/treesitter.lua#L19

Mappings are not triggered

I just installed treesitter-text-objects and treesitter-textsubjects ( really cool plugin btw, thank you for your work! )

However, I cannot make it work. treesitter-text-objects does work, the mapping of textsubjects refuse to get triggered though. Am I misunderstanding the mappings? v ; for example does not work for me.

Here is my treesitter config (taken from here):

require'nvim-treesitter.configs'.setup {
    ensure_installed = {"help", "javascript", "typescript", "lua"},
    sync_install = false,
    auto_install = true,

    textobjects = {
        select = {
            enable = true,
            lookahead = true,
            keymaps = {
                ["ia"] = "@parameter.inner",
                ["aa"] = "@parameter.outer"
            },
            include_surrounding_whitespace = true
        },
        move = {
            enable = true,
            goto_next_start = {
                [']m'] = '@function.outer'
            },
            goto_previous_start = {
                ['[m'] = '@function.outer'
            }
        }
    },

    endwise = {
        enable = true
    },

    textsubjects = {
        enable = true,
        prev_selection = ',',
        keymaps = {
            ['<cr>'] = 'textsubjects-smart',
            [';'] = 'textsubjects-container-outer',
            ['i;'] = 'textsubjects-container-inner'
        }
    }
}

And here is my whole config (I am a beginner so it is really simple)

Windows 11
NVIM v0.8.3
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3

Quantifiers `*` and `+`?

I notice that you're using + and * in some of your queries (e.g., here).

Do those work for you? I ask because unless I'm confused treesitter (for textobjects?) doesn't yet support * and +. See, for example, here and here.

I apologize if this question is out of place, but I'm struggling a bit to understand the treesitter implementation in neovim. Thanks.

Avoiding putting the cursor on different lines after textsubjects-smart?

Hi! I love your plugin and I'm currently implementing a Haskell query for it so I can use it at work. I'll PR it upstream after I have a week or two to smoke test it at work. Here's my current progress: https://github.com/lf-/dotfiles/blob/main/configs/nvim/after/queries/haskell/textsubjects-smart.scm

A trouble that I have is that when I hit v., the plugin will put the cursor on the next or preceding line. This is particularly biting me because I'd like to do v.. to expand the selection to grab the function along with its signature, but v. moves the cursor outside of the syntax nodes where the range would apply.

I'm not quite sure whose bug this is, or if it is an issue with my query in some way. It doesn't seem to happen when there's not whitespace surrounding the lines in question.

Minimal textsubjects query to reproduce the issue:

([
  (signature)
  (function)
 ] @_start @_end
 (#make-range! "range" @_start @_end))

; signature + function
(
 ((signature) @_start
  .
  (function) @_end)
 (#make-range! "range" @_start @_end))

Sample haskell code that could show it:

module Test where
-- โ†“โ†“โ†“ cursor goes on the "test :: Int" line, then press `v.` and it will go on the line above

test :: Int
test = 1

Relevant parts of syntax tree:

signature [256, 0] - [256, 11]
  name: variable [256, 0] - [256, 4]
  type: "::" [256, 5] - [256, 7]
  type: type_name [256, 8] - [256, 11]
    type [256, 8] - [256, 11]
function [257, 0] - [257, 8]
  name: variable [257, 0] - [257, 4]
  "=" [257, 5] - [257, 6]
  rhs: exp_literal [257, 7] - [257, 8]
    integer [257, 7] - [257, 8]

no such mapping `nvim_buf_del_keymap` in `yaml` files

On neovim nightly, in particular

NVIM v0.10.0-dev-1496+g4c8fdc018-Homebrew
Build type: Release
LuaJIT 2.1.1699180677

I get the following exception while opening .yaml files (and .yaml files only, I haven't been able to reproduce it with any other file format, strangely enough)

Error detected while processing BufReadPost Autocommands for "*":
Error executing lua callback: ...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:30: Error executing lua: ...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:31: BufReadPost Autocommands for "*"..FileType Autocommands for "*": Vim(append):Error executing lua callback: ...sitter-textsubjects/lua/nvim-treesitter/textsubjects.lua:236: E31: No such mapping
stack traceback:
	[C]: in function 'nvim_buf_del_keymap'
	...sitter-textsubjects/lua/nvim-treesitter/textsubjects.lua:236: in function 'detach'
	...vim/lazy/nvim-treesitter/lua/nvim-treesitter/configs.lua:522: in function 'detach_module'
	...vim/lazy/nvim-treesitter/lua/nvim-treesitter/configs.lua:531: in function 'reattach_module'
	...vim/lazy/nvim-treesitter/lua/nvim-treesitter/configs.lua:133: in function <...vim/lazy/nvim-treesitter/lua/nvim-treesitter/configs.lua:132>
	[C]: in function 'nvim_cmd'
	...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:31: in function <...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:30>
	[C]: in function 'nvim_buf_call'
	...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:30: in function <...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:10>
stack traceback:
	[C]: in function 'nvim_cmd'
	...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:31: in function <...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:30>
	[C]: in function 'nvim_buf_call'
	...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:30: in function <...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:10>
stack traceback:
	[C]: in function 'nvim_buf_call'
	...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:30: in function <...llar/neovim/HEAD-4c8fdc0/share/nvim/runtime/filetype.lua:10>

which seems to point to this line.

I find it strange that only yaml files are affected, so I thought the problem could lie within the yaml lsp configuration, however the error still persists even after removing said yaml configuration.

Do you think the error lies elsewhere? Perhaps you could point me to the right direction?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.