Merge pull request #1 from nvim-treesitter/master

Updates from master
This commit is contained in:
TravonteD 2020-05-11 11:29:40 -04:00 committed by GitHub
commit 73ea03fb8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 1422 additions and 171 deletions

99
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,99 @@
# Contributing to `nvim-treesitter`
First of all, thank you very much for contributing to `nvim-treesitter`.
If you haven't already, you should really come and reach out to us on our [gitter](https://gitter.im/nvim-treesitter/community?utm_source=share-link&utm_medium=link&utm_campaign=share-link)
room, so we can help you with any question you might have!
As you know, `nvim-treesitter` is roughly splitted in two parts :
- Parser configurations : for various things like `locals`, `highlights`
- What we like to call *modules* : tiny lua modules that provide a given feature, based on parser configurations
Depending on which part of the plugin you want to contribute to, please read the appropriate section.
## Parser configurations
Contributing to parser configurations is basically modifying one of the `queries/*/*.scm`.
Each of these `scheme` files contains a *tree-sitter query* for a given purpose.
Before going any further, we highly suggest that you [read more about tree-sitter queries](https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries).
Each query has an appropriate name, which is then used by modules to extract data from the syntax tree.
For now two types of queries are used by `nvim-treesitter`:
- `highlights.scm` : used for syntax highlighting, using the `highlight` module.
- `locals.scm` : used to extract keyword definitions, scopes, references,... using the `locals` module.
For both of these types there is a *norm* you will have to follow so that features work fine.
Here are some global advices :
- If your language is listed [here](https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries),
you can debug and experiment with your queries there.
- If not, you should consider installing the [tree-sitter cli](https://github.com/tree-sitter/tree-sitter/tree/master/cli),
you should then be able to open a local playground using `tree-sitter build-wasm && tree-sitter web-ui` within the
parsers repo.
### Highlights
As languages differ quite a lot, here is a set of captures available to you when building a `highlights.scm` query.
One important thing to note is that many of these capture groups are not supported by `neovim` for now, and will not have any
effect on highlighting. We will work on improving highlighting in the near future though.
#### Misc
`@comment`
`@error` for error `(ERROR)` nodes.
`@punctuation.delimiter` for `;` `.` `,`
`@punctuation.bracket` for `()` or `{}`
Some captures are related to language injection (like markdown code blocks). As this is not supported by neovim yet, these
are optional and will not have any effect for now.
`@embedded`
`@injection`
`language`
`content`
#### Constants
`@constant`
`builtin`
`macro`
`@string`
`regex`
`escape`
`@character`
`@number`
`@boolean`
`@float`
#### Functions
`@function`
`builtin`
`macro`
`@parameter`
`@method`
`@field` or `@property`
`@constructor`
#### Keywords
`@conditional`
`@repeat`
`@label` for C/Lua-like labels
`@operator`
`@keyword`
`@exception`
`@type`
`builtin`
`@structure`
### Locals
`@definition` for various definitions
`function`
`method`
`var`
`macro`
`type`
`@scope`
`@reference`

View file

@ -11,7 +11,7 @@ Treesitter configurations and abstraction layer for Neovim.
## Installation
You can install `nvim-treesitter` with your favorite package manager, or using the default `pack` feature of neovim !
You can install `nvim-treesitter` with your favorite package manager, or using the default `pack` feature of Neovim!
### Using a package manager
@ -79,19 +79,101 @@ bash [✗] not installed
tsx [✗] not installed
```
And now you should be able to use every functionnality `nvim-treesitter` provides !
And now you should be able to use every functionality `nvim-treesitter` provides!
## Setup
in your `init.vim`:
```lua
lua <<EOF
require'nvim-treesitter.configs'.setup {
highlight = {
enable = true, -- false will disable the whole extension
disable = { 'c', 'rust' }, -- list of language that will be disabled
},
incremental_selection = { -- this enables incremental selection
enable = true,
disable = { 'cpp', 'lua' },
keymaps = { -- mappings for incremental selection (visual mappings)
node_incremental = "<leader>e", -- "grn" by default,
scope_incremental = "<leader>f" -- "grc" by default
}
},
node_movement = { -- this enables cursor movement in node hierarchy
enable = true,
disable = { 'cpp', 'rust' },
keymaps = { -- mappings for node movement (normal mappings)
move_up = "<a-k>", -- default is to move with alt key hold
move_down = "<a-j>",
move_left = "<a-h>",
move_right = "<a-l>",
}
},
ensure_installed = 'all' -- one of 'all', 'language', or a list of languages
}
EOF
```
## Commands
Each feature can be enabled or disabled by different means:
```vim
:TSBufEnable {module} " enable module on current buffer
:TSBufDisable {module} " disable module on current buffer
:TSEnableAll {module} [{ft}] " enable module on every buffer. If filetype is specified, enable only for this filetype.
:TSDisableAll {module} [{ft}] " disable module on every buffer. If filetype is specified, disable only for this filetype.
:TSModuleInfo [{module}] " list information about modules state for each filetype
```
## Features and Roadmap
The goal of `nvim-treesitter` is both to provide a simple and easy way to use the interface for treesitter in neovim,
but also to add some functionnalities to it:
The goal of `nvim-treesitter` is both to provide a simple and easy way to use the interface for Treesitter in Neovim,
but also to add some functionalities to it:
Some of these features are :
- [ ] Incremental selection
- [x] Incremental selection
- [ ] Syntax based code folding
- [ ] Consistent syntax highlighting
- [x] Consistent syntax highlighting (the api is not quite stable yet)
- [x] Cursor movement in node hierachy
- [x] Statusline indicator (`require'nvim-treesitter'.statusline(size)`)
You can find the roadmap [here](https://github.com/nvim-treesitter/nvim-treesitter/projects/1).
The roadmap and all features of this plugin are open to change, and any suggestion will be highly apreciated !
The roadmap and all features of this plugin are open to change, and any suggestion will be highly appreciated!
## Supported Languages
For treesitter to work, we need to use query files such as those you can find in `queries/{lang}/{locals,highlights}.scm`
We are looking for maintainers to write query files for their languages.
List of currently supported languages:
- [x] lua (maintained by @vigoux)
- [x] ruby (maintained by @TravonteD)
- [ ] c
- [ ] go
- [ ] cpp
- [ ] rust
- [ ] python
- [ ] javascript
- [ ] typescript
- [ ] tsx
- [ ] json
- [ ] html
- [ ] csharp
- [ ] swift
- [ ] java
- [ ] ocaml
- [ ] css
- [ ] julia
- [ ] php
- [ ] bash
- [ ] scala
- [ ] haskell
- [ ] toml
- [ ] vue
- [ ] elm
- [ ] yaml
- [ ] nix
## Troubleshooting
Before doing anything run `:checkhealth nvim_treesitter`. This will help you find where the bug might come from.

View file

@ -0,0 +1,3 @@
function! nvim_treesitter#statusline(len)
return luaeval("require'nvim-treesitter'.statusline(_A)", a:len)
endfunction

112
doc/nvim-treesitter.txt Normal file
View file

@ -0,0 +1,112 @@
*nvim-treesitter*
Minimum version of neovim: nightly
Authors: Yazdani Kiyan <yazdani.kiyan@protonmail.com>, Vigouroux Thomas <tomvig38@gmail.com>
==============================================================================
INTRODUCTION *nvim-treesitter-intro*
nvim-treesitter wraps the neovim treesitter api to provide functionnalities such
as highlighting and incremental selection, and a command to easily install parsers.
==============================================================================
QUICK START *nvim-treesitter-quickstart*
Install the parser for your language
>
:TSInstall {language}
<
To get a list of supported languages
>
:TSInstallInfo
<
By default, everything is disabled. To enable support for features, in your `init.vim`:
>
lua <<EOF
require'nvim-treesitter.configs'.setup {
highlight = {
enable = true, -- false will disable the whole extension
disable = { 'c', 'rust' }, -- list of language that will be disabled
},
incremental_selection = { -- this enables incremental selection
enable = true,
disable = { 'cpp', 'lua' },
keymaps = { -- mappings for incremental selection (visual mappings)
node_incremental = "<leader>e", -- "grn" by default,
scope_incremental = "<leader>f" -- "grc" by default
}
},
node_movement = { -- this cursor movement in node hierachy
enable = true,
disable = { 'cpp', 'rust' },
keymaps = { -- mappings for node movement (normal mappings)
move_up = "<a-k>", -- default is to move with alt key hold
move_down = "<a-j>",
move_left = "<a-h>",
move_right = "<a-l>",
}
},
ensure_installed = 'all' -- one of 'all', 'language', or a list of languages
}
<
==============================================================================
COMMANDS *nvim-treesitter-commands*
|:TSInstall| {language} *:TSInstall*
Download, compile and install a parser for {language}
|:TSInstallInfo| *:TSInstallInfo*
List informations about currently installed parsers
|:TSBufEnable| {module} *:TSBufEnable*
Enable {module} on the current buffer.
A list of modules can be found at |:TSModuleInfo|
|:TSBufDisable| {module} *:TSBufDisable*
Disable {module} on the current buffer
A list of modules can be found at |:TSModuleInfo|
|:TSBufEnableAll| {module} [{language}] *:TSBufEnableAll*
Enable {module} for the session
if {language} is specified, enable module for the session only for this
particular language.
A list of modules can be found at |:TSModuleInfo|
A list of languages can be found at |:TSInstallInfo|
|:TSBufDisableAll| {module} [{language}] *:TSBufDisableAll*
Disable {module} for the session
if {language} is specified, disable module for the session only for this
particular language.
A list of modules can be found at |:TSModuleInfo|
A list of languages can be found at |:TSInstallInfo|
|:TSModuleInfo| [{module}] *:TSModuleInfo*
List modules state for the current session.
==============================================================================
FUNCTIONS~
*nvim-treesitter-functions*
|nvim_treesitter#statusline(size)|
*nvim_treesitter#statusline()*
Returns a string describing the current position in the syntax tree. This
could be used as a statusline indicator.
Note: The `size` argument is optionnal. When specified, the string will not be
longer than `size`.
vim:tw=78:ts=8:noet:ft=help:norl:

13
doc/tags Normal file
View file

@ -0,0 +1,13 @@
:TSBufDisable nvim-treesitter.txt /*:TSBufDisable*
:TSBufDisableAll nvim-treesitter.txt /*:TSBufDisableAll*
:TSBufEnable nvim-treesitter.txt /*:TSBufEnable*
:TSBufEnableAll nvim-treesitter.txt /*:TSBufEnableAll*
:TSInstall nvim-treesitter.txt /*:TSInstall*
:TSInstallInfo nvim-treesitter.txt /*:TSInstallInfo*
:TSModuleInfo nvim-treesitter.txt /*:TSModuleInfo*
nvim-treesitter nvim-treesitter.txt /*nvim-treesitter*
nvim-treesitter-commands nvim-treesitter.txt /*nvim-treesitter-commands*
nvim-treesitter-functions nvim-treesitter.txt /*nvim-treesitter-functions*
nvim-treesitter-intro nvim-treesitter.txt /*nvim-treesitter-intro*
nvim-treesitter-quickstart nvim-treesitter.txt /*nvim-treesitter-quickstart*
nvim_treesitter#statusline() nvim-treesitter.txt /*nvim_treesitter#statusline()*

View file

@ -1,30 +1,58 @@
local api = vim.api
local parsers = require'nvim-treesitter.parsers'
local configs = require 'nvim-treesitter.configs'
local install = require'nvim-treesitter.install'
local locals = require'nvim-treesitter.locals'
local highlight = require'nvim-treesitter.highlight'
local utils = require'nvim-treesitter.utils'
local info = require'nvim-treesitter.info'
local configs = require'nvim-treesitter.configs'
local M = {}
function M.available_parsers()
return vim.tbl_keys(configs.repositories)
end
-- This function sets up everythin needed for a given language
-- this is the main interface through the plugin
function M.setup(lang)
if parsers.has_parser(lang) then
local autocmd = "autocmd NvimTreesitter FileType %s lua require'nvim-treesitter.highlight'.setup()"
api.nvim_command(string.format(autocmd, lang))
utils.setup_commands('install', install.commands)
utils.setup_commands('info', info.commands)
utils.setup_commands('configs', configs.commands)
for _, ft in pairs(configs.available_parsers()) do
for _, mod in pairs(configs.available_modules()) do
if configs.is_enabled(mod, ft) then
local cmd = string.format("lua require'nvim-treesitter.%s'.attach()", mod)
api.nvim_command(string.format("autocmd FileType %s %s", ft, cmd))
end
end
end
end
-- This function initialize the plugin
-- it is run at startup
M._root = {}
function M._root.setup()
install.setup()
function M.statusline(indicator_size)
local indicator_size = indicator_size or 1000
local expr = require"nvim-treesitter.utils".expression_at_point()
local current_node =
require'nvim-treesitter.node_movement'.current_node[api.nvim_get_current_buf()]
local indicator = ""
while expr and (#indicator + #(expr:type()) + 5) < indicator_size do
local prefix = ""
if expr:parent() then
prefix = "->"
end
if expr == current_node then
indicator = string.format("%s[%s]%s", prefix, expr:type(), indicator)
else
indicator = prefix .. expr:type() .. indicator
end
expr = expr:parent()
end
if expr then
return "..." .. indicator
else
return indicator
end
end
return M

View file

@ -1,88 +1,421 @@
local M = {}
local api = vim.api
local queries = require'nvim-treesitter.query'
local parser_utils = require'nvim-treesitter.parsers'
local parsers = {}
M.repositories = {
javascript = {
parsers.javascript = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-javascript",
files = { "src/parser.c", "src/scanner.c" },
},
c = {
}
}
parsers.c = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-c",
files = { "src/parser.c" }
},
cpp = {
}
}
parsers.cpp = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-cpp",
files = { "src/parser.c", "src/scanner.cc" }
},
rust = {
}
}
parsers.rust = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-rust",
files = { "src/parser.c", "src/scanner.c" },
},
lua = {
}
}
parsers.lua = {
install_info = {
url = "https://github.com/nvim-treesitter/tree-sitter-lua",
files = { "src/parser.c", "src/scanner.cc" }
},
python = {
}
}
parsers.python = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-python",
files = { "src/parser.c", "src/scanner.cc" },
},
go = {
}
}
parsers.go = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-go",
files = { "src/parser.c" },
},
ruby = {
}
}
parsers.ruby = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-ruby",
files = { "src/parser.c", "src/scanner.cc" },
},
bash = {
}
}
parsers.bash = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-bash",
files = { "src/parser.c", "src/scanner.cc" },
},
php = {
}
}
parsers.php = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-php",
files = { "src/parser.c", "src/scanner.cc" },
},
java = {
}
}
parsers.java = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-java",
files = { "src/parser.c" },
},
html = {
}
}
parsers.html = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-html",
files = { "src/parser.c", "src/scanner.cc" },
},
julia = {
}
}
parsers.julia = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-julia",
files = { "src/parser.c", "src/scanner.c" },
},
json = {
}
}
parsers.json = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-json",
files = { "src/parser.c" },
},
css = {
}
}
parsers.css = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-css",
files = { "src/parser.c", "src/scanner.c" },
},
ocaml = {
}
}
parsers.ocaml = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-ocaml",
files = { "src/parser.c", "src/scanner.cc" },
},
swift = {
}
}
parsers.swift = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-swift",
files = { "src/parser.c" },
},
csharp = {
}
}
parsers.csharp = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-c-sharp",
files = { "src/parser.c", "src/scanner.c" },
},
typescript = {
}
}
parsers.typescript = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-typescript",
files = { "src/parser.c", "src/scanner.c" },
location = "tree-sitter-typescript/typescript"
},
tsx = {
}
}
parsers.tsx = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-typescript",
files = { "src/parser.c", "src/scanner.c" },
location = "tree-sitter-tsx/tsx"
}
}
parsers.scala = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-scala",
files = { "src/parser.c", "src/scanner.c" },
}
}
parsers.haskell = {
install_info = {
url = "https://github.com/tree-sitter/tree-sitter-haskell",
files = { "src/parser.c", "src/scanner.cc" },
}
}
parsers.markdown = {
install_info = {
url = "https://github.com/ikatyang/tree-sitter-markdown",
files = { "src/parser.c", "src/scanner.cc" },
}
}
parsers.toml = {
install_info = {
url = "https://github.com/ikatyang/tree-sitter-toml",
files = { "src/parser.c", "src/scanner.c" },
}
}
parsers.vue = {
install_info = {
url = "https://github.com/ikatyang/tree-sitter-vue",
files = { "src/parser.c", "src/scanner.cc" },
}
}
parsers.elm = {
install_info = {
url = "https://github.com//razzeee/tree-sitter-elm",
files = { "src/parser.c", "src/scanner.cc" },
}
}
parsers.yaml = {
install_info = {
url = "https://github.com/ikatyang/tree-sitter-yaml",
files = { "src/parser.c", "src/scanner.cc" },
}
}
parsers.nix = {
install_info = {
url = "https://github.com/cstrahan/tree-sitter-nix",
files = { "src/parser.c", "src/scanner.cc" },
}
}
-- @enable can be true or false
-- @disable is a list of languages, only relevant if enable is true
-- @keymaps list of user mappings for a given module if relevant
-- @is_supported function which, given a ft, will return true if the ft works on the module
local config = {
modules = {
highlight = {
enable = false,
disable = {},
is_supported = function(ft)
return queries.get_query(ft, 'highlights') ~= nil
end
},
incremental_selection = {
enable = false,
disable = {},
keymaps = {
node_incremental="grn",
scope_incremental="grc"
},
is_supported = function() return true end
},
node_movement = {
enable = false,
disable = {},
is_supported = function() return true end,
keymaps = {
move_up = "<a-k>",
move_down = "<a-j>",
move_left = "<a-h>",
move_right = "<a-l>",
},
},
-- folding = {
-- enable = false,
-- disable = {},
-- keymaps = {},
-- is_supported = function() return false end
-- }
},
ensure_installed = nil
}
local M = {}
local function enable_module(mod, bufnr, ft)
local bufnr = bufnr or api.nvim_get_current_buf()
local ft = ft or api.nvim_buf_get_option(bufnr, 'ft')
if not parsers[ft] or not config.modules[mod] then
return
end
local loaded_mod = require(string.format("nvim-treesitter.%s", mod))
loaded_mod.attach(bufnr, ft)
end
local function enable_mod_conf_autocmd(mod, ft)
if not config.modules[mod] or M.is_enabled(mod, ft) then return end
local cmd = string.format("lua require'nvim-treesitter.%s'.attach()", mod)
api.nvim_command(string.format("autocmd FileType %s %s", ft, cmd))
for i, parser in pairs(config.modules[mod].disable) do
if parser == ft then
table.remove(config.modules[mod].disable, i)
break
end
end
end
local function enable_all(mod, ft)
if not config.modules[mod] then return end
for _, bufnr in pairs(api.nvim_list_bufs()) do
if not ft or api.nvim_buf_get_option(bufnr, 'ft') == ft then
enable_module(mod, bufnr, ft)
end
end
if ft then
if parser_utils.has_parser(ft) then
enable_mod_conf_autocmd(mod, ft)
end
else
for _, ft in pairs(M.available_parsers()) do
if parser_utils.has_parser(ft) then
enable_mod_conf_autocmd(mod, ft)
end
end
end
config.modules[mod].enable = true
end
local function disable_module(mod, bufnr, ft)
local bufnr = bufnr or api.nvim_get_current_buf()
local ft = ft or api.nvim_buf_get_option(bufnr, 'ft')
if not parsers[ft] or not config.modules[mod] then
return
end
local loaded_mod = require(string.format("nvim-treesitter.%s", mod))
loaded_mod.detach(bufnr, ft)
end
local function disable_mod_conf_autocmd(mod, ft)
if not config.modules[mod] or not M.is_enabled(mod, ft) then return end
api.nvim_command(string.format("autocmd! FileType %s", ft))
table.insert(config.modules[mod].disable, ft)
end
local function disable_all(mod, ft)
for _, bufnr in pairs(api.nvim_list_bufs()) do
if not ft or api.nvim_buf_get_option(bufnr, 'ft') == ft then
disable_module(mod, bufnr, ft)
end
end
if ft then
disable_mod_conf_autocmd(mod, ft)
else
for _, ft in pairs(M.available_parsers()) do
disable_mod_conf_autocmd(mod, ft)
end
config.modules[mod].enable = false
end
end
M.commands = {
TSBufEnable = {
run = enable_module,
args = {
"-nargs=1",
"-complete=custom,v:lua.ts_available_modules"
},
description = '`:TSBufEnable module_name` enable a specified module on the current buffer'
},
TSBufDisable = {
run = disable_module,
args = {
"-nargs=1",
"-complete=custom,v:lua.ts_available_modules"
},
description = '`:TSBufDisable module_name` disable a specified module on the current buffer'
},
TSEnableAll = {
run = enable_all,
args = {
"-nargs=+",
"-complete=custom,v:lua.ts_available_modules"
},
description = '`:TSEnableAll module_name (filetype)` enables a specified module on all buffers. If filetype is specified, enable only for specified filetype'
},
TSDisableAll = {
run = disable_all,
args = {
"-nargs=+",
"-complete=custom,v:lua.ts_available_modules"
},
description = '`:TSDisableAll module_name (filetype)` disables a specified module on all buffers. If filetype is specified, disable only for specified filetype'
},
}
-- @param mod: module (string)
-- @param ft: filetype (string)
function M.is_enabled(mod, ft)
if not M.get_parser_configs()[ft] or not parser_utils.has_parser(ft) then
return false
end
local module_config = config.modules[mod]
if not module_config then return false end
if not module_config.enable or not module_config.is_supported(ft) then
return false
end
for _, parser in pairs(module_config.disable) do
if ft == parser then return false end
end
return true
end
function M.setup(user_data)
if not user_data then return end
for mod, data in pairs(user_data) do
if config.modules[mod] then
if type(data.enable) == 'boolean' then
config.modules[mod].enable = data.enable
end
if type(data.disable) == 'table' then
config.modules[mod].disable = data.disable
end
if config.modules[mod].keymaps and type(data.keymaps) == 'table' then
config.modules[mod].keymaps = data.keymaps
end
elseif mod == 'ensure_installed' then
config.ensure_installed = data
require'nvim-treesitter/install'.ensure_installed(data)
end
end
end
function M.get_parser_configs()
return parsers
end
function M.available_parsers()
return vim.tbl_keys(parsers)
end
function M.available_modules()
return vim.tbl_keys(config.modules)
end
function M.get_module(mod)
return config.modules[mod]
end
return M

View file

@ -3,6 +3,7 @@ local fn = vim.fn
local queries = require'nvim-treesitter.query'
local locals = require'nvim-treesitter.locals'
local highlight = require'nvim-treesitter.highlight'
local configs = require'nvim-treesitter.configs'
local health_start = vim.fn["health#report_start"]
@ -13,7 +14,7 @@ local health_error = vim.fn['health#report_error']
local M = {}
local function configs_health()
local function install_health()
if fn.executable('git') == 0 then
health_error('`git` executable not found.', {
'Install it with your package manager.',
@ -34,15 +35,36 @@ local function configs_health()
end
end
local function highlight_health(lang)
if not queries.get_query(lang, "highlights") then
health_warn("No `highlights.scm` query found for " .. lang, {
"Open an issue at https://github.com/nvim-treesitter/nvim-treesitter"
})
else
health_ok("`highlights.scm` found.")
end
end
function locals_health(lang)
if not queries.get_query(lang, "locals") then
health_warn("No `locals.scm` query found for " .. lang, {
"Open an issue at https://github.com/nvim-treesitter/nvim-treesitter"
})
else
health_ok("`locals.scm` found.")
end
end
-- TODO(vigoux): Maybe we should move each check to be perform in its own module
function M.checkhealth()
-- Installation dependency checks
health_start('Installation')
configs_health()
install_health()
local missing_parsers = {}
-- Parser installation checks
for parser_name in pairs(configs.repositories) do
for _, parser_name in pairs(configs.available_parsers()) do
local installed = #api.nvim_get_runtime_file('parser/'..parser_name..'.so', false)
-- Only print informations about installed parsers
@ -50,7 +72,8 @@ function M.checkhealth()
health_start(parser_name .. " parser healthcheck")
health_ok(parser_name .. " parser found.")
locals.checkhealth(parser_name)
locals_health(parser_name)
highlight_health(parser_name)
elseif installed > 1 then
health_warn(string.format("Multiple parsers found for %s, only %s will be used.", parser_name, installed[1]))
else

View file

@ -1,12 +1,53 @@
local api = vim.api
local queries = require'nvim-treesitter.query'
local ts = vim.treesitter
local queries = require'nvim-treesitter.query'
local M = {
highlighters={}
highlighters = {}
}
function M.setup(bufnr, ft)
local hlmap = vim.treesitter.TSHighlighter.hl_map
-- Misc
hlmap.error = "Error"
hlmap["punctuation.delimiter"] = "Delimiter"
hlmap["punctuation.bracket"] = "Delimiter"
-- Constants
hlmap["constant"] = "Constant"
hlmap["constant.builtin"] = "Special"
hlmap["constant.macro"] = "Define"
hlmap["string"] = "String"
hlmap["string.regex"] = "String"
hlmap["string.escape"] = "SpecialChar"
hlmap["character"] = "Character"
hlmap["number"] = "Number"
hlmap["boolean"] = "Boolean"
hlmap["float"] = "Float"
-- Functions
hlmap["function"] = "Function"
hlmap["function.builtin"] = "Special"
hlmap["function.macro"] = "Macro"
hlmap["parameter"] = "Identifier"
hlmap["method"] = "Function"
hlmap["field"] = "Identifier"
hlmap["property"] = "Identifier"
hlmap["constructor"] = "Special"
-- Keywords
hlmap["conditional"] = "Conditional"
hlmap["repeat"] = "Repeat"
hlmap["label"] = "Label"
hlmap["operator"] = "Operator"
hlmap["keyword"] = "Keyword"
hlmap["exception"] = "Exception"
hlmap["type"] = "Type"
hlmap["type.builtin"] = "Type"
hlmap["structure"] = "Structure"
function M.attach(bufnr, ft)
local buf = bufnr or api.nvim_get_current_buf()
local ft = ft or api.nvim_buf_get_option(buf, 'ft')
@ -16,4 +57,13 @@ function M.setup(bufnr, ft)
M.highlighters[buf] = ts.TSHighlighter.new(query, buf, ft)
end
function M.detach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
if M.highlighters[buf] then
M.highlighters[buf]:set_query("")
M.highlighters[buf] = nil
end
api.nvim_buf_set_option(buf, 'syntax', 'on')
end
return M

View file

@ -0,0 +1,78 @@
local api = vim.api
local utils = require'nvim-treesitter.utils'
local parsers = require'nvim-treesitter.parsers'
local M = {}
local function node_range_to_vim(node)
if not node then return end
local start_row, start_col, end_row, end_col = node:range()
local select_range = [[
call cursor(%d, %d)
normal v
call cursor(%d, %d)
]]
local exec_command = string.format(select_range,
start_row+1, start_col+1,
end_row+1, end_col+1)
api.nvim_exec(exec_command, false)
end
local function select_incremental(increment_func)
return function()
local buf, sel_start_line, sel_start_col, _ = unpack(vim.fn.getpos("'<"))
local buf, sel_end_line, sel_end_col, _ = unpack(vim.fn.getpos("'>"))
local node = nil
if parsers.has_parser() then
local root = parsers.get_parser():parse():root()
node = root:named_descendant_for_range(sel_start_line-1, sel_start_col-1, sel_end_line-1, sel_end_col)
local node_start_row, node_start_col, node_end_row, node_end_col = node:range()
if (sel_start_line-1) == node_start_row and (sel_start_col-1) == node_start_col
and (sel_end_line-1) == node_end_row and sel_end_col == node_end_col then
node = increment_func(node)
end
end
return node_range_to_vim(node)
end
end
M.node_incremental = select_incremental(function(node)
if node then
return node:parent() or node
end
end)
M.scope_incremental = select_incremental(function(node)
if node then
return utils.smallest_containing_scope(node:parent() or node)
end
end)
function M.attach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
local config = require'nvim-treesitter.configs'.get_module('incremental_selection')
for funcname, mapping in pairs(config.keymaps) do
api.nvim_buf_set_keymap(buf, 'v', mapping,
string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname), { silent = true })
api.nvim_buf_set_keymap(buf, 'o', mapping,
string.format(":normal v%s<CR>", mapping), { silent = true })
end
end
function M.detach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
local config = require'nvim-treesitter.configs'.get_module('incremental_selection')
for _, mapping in pairs(config.keymaps) do
api.nvim_buf_del_keymap(buf, 'v', mapping)
api.nvim_buf_del_keymap(buf, 'o', mapping)
end
end
return M

View file

@ -0,0 +1,96 @@
local api = vim.api
local configs = require'nvim-treesitter.configs'
local M = {}
local function install_info()
local max_len = 0
for _, ft in pairs(configs.available_parsers()) do
if #ft > max_len then max_len = #ft end
end
for _, ft in pairs(configs.available_parsers()) do
local is_installed = #api.nvim_get_runtime_file('parser/'..ft..'.so', false) > 0
api.nvim_out_write(ft..string.rep(' ', max_len - #ft + 1))
if is_installed then
api.nvim_out_write("[✓] installed\n")
else
api.nvim_out_write("[✗] not installed\n")
end
end
end
local function print_info_module(sorted_filetypes, mod)
local max_str_len = #sorted_filetypes[1]
local header = string.format('%s%s', string.rep(' ', max_str_len + 2), mod)
api.nvim_out_write(header..'\n')
for _, ft in pairs(sorted_filetypes) do
local padding = string.rep(' ', max_str_len - #ft + #mod / 2 + 1)
api.nvim_out_write(ft..":"..padding)
if configs.is_enabled(mod, ft) then
api.nvim_out_write('')
else
api.nvim_out_write('')
end
api.nvim_out_write('\n')
end
end
local function print_info_modules(sorted_filetypes)
local max_str_len = #sorted_filetypes[1]
local header = string.rep(' ', max_str_len + 2)
for _, mod in pairs(configs.available_modules()) do
header = string.format('%s%s ', header, mod)
end
api.nvim_out_write(header..'\n')
for _, ft in pairs(sorted_filetypes) do
local padding = string.rep(' ', max_str_len - #ft)
api.nvim_out_write(ft..":"..padding)
for _, mod in pairs(configs.available_modules()) do
local pad_len = #mod / 2 + 1
api.nvim_out_write(string.rep(' ', pad_len))
if configs.is_enabled(mod, ft) then
api.nvim_out_write('')
else
api.nvim_out_write('')
end
api.nvim_out_write(string.rep(' ', pad_len - 1))
end
api.nvim_out_write('\n')
end
end
local function module_info(mod)
if mod and not configs.get_config()[mod] then return end
local ft_by_len = configs.available_parsers()
table.sort(ft_by_len, function(a, b) return #a > #b end)
if mod then
print_info_module(ft_by_len, mod)
else
print_info_modules(ft_by_len)
end
end
M.commands = {
TSInstallInfo = {
run = install_info,
args = {
"-nargs=0",
},
description = '`:TSInstallInfo` print installation state for every filetype'
},
TSModuleInfo = {
run = module_info,
args = {
"-nargs=?",
"-complete=custom,v:lua.ts_available_modules"
},
description = '`:TSModuleInfo` print module state for every filetype, if module is specified, only for current module'
}
}
return M

View file

@ -1,7 +1,9 @@
local api = vim.api
local fn = vim.fn
local luv = vim.loop
local repositories = require'nvim-treesitter/configs'.repositories
local configs = require'nvim-treesitter/configs'
local parsers = configs.get_parser_configs()
local has_parser = require'nvim-treesitter/parsers'.has_parser
local M = {}
@ -33,14 +35,16 @@ local function get_cache_dir()
end
local function iter_cmd(cmd_list, i, ft)
if i == #cmd_list then return print('Treesitter parser for '..ft..' has been installed') end
if i == #cmd_list + 1 then return print('Treesitter parser for '..ft..' has been installed') end
local attr = cmd_list[i + 1]
local attr = cmd_list[i]
if attr.info then print(attr.info) end
local handle
handle = luv.spawn(attr.cmd, attr.opts, vim.schedule_wrap(function(code)
handle:close()
if code ~= 0 then return api.nvim_err_writeln(attr.err) end
if code ~= 0 then return api.nvim_err_writeln(attr.err) end
iter_cmd(cmd_list, i + 1, ft)
end))
end
@ -75,12 +79,12 @@ local function run_install(cache_folder, package_path, ft, repo)
args = vim.tbl_flatten({
'-o',
'parser.so',
'-I./src',
repo.files,
'-shared',
'-Os',
'-lstdc++',
'-fPIC',
'-Os',
'-I./src',
repo.files
}),
cwd = compile_location
}
@ -99,7 +103,7 @@ local function run_install(cache_folder, package_path, ft, repo)
}
}
iter_cmd(command_list, 0, ft)
iter_cmd(command_list, 1, ft)
end
-- TODO(kyazdani): this should work on windows too
@ -118,14 +122,15 @@ local function install(ft)
if not string.match(yesno, '^y.*') then return end
end
local repository = repositories[ft]
if not repository then
local parser_config = parsers[ft]
if not parser_config then
return api.nvim_err_writeln('Parser not available for language '..ft)
end
local install_info = parser_config.install_info
vim.validate {
url={ repository.url, 'string' },
files={ repository.files, 'table' }
url={ install_info.url, 'string' },
files={ install_info.files, 'table' }
}
if fn.executable('git') == 0 then
@ -138,26 +143,27 @@ local function install(ft)
local cache_folder, err = get_cache_dir()
if err then return api.nvim_err_writeln(err) end
run_install(cache_folder, package_path, ft, repository)
run_install(cache_folder, package_path, ft, install_info)
end
local function install_info()
local max_len = 0
for parser_name, _ in pairs(repositories) do
if #parser_name > max_len then max_len = #parser_name end
M.ensure_installed = function(languages)
if type(languages) == 'string' then
if languages == 'all' then
languages = configs.available_parsers()
else
languages = {languages}
end
end
for parser_name, _ in pairs(repositories) do
local is_installed = #api.nvim_get_runtime_file('parser/'..parser_name..'.so', false) > 0
api.nvim_out_write(parser_name..string.rep(' ', max_len - #parser_name + 1))
if is_installed then
api.nvim_out_write("[✓] installed\n")
else
api.nvim_out_write("[✗] not installed\n")
for _, ft in ipairs(languages) do
if not has_parser(ft) then
install(ft)
end
end
end
M.commands = {
TSInstall = {
run = install,
@ -166,25 +172,7 @@ M.commands = {
"-complete=custom,v:lua.ts_installable_parsers"
},
description = '`:TSInstall {ft}` installs a parser under nvim-treesitter/parser/{name}.so'
},
TSInstallInfo = {
run = install_info,
args = { "-nargs=0" },
description = '`:TSInstallInfo` print installation state for every filetype'
}
}
function M.setup()
for command_name, def in pairs(M.commands) do
local call_fn = string.format("lua require'nvim-treesitter.install'.commands.%s.run(<f-args>)", command_name)
local parts = vim.tbl_flatten({
"command!",
def.args,
command_name,
call_fn,
})
api.nvim_command(table.concat(parts, " "))
end
end
return M

View file

@ -10,22 +10,6 @@ local M = {
locals={}
}
function M.checkhealth(lang)
local health_start = vim.fn["health#report_start"]
local health_ok = vim.fn['health#report_ok']
local health_info = vim.fn['health#report_info']
local health_warn = vim.fn['health#report_warn']
local health_error = vim.fn['health#report_error']
if not queries.get_query(lang, "locals") then
health_warn("No `locals.scm` query found for " .. lang, {
"Open an issue at https://github.com/nvim-treesitter/nvim-treesitter"
})
else
health_ok("`locals.scm` found.")
end
end
function M.collect_locals(bufnr)
local ft = api.nvim_buf_get_option(bufnr, "ft")
if not ft then return end
@ -69,7 +53,7 @@ function M.get_definitions(bufnr)
for _, loc in ipairs(locals) do
if loc.definition then
table.insert(defs, {definition=loc.definition, kind=loc.kind})
table.insert(defs, loc.definition)
end
end
@ -82,8 +66,8 @@ function M.get_scopes(bufnr)
local scopes = {}
for _, loc in ipairs(locals) do
if loc.scope then
table.insert(scopes, loc.scope)
if loc.scope and loc.scope.node then
table.insert(scopes, loc.scope.node)
end
end
@ -96,8 +80,8 @@ function M.get_references(bufnr)
local refs = {}
for _, loc in ipairs(locals) do
if loc.reference then
table.insert(refs, loc.reference)
if loc.reference and loc.reference.node then
table.insert(refs, loc.reference.node)
end
end

View file

@ -0,0 +1,91 @@
local api = vim.api
local parsers = require'nvim-treesitter.parsers'
local utils = require'nvim-treesitter.utils'
local M = {}
M.NodeMovementKind = {
up = 'up',
down = 'down',
left = 'left',
right = 'right',
}
M.current_node = {}
local function node_start_to_vim(node)
if not node then return end
local row, col = node:start()
local exec_command = string.format('call cursor(%d, %d)', row+1, col+1)
api.nvim_exec(exec_command, false)
end
M.do_node_movement = function(kind)
local buf, line, col = unpack(vim.fn.getpos("."))
local current_node = M.current_node[buf]
if current_node then
local node_line, node_col = current_node:start()
if line-1 ~= node_line or col-1 ~= node_col then
current_node = nil
end
end
local destination_node
if parsers.has_parser() then
local root = parsers.get_parser():parse():root()
if not current_node then
current_node = root:named_descendant_for_range(line-1, col-1, line-1, col)
end
if kind == M.NodeMovementKind.up then
destination_node = current_node:parent()
elseif kind == M.NodeMovementKind.down then
if current_node:named_child_count() > 0 then
destination_node = current_node:named_child(0)
else
local next_node = utils.get_next_node(current_node)
if next_node and next_node:named_child_count() > 0 then
destination_node = next_node:named_child(0)
end
end
elseif kind == M.NodeMovementKind.left then
destination_node = utils.get_previous_node(current_node, true, true)
elseif kind == M.NodeMovementKind.right then
destination_node = utils.get_next_node(current_node, true, true)
end
M.current_node[buf] = destination_node or current_node
end
if destination_node then
node_start_to_vim(destination_node)
end
end
M.move_up = function() M.do_node_movement(M.NodeMovementKind.up) end
M.move_down = function() M.do_node_movement(M.NodeMovementKind.down) end
M.move_left = function() M.do_node_movement(M.NodeMovementKind.left) end
M.move_right = function() M.do_node_movement(M.NodeMovementKind.right) end
function M.attach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
local config = require'nvim-treesitter.configs'.get_module('node_movement')
for funcname, mapping in pairs(config.keymaps) do
api.nvim_buf_set_keymap(buf, 'n', mapping,
string.format(":lua require'nvim-treesitter.node_movement'.%s()<CR>", funcname), { silent = true })
end
end
function M.detach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
local config = require'nvim-treesitter.configs'.get_module('node_movement')
for _, mapping in pairs(config.keymaps) do
api.nvim_buf_del_keymap(buf, 'n', mapping)
end
end
return M

View file

@ -5,11 +5,12 @@ local M = {}
function M.has_parser(lang)
local lang = lang or api.nvim_buf_get_option(0, 'filetype')
if not lang or #lang == 0 then return false end
return #api.nvim_get_runtime_file('parser/' .. lang .. '.*', false) > 0
end
function M.get_parser(bufnr, lang)
if M.has_parser() then
if M.has_parser(lang) then
local buf = bufnr or api.nvim_get_current_buf()
local lang = lang or api.nvim_buf_get_option(buf, 'ft')
if not M[buf] then

View file

@ -1,6 +1,7 @@
-- Utils collection for nvim-treesitter
local api = vim.api
local parsers = require'nvim-treesitter.parsers'
local locals = require'nvim-treesitter.locals'
local M = {}
@ -63,4 +64,92 @@ function M.is_parent(dest, source)
return false
end
function M.setup_commands(mod, commands)
for command_name, def in pairs(commands) do
local call_fn = string.format("lua require'nvim-treesitter.%s'.commands.%s.run(<f-args>)", mod, command_name)
local parts = vim.tbl_flatten({
"command!",
def.args,
command_name,
call_fn,
})
api.nvim_command(table.concat(parts, " "))
end
end
--- Gets the smallest scope which contains @param node
function M.smallest_containing_scope(node, bufnr)
local bufnr = bufnr or api.nvim_get_current_buf()
local root = parsers.get_parser(bufnr):parse():root()
if not node then return root end
local scopes = locals.get_scopes(bufnr)
local current = node
while current ~= nil and not vim.tbl_contains(scopes, current) do
current = current:parent()
end
return current or root
end
--- Get next node with same parent
-- @param node node
-- @param allow_switch_parents allow switching parents if last node
-- @param allow_next_parent allow next parent if last node and next parent without children
function M.get_next_node(node, allow_switch_parents, allow_next_parent)
local destination_node
local parent = node:parent()
if parent then
local found_pos = 0
for i = 0,parent:named_child_count()-1,1 do
if parent:named_child(i) == node then
found_pos = i
break
end
end
if parent:named_child_count() > found_pos + 1 then
destination_node = parent:named_child(found_pos + 1)
elseif allow_switch_parents then
local next_node = M.get_next_node(node:parent())
if next_node and next_node:named_child_count() > 0 then
destination_node = next_node:named_child(0)
elseif next_node and allow_next_parent then
destination_node = next_node
end
end
end
return destination_node
end
--- Get previous node with same parent
-- @param node node
-- @param allow_switch_parents allow switching parents if first node
-- @param allow_previous_parent allow previous parent if first node and previous parent without children
function M.get_previous_node(node, allow_switch_parents, allow_previous_parent)
local destination_node
local parent = node:parent()
if parent then
local found_pos = 0
for i = 0,parent:named_child_count()-1,1 do
if parent:named_child(i) == node then
found_pos = i
break
end
end
if 0 < found_pos then
destination_node = parent:named_child(found_pos - 1)
elseif allow_switch_parents then
local previous_node = M.get_previous_node(node:parent())
if previous_node and previous_node:named_child_count() > 0 then
destination_node = previous_node:named_child(previous_node:named_child_count() - 1)
elseif previous_node and allow_previous_parent then
destination_node = previous_node
end
end
end
return destination_node
end
return M

View file

@ -1,17 +1,20 @@
" Last Change: 2020 avril 19
" Last Change: 2020 avril 25
if exists('g:loaded_nvim_treesitter')
finish
endif
lua << EOF
ts_installable_parsers = function()
return table.concat(require'nvim-treesitter'.available_parsers(), '\n')
end
require'nvim-treesitter'._root.setup()
EOF
augroup NvimTreesitter
augroup END
let g:loaded_nvim_treesitter = 1
augroup NvimTreesitter
augroup END
lua << EOF
ts_installable_parsers = function()
return table.concat(require'nvim-treesitter.configs'.available_parsers(), '\n')
end
ts_available_modules = function()
return table.concat(require'nvim-treesitter.configs'.available_modules(), '\n')
end
require'nvim-treesitter'.setup()
EOF

View file

@ -3,16 +3,16 @@
;;; Builtins
;; Keywords
"local" @keyword
"if" @keyword
"then" @keyword
"else" @keyword
"elseif" @keyword
"if" @conditional
"then" @conditional
"else" @conditional
"elseif" @conditional
"end" @keyword
"return" @keyword
"do" @keyword
"while" @keyword
"repeat" @keyword
"for" @keyword
"do" @repeat
"while" @repeat
"repeat" @repeat
"for" @repeat
(break_statement) @keyword
"goto" @keyword
@ -43,15 +43,16 @@
"#" @operator
;; Constants
(false) @constant
(true) @constant
(nil) @constant
(false) @boolean
(true) @boolean
(nil) @constant.builtin
(spread) @constant ;; "..."
;; Nodes
(function "function" @function "end" @function)
(function_definition "function" @function "end" @function)
(local_function "function" @function "end" @function)
(table "{" @operator "}" @operator)
(table "{" @constructor "}" @constructor)
(comment) @comment
(string) @string
(number) @number

View file

@ -2,25 +2,20 @@
;; Variable and field declarations
((variable_declarator
(identifier) @definition)
(set! definition.kind "v"))
(identifier) @definition.var))
((variable_declarator
(field_expression object:(*) @definition.associated (property_identifier) @definition))
(set! difinition.kind "v"))
(field_expression object:(*) @definition.associated (property_identifier) @definition.var)))
;; Parameters
((local_function
(parameters (identifier) @definition))
(set! definition.kind "v"))
(parameters (identifier) @definition.var)))
((function
(parameters (identifier) @definition))
(set! definition.kind "v"))
(parameters (identifier) @definition.var)))
;; Loops
((loop_expression
(identifier) @definition)
(set! definition.kind "v"))
(identifier) @definition.var))
;; Function definitions
;; Functions definitions creates both a definition and a new scope
@ -28,16 +23,13 @@
(function_name
(function_name_field
(identifier) @definition.associated
(property_identifier) @definition))) @scope
(set! definition.kind "m"))
(property_identifier) @definition.method))) @scope)
((function
(function_name (identifier) @definition)) @scope
(set! definition.kind "f"))
(function_name (identifier) @definition.function)) @scope)
((local_function
(identifier) @definition) @scope
(set! definition.kind "f"))
(identifier) @definition.function) @scope)
((if_statement) @scope)
((for_in_statement) @scope)

140
queries/ruby/highlights.scm Normal file
View file

@ -0,0 +1,140 @@
; Keywords
"alias" @keyword
"and" @keyword
"begin" @keyword
"break" @keyword
"case" @keyword
"class" @keyword
"def" @keyword
"do" @keyword
"else" @keyword
"elsif" @keyword
"end" @keyword
"ensure" @keyword
"for" @keyword
"if" @keyword
"in" @keyword
"module" @keyword
"next" @keyword
"or" @keyword
"rescue" @keyword
"retry" @keyword
"return" @keyword
"then" @keyword
"unless" @keyword
"until" @keyword
"when" @keyword
"while" @keyword
"yield" @keyword
((identifier) @keyword
(match? @keyword "^(private|protected|public)$"))
; Function calls
((identifier) @function
(eq? @function "require"))
"defined?" @function
(call
receiver: (constant) @constant)
(method_call
receiver: (constant) @constant)
(call
method: (identifier) @function)
(method_call
method: (identifier) @function)
(call
method: (constant) @function)
(method_call
method: (constant) @function)
; Function definitions
(alias (identifier) @function)
(setter (identifier) @function)
(method name: (identifier) @function)
(method name: (constant) @constant)
(class name: (constant) @constant)
(singleton_method name: (identifier) @function)
(singleton_method name: (constant) @constant)
; Identifiers
(class_variable) @Identifier
(instance_variable) @Identifier
((identifier) @constant
(match? @constant "^__(FILE|LINE|ENCODING)__$"))
((constant) @constant
(match? @constant "^[A-Z\\d_]+$"))
(constant) @constant
(self) @constant
(super) @Identifier
(method_parameters (identifier) @Type)
(lambda_parameters (identifier) @Type)
(block_parameters (identifier) @Type)
(splat_parameter (identifier) @Type)
(hash_splat_parameter (identifier) @Type)
(optional_parameter (identifier) @Type)
(destructured_parameter (identifier) @Type)
(block_parameter (identifier) @Type)
(keyword_parameter (identifier) @Type)
((identifier) @function
(is-not? local))
; Literals
(string) @string
(bare_string) @string
(bare_symbol) @constant
(subshell) @string
(heredoc_beginning) @Delimiter
(heredoc_body) @string
(heredoc_end) @Delimiter
(symbol) @constant
(regex) @string
(escape_sequence) @Special
(integer) @number
(float) @number
(nil) @Identifier
(true) @Identifier
(false) @Identifier
(interpolation
"#{" @Delimiter
(identifier) @Identifier
"}" @Delimiter) @embedded
(comment) @comment
; Operators
"=" @operator
"=>" @operator
"->" @operator
"+" @operator
"-" @operator
"*" @operator
"/" @operator
"," @Normal
";" @Normal
"." @Normal
"(" @Normal
")" @Normal
"[" @Normal
"]" @Normal
"{" @Normal
"}" @Normal
"%w(" @Normal
"%i(" @Normal

45
queries/ruby/locals.scm Normal file
View file

@ -0,0 +1,45 @@
; The MIT License (MIT)
;
; Copyright (c) 2016 Rob Rix
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
;;; DESCLARATIONS AND SCOPES
((method) @scope
(set! scope-inherits false))
(block) @scope
(do_block) @scope
(method_parameters (identifier) @definition)
(lambda_parameters (identifier) @definition)
(block_parameters (identifier) @definition)
(splat_parameter name: (identifier) @definition)
(hash_splat_parameter name: (identifier) @definition)
(optional_parameter name: (identifier) @definition)
(destructured_parameter name: (identifier) @definition)
(block_parameter name: (identifier) @definition)
(keyword_parameter name: (identifier) @definition)
(identifier) @reference
(assignment left:(identifier) @definition)
(left_assignment_list (identifier) @definition)
(rest_assignment (identifier) @definition)
(destructured_left_assignment (identifier) @definition)