Support for Julia language
phgz opened this issue · 11 comments
Hi,
This seems a great plugin. Could it be implemented for Julia as well? The syntax is very similar to the Ruby one.
Thank you!
I'm open to having Julia support added, but since it's not a language I've ever used I wouldn't implement it myself and instead would be willing to help guide someone with Julia experience to implement it. I'll give some details below on how to add support.
Adding support is as simple as added a single tree-sitter query file, see https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries for query syntax. Make a file queries/julia/endwise.scm
, this is where the queries will go. There will be generally two queries for each thing which can have an end
node added to it: when the parsing fails, and when the parsing succeeds. To get a better understanding of this, let's take a look at Lua which has a decently simple grammar.
In Lua, we have the following queries, https://github.com/RRethy/nvim-treesitter-endwise/blob/master/queries/lua/endwise.scm. Let's focus on the function definition queries, of which there are two:
((ERROR ("function" . (_)? . (parameters) @cursor) @indent) (#endwise! "end"))
The first query with ERROR
is simple and will match the following:
function foo()<cursor>
Since we are working with syntax trees that have an error in them, we will expect the parser to be in a weird state and not be able to parse this code into a function_definition
node, instead it gets parsed as a sequence of tokens and nodes and placed into the generic ERROR
node to signify that the parser couldn't make sense of this sequence of tokens. In this example, we have a "function"
followed by an (identifier)
followed by (parameters)
. We also have two captures, @cursor
to mark where we expect the users cursor to be in the query match, and @indent
to signify what kind of indentation the end
node should have when we place it. Lastly, we also have the #endwise!
directive which is how we can configure the end
node, if we made it foo
then the text that gets inserted would be that.
Let's now take a look at the second query:
((function_definition parameters: (_) @cursor) @endable @indent (#endwise! "end"))
This one is a bit more complicated but it's a side effect of tree-sitter generating parsers which follow maximal-munch. Let's take a look at a piece of code:
function foo()
function bar()<cursor>
end
If we look at this, we know that the end
token is for the foo
function, but the parser will parse it as part of the bar
function which means the bar
function will have a valid parse tree even though it shouldn't. To get around this, we can use the @indent
in conjunction with the @endable
capture group, if the last child of the node captured by @endable
has a different indentation than the node captured by @indent
, and if an ancestor node in the syntax tree has an error, then we can assume that the end
node is actually meant to be a part of a different node. As such, we insert an end
node with matching indentation.
To help you with writing queries, try writing some Julia code which you would expect to have an end
node added, then run :TSPlayground
and inspect the syntax tree (pressing a
in the playground shows anonymous nodes). You can also add tests in tests/endwise/julia.rb
that follow tests/endwise/lua.rb
to verify your queries work. The consist of a few lines prefixed by a -
with a █
to mark the initial cursor position, followed by lines prefixed by a +
to show the expected end state of the text. You can run these tests with ruby ./tests/runner.rb <keyword>
where <keyword>
is something to match the provided description (or empty to match all tests).
Thank you much for the detailed guidelines. I am myself still learning the language, so it will be a good challenge. I am however quite occupied these days, so i will not be able to give it a grasp in the coming days, but as soon as I do, I will start working on it.
As you say, I think it will be straightforward since the syntax is so similar to ruby
and lua
.
I will try to make a PR when it is ready 😄.
I think @jasonrhansen has started work on adding Julia support FWIW (https://github.com/jasonrhansen/nvim-treesitter-endwise/tree/julia).
Oh, I just saw that! Well awesome then.
Can you review the Julia PR linked to go through the use-cases.
I will be able to check it after next week (exams).
Sorry for the delay!
Have you had a chance to take a look through the PR?
Yes, it seems OK!
The only thing I don't understand is why, when I'm here
for i in 1:5
|
end
and press ENTER
, then it triggers another end
.
Can you comment that on the PR as part of a PR review.
Bumping this, can you provide a PR review on that PR raising the issues you found.