Skip to content

🌳 Tree-sitter grammar for the ⚑ Tact contract programming language

License

Notifications You must be signed in to change notification settings

tact-lang/tree-sitter-tact

Repository files navigation

tree-sitter-tact

Tree-sitter + Tact = tree-sitter-tact

A fully-featured 🌳 Tree-sitter grammar for the ⚑ Tact contract programming language:

  • 🍰 Parses whole Tact grammar as defined in grammar.ohm (with performance and usability in mind).
  • 🎨 Provides highlighting, scoping and tagging queries.
  • βš™ Test-covered (including queries), reflects latest Tact language updates.
  • πŸš€ See guidelines on usage and integration in editors supporting Tree-sitter below.

Note, that the only limiting point are the asm functions introduced in Tact 1.5.0 β€” their bodies doesn't produce any highlighting and can be ill-parsed for now, so expect ERROR nodes in the parse tree. In the future, this is planned to be resolved by an external scanner β€” it can parse much more, and it can yield more tokens for subsequent highlighting.

πŸš€ Usage

Neovim

Installation assumes you're using lazy.nvim as a plugin manager:

Instructions
  1. Clone the repo to any convenient place: git clone https://github.com/tact-lang/tree-sitter-tact ~/.local/git/tree-sitter-tact (~/.local/git is exemplary, you may choose another directory)

  2. Add the following (partly or as a whole) to your ~/.config/nvim/init.lua (Or ~\AppData\Local\nvim\init.lua on Windows):

For the general Tree-sitter support:

-- lazy.nvim package manager
require('lazy').setup({
  -- ...
	{
    -- Highlight, edit, and navigate code
    'nvim-treesitter/nvim-treesitter',
    build = ':TSUpdate',

    -- Optional, may be removed:
    dependencies = {
      -- adds syntax aware text-objects, select, move, swap, and peek support
      -- see: https://github.com/nvim-treesitter/nvim-treesitter-textobjects
      'nvim-treesitter/nvim-treesitter-textobjects',

      -- adds a sticky context header on top as you scroll through file contents
      -- see: https://github.com/nvim-treesitter/nvim-treesitter-context
      'nvim-treesitter/nvim-treesitter-context'
    },
  },
  -- ...
}, {})

For the tree-sitter-tact support:

local parser_config = require "nvim-treesitter.parsers".get_parser_configs()

-- Adds tree-sitter-tact support
parser_config.tact = {
  install_info = {
    url = "~/.local/git/tree-sitter-tact", -- a path to the cloned repo
    files = {"src/parser.c"},
    branch = "main",
    generate_requires_npm = false,
    requires_generate_from_grammar = false,
  }
}

-- Adds filetype recognition for .tact files
vim.filetype.add({
  extension = {
    tact = "tact",
  }
})
  1. Create a folder for queries under your Neovim runtime directory, if not exists:
  • Windows: mkdir -p ~\AppData\Local\nvim\queries
  • Linux, macOS, *NIX: mkdir -p ~/.config/nvim/queries
  1. Symlink the editor_queries/neovim sub-directory, this will add all the queries:
  • Windows: mklink /D ~\AppData\Local\nvim\queries\tact ~\.local\git\tree-sitter-tact\editor_queries\neovim
  • Linux, macOS, *NIX: ln -s ~/.local/git/tree-sitter-tact/editor_queries/neovim ~/.config/nvim/queries/tact
  1. Finally, run the :TSInstall tact inside the Neovim.

  2. For further configuration and customization, refer to the following repositories:

Queries bundled (see editor_queries/neovim):

  • highlights.scm β€” syntax highlighting
  • locals.scm β€” used to extract keyword definitions, scopes, references, etc., but NOT used for highlighting (unlike Generic or Helix queries)
  • injections.scm β€” highlighting of TODO, FIXME and related in single-line comments
  • folds.scm β€” syntax folds (note, that folding has to be enabled in config in order to use those)
  • indents.scm β€” indentation levels
  • textobjects.scm β€” syntax aware text-objects, select, move, swap, and peek support.
  • context.scm β€” shows sticky context on top of the editor as you scroll through file contents

