diff --git a/README.md b/README.md
index 66d2692..9cf6b0a 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,122 @@ syntax, and slightly changed to reduce some conflicts. Tree-sitter
doesn't need a full syntax tree, so we can take some shortcuts in
the grammar.
-
## Installation
-Execute the following commands:
+You will need neovim at least version 8.0 (not tested with earlier version).
+
+Installation is very manual at this stage, until we can integrate this package
+inside nvim-treesitter itself. At the moment, assuming you are using lua
+configuration and Packer for your package management:
+
+```lua
+-- file: ~/.config/nvim/init.lua
+
+-- Merge this with any existing Packer configuration you might already
+-- have. This loads packer itself, then loads the new `ada.nvim` package.
+require('packer').startup(function(use)
+ use(require('mytreesitter.nvim'))
+end)
```
+
+Then create a new file to setup treesitter (or merge with an existing
+configuration of course).
+```lua
+-- file: ~/.config/nvim/mytreesitter.nvim
+
+return {
+ 'nvim-treesitter/nvim-treesitter',
+ requires = {
+ 'nvim-treesitter/nvim-treesitter-textobjects'
+ },
+ run=function()
+ require('nvim-treesitter.install').update({ with_sync = true })
+ end,
+ config=function()
+
+ -- Add support for our Ada parser
+
+ local parsers = require "nvim-treesitter.parsers"
+ local parser_config = parsers.get_parser_configs()
+ parser_config.ada = {
+ install_info = {
+ url = "https://github.com/briot/tree-sitter-ada",
+ files = {"src/parser.c"},
+ generate_requires_npm = false,
+ requires_generate_from_grammar = false,
+ },
+ filetype = "ada",
+ }
+ end,
+}
+```
+
+Finally, we need to install the Ada parser with:
+```vim
+ :PackerSync " to install treesitter itself
+ :TSInstall ada " to install Ada support
+```
+
+However, the above part only installs the parser itself (to generate a syntax
+tree from your source files). We now need to install queries, i.e. pattern
+matching against that tree to provide various capabilities like syntax
+highlighting, folding, indentation, smart textobject selection,...
+
+For this, and until we can merge with nvim-treesitter itself, you will have
+to clone this github repository, then copy the `queries/` directory to
+```
+ ~/.local/share/nvim/site/pack/packer/start/nvim-treesitter/queries/
+```
+
+## Usage
+
+### Syntax highlighting
+
+The above default configuration will replace the default regular
+expressions-based syntax highlighting in vim. Instead, the highlighting is
+based on the tree build every time you type something.
+
+The default highlighting looks pretty much like the one from the standard
+Ada mode. However, the tree-based approach potentially opens the door for
+smart highlighting, like "Use a different background color for a subprogram
+specification", "show constant definitions in blue" or other high-level
+approaches.
+
+ WIP: document how users can do this in their own configuration files.
+ The current approach is to modify queries/highlights.scm
+
+Potentially (though it seems to be disabled in neovim at the moment), the
+highlighting can also get smarter. Going back to the "show constants in
+blue" example above, the queries/locals.scm file adds a simple approach so
+that references to those constants can point to the definition, and therefore
+use the same blue highlighting.
+
+Because neovim also has support for language servers (LSP), it is likely
+better to rely on the language server here.
+
+### Block folding
+
+If you press za now, this will toggle the folding of the
+"current block".
+This is defined in queries/folds.scm, and currently knows about package
+specifications, package bodies, subprograms bodies, if statements and loops.
+Other semantic blocks could be added.
+
+### Smart Selection
+
+The file queries/textobjects.scm defines a function textobjects, so that
+you can now use commands like
+
+ - vaf (v)isually select (a) (f)unction or subprogram
+ - vif (v)isually select (i)nside a (f)unction or subprogram
+ - vai (v)isually select (a) (i)f statement (or loop)
+ - vii (v)isually select (i)nside an (i)f statement (or loop)
+
+
+## Development
+
+Execute the following commands:
+```bash
npm install
npm run test
```
diff --git a/grammar.js b/grammar.js
index 42208b1..fe0e1f0 100644
--- a/grammar.js
+++ b/grammar.js
@@ -360,7 +360,7 @@ module.exports = grammar({
package_body: $ => seq(
reservedWord('package'),
reservedWord('body'),
- $.name,
+ field('name', $.name),
optional($.aspect_specification),
reservedWord('is'),
optional($.non_empty_declarative_part),
diff --git a/package.json b/package.json
index b5f5e53..f60310d 100644
--- a/package.json
+++ b/package.json
@@ -12,5 +12,16 @@
"testquick": "time tree-sitter test",
"update-test": "tree-sitter test --update"
},
- "main": "bindings/node"
+ "main": "bindings/node",
+ "tree-sitter": [
+ {
+ "scope": "source.ada",
+ "file-types": [
+ "ada"
+ ],
+ "highlights": [
+ "queries/highlights.scm"
+ ]
+ }
+ ]
}
diff --git a/queries/folds.scm b/queries/folds.scm
new file mode 100644
index 0000000..8d7e7e9
--- /dev/null
+++ b/queries/folds.scm
@@ -0,0 +1,11 @@
+;; Support for folding in Ada
+;; za toggles folding a package, subprogram, if statement or loop
+
+[
+ (package_specification)
+ (package_body)
+ (subprogram_body)
+ (block_statement)
+ (if_statement)
+ (loop_statement)
+] @fold
diff --git a/queries/highlights.scm b/queries/highlights.scm
new file mode 100644
index 0000000..a03fd66
--- /dev/null
+++ b/queries/highlights.scm
@@ -0,0 +1,147 @@
+;; highlight queries.
+;; See the syntax at https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries
+;; See also https://github.com/nvim-treesitter/nvim-treesitter/blob/master/CONTRIBUTING.md#parser-configurations
+;; for a list of recommended @ tags, though not all of them have matching
+;; highlights in neovim.
+
+[
+ "abort"
+ "abs"
+ "accept"
+ "all"
+ "at"
+ "begin"
+ "declare"
+ "delay"
+ "until"
+ "do"
+ "end"
+ "entry"
+ "exit"
+ "generic"
+ "is"
+ "null"
+ "others"
+ "out"
+ "pragma"
+ "renames"
+ "when"
+] @keyword
+[
+ "abstract"
+ "access"
+ "aliased"
+ "array"
+ "constant"
+ "delta"
+ "digits"
+ "interface"
+ "limited"
+ "of"
+ "private"
+ "range"
+ "synchronized"
+ "tagged"
+] @StorageClass
+[
+ "mod"
+ "new"
+ "protected"
+ "record"
+ "subtype"
+ "task"
+ "type"
+] @type.definition
+[
+ "with"
+ "use"
+] @include
+[
+ "body"
+ "function"
+ "overriding"
+ "procedure"
+ "package"
+ "separate"
+] @keyword.function
+[
+ "and"
+ "in"
+ "not"
+ "or"
+ "xor"
+] @keyword.operator
+[
+ "while"
+ "loop"
+ "for"
+ "parallel"
+ "reverse"
+ "some"
+] @keyword.repeat
+[
+ "return"
+] @keyword.return
+[
+ "case"
+ "if"
+ "else"
+ "then"
+ "elsif"
+ "select"
+] @conditional
+[
+ "exception"
+ "raise"
+] @exception
+(comment) @comment
+(comment) @spell ;; spell-check comments
+(string_literal) @string
+(string_literal) @spell ;; spell-check strings
+(identifier) @variable
+(numeric_literal) @number
+
+;; Highlight the name of subprograms
+(procedure_specification
+ (name) @function
+)
+(function_specification
+ (name) @function
+)
+(package_specification
+ name: (name) @function ;; Should use @module, but no default highlight
+)
+(package_body
+ (name) @function ;; Should use @module, but no default highlight
+)
+(generic_instantiation
+ . (name) @function
+)
+
+;; Change keyword categories inside type definitions.
+;; WIP: waiting for simplified tree.
+ ; [
+ ; "is"
+ ; "abstract"
+ ; "access"
+ ; "array"
+ ; "tagged"
+ ; "constant"
+ ; "range"
+ ; "mod"
+ ; "digits"
+ ; "delta"
+ ; "limited"
+ ; "synchronized"
+ ; ]* @keyword.type
+(full_type_declaration
+ (identifier) @type
+ "is" @type.definition
+ ; (access_type_definition "access" @keyword.type)
+)
+
+;; Highlight errors in red. This is not very useful in practice, as text will
+;; be highlighted as user types, and the error could be elsewhere in the code.
+;; This also requires defining :hi @error guifg=Red for instance.
+(ERROR) @error
+
diff --git a/queries/locals.scm b/queries/locals.scm
new file mode 100644
index 0000000..655e74b
--- /dev/null
+++ b/queries/locals.scm
@@ -0,0 +1,17 @@
+;; Better highlighting by referencing to the definition, for variable
+;; references. However, this is not yet supported by neovim
+;; See https://tree-sitter.github.io/tree-sitter/syntax-highlighting#local-variables
+
+(package_specification) @scope
+(subprogram_specification) @scope
+(block_statement) @scope
+
+(procedure_specification (name) @definition.var)
+(function_specification (name) @definition.var)
+(package_specification name: (name) @definition.var)
+(package_body (name) @definition.var)
+(generic_instantiation . (name) @definition.var)
+(defining_identifier_list (identifier) @definition.var)
+
+(identifier) @reference
+(name) @reference
diff --git a/queries/textobjects.scm b/queries/textobjects.scm
new file mode 100644
index 0000000..4771501
--- /dev/null
+++ b/queries/textobjects.scm
@@ -0,0 +1,19 @@
+;; Support for high-level text objects selections.
+;; For instance:
+;; vaf (v)isually select (a) (f)unction or subprogram
+;; vif (v)isually select (i)nside a (f)unction or subprogram
+;; vai (v)isually select (a) (i)f statement (or loop)
+;; vii (v)isually select (i)nside an (i)f statement (or loop)
+;;
+;; https://github.com/nvim-treesitter/nvim-treesitter-textobjects/blob/master/README.md
+
+(subprogram_body) @function.outer
+(subprogram_body (non_empty_declarative_part) @function.inner)
+(subprogram_body (handled_sequence_of_statements) @function.inner)
+(subprogram_specification) @function.outer
+(package_specification) @function.outer
+(package_body) @function.outer
+(if_statement) @block.outer
+(if_statement (sequence_of_statements) @block.inner)
+(loop_statement) @block.outer
+(loop_statement (sequence_of_statements) @block.inner)
diff --git a/corpus/access.txt b/test/corpus/access.txt
similarity index 100%
rename from corpus/access.txt
rename to test/corpus/access.txt
diff --git a/corpus/arrays.txt b/test/corpus/arrays.txt
similarity index 100%
rename from corpus/arrays.txt
rename to test/corpus/arrays.txt
diff --git a/corpus/attributes.txt b/test/corpus/attributes.txt
similarity index 100%
rename from corpus/attributes.txt
rename to test/corpus/attributes.txt
diff --git a/corpus/generics.txt b/test/corpus/generics.txt
similarity index 100%
rename from corpus/generics.txt
rename to test/corpus/generics.txt
diff --git a/corpus/packages.txt b/test/corpus/packages.txt
similarity index 100%
rename from corpus/packages.txt
rename to test/corpus/packages.txt
diff --git a/corpus/protected.txt b/test/corpus/protected.txt
similarity index 100%
rename from corpus/protected.txt
rename to test/corpus/protected.txt
diff --git a/corpus/records.txt b/test/corpus/records.txt
similarity index 100%
rename from corpus/records.txt
rename to test/corpus/records.txt
diff --git a/corpus/renames.txt b/test/corpus/renames.txt
similarity index 100%
rename from corpus/renames.txt
rename to test/corpus/renames.txt
diff --git a/corpus/separates.txt b/test/corpus/separates.txt
similarity index 100%
rename from corpus/separates.txt
rename to test/corpus/separates.txt
diff --git a/corpus/statements.txt b/test/corpus/statements.txt
similarity index 100%
rename from corpus/statements.txt
rename to test/corpus/statements.txt
diff --git a/corpus/subprograms.txt b/test/corpus/subprograms.txt
similarity index 100%
rename from corpus/subprograms.txt
rename to test/corpus/subprograms.txt
diff --git a/corpus/tasking.txt b/test/corpus/tasking.txt
similarity index 100%
rename from corpus/tasking.txt
rename to test/corpus/tasking.txt
diff --git a/corpus/types.txt b/test/corpus/types.txt
similarity index 100%
rename from corpus/types.txt
rename to test/corpus/types.txt