Helix

πŸš€ Helix version 24.03 comes bundled with tree-sitter-tact for Tact 1.2.0.

If you want to always have the latest parser and queries available (which target branches master of Helix and main of Tact), do the following:

Instructions
  1. Clone the repo to any convenient place: git clone https://github.com/tact-lang/tree-sitter-tact ~/.local/git/tree-sitter-tact (~/.local/git is exemplary, you may choose another directory)

  2. Create a folder for queries under your Helix runtime directory, if not exists:

  • Windows: mkdir -p ~\AppData\Roaming\helix\runtime\queries
  • Linux, macOS, *NIX: mkdir -p ~/.config/helix/runtime/queries
  1. Symlink the editor_queries/helix sub-directory, this will add all the queries:
  • Windows: mklink /D ~\AppData\Roaming\helix\runtime\queries\tact ~\.local\git\tree-sitter-tact\editor_queries\helix
  • Linux, macOS, *NIX: ln -s ~/.local/git/tree-sitter-tact/editor_queries/helix ~/.config/helix/runtime/queries/tact
  1. Add the following to your ~/.config/helix/languages.toml (Or ~\AppData\Roaming\helix\languages.toml on Windows):
[[language]]
name = "tact"
scope = "source.tact"
injection-regex = "tact"
file-types = ["tact"]
comment-token = "//"
block-comment-tokens = [{ start = "/*", end = "*/"}]
indent = { tab-width = 4, unit = "    " }

[language.auto-pairs]
'"' = '"'
'{' = '}'
'(' = ')'
'<' = '>'

[[grammar]]
name = "tact"
source = { path = "/absolute/path/to/your/home/directory/.local/git/tree-sitter-tact" }  # TODO: replace with your full path to downloaded repo
  1. Finally, run the following commands to update all Tree-sitter grammars, including Tact's:
hx --grammar fetch
hx --grammar build

Queries bundled (see editor_queries/helix):

  • highlights.scm β€” syntax highlighting
  • injections.scm β€” highlighting of TODO, FIXME and related in single-line comments
  • indents.scm β€” indentation levels
  • textobjects.scm β€” syntax aware text-objects

πŸ’² CLI Usage

Tree-sitter grammars have limited utility on its own and are best used as parsers that can be embedded in other projects. However, tree-sitter-cli can be used with this grammar to show generated parse trees and syntax highlighting for a given Tact file.

For a quick demo of tree-sitter-cli usage:

  1. Clone this repo.
  2. Install Node.js dependencies (by npm ci (preferred, to re-use package-lock.json), pnpm i, bun i or yarn).
  3. Execute relevant commands from the scripts tag in package.json.

For a more streamlined experience, you may:

  1. Install tree-sitter-cli.
  2. Create a tree-sitters directory in your home directory.
  3. Clone this repository (or symlink it) into the new ~/tree-sitters/ directory.
  4. Run tree-sitter parse path/to/file.tact to be shown the parse tree for the file.
  5. Run tree-sitter highlight path/to/file.tact to be shown the file with syntax highlighting applied.

🎨 Structure

Grammar definition resides in grammar.js:

  • Actual grammar and bindings are generated from it via Tree-sitter.
  • Queries and tests rely on its namings of nodes and fields.

Generic queries are structured as follows:

queries/
|-- highlights.scm -- syntax highlighting queries (generic, for Tree-sitter & GitHub)
|-- locals.scm -- fixed set of capture names to track local scopes and variables (and alike)
`-- tags.scm -- tagging queries for code navigation systems (as used on GitHub)

To find highlighting and other queries for specific editors, look in the editor_queries/ directory. There, all the queries target development upstream branches of the relevant editors, unless the directory has a suffix -release/, in such case the queries provided there are targeting the latest releases.

βš™ References

Useful ⚑ Tact links

Credits

Based on The Open Network.

Built with 🀍 by Novus Nota.

License

MIT