A tree-sitter parser genreator for the Polar language.
Install the tree-sitter and formatting CLIs
cargo install --locked tree-sitter-cli
cargo install --locked topiary-cliAnd entr (needed for development watcher scripts).
- Pick a Polar policy you want to validate against
- Start the watcher:
./watchparse.sh <path/to/policy.polar>- Any additional positional args will be passed through to
tree-sitter parse.
- Any additional positional args will be passed through to
- Edit
grammar.js. The output from thewatchparse.shsession will update when either the policy or grammar files are updated.
Additional tree exploration can take place in the playground:
tree-sitter build --wasm && \
tree-sitter playground --grammar-path .To avoid negative interactions with existing Neovim plugins, it's recommended
that you use a fresh config for development. This can be accomplished through
the use of an APPNAME.
# Linux
mkdir -p ~/.config/nvim-polar/queries/polar/
touch ~/.config/nvim-polar/init.lua
ln -s /path/to/tree-sitter-polar/queries/highlights.scm ~/.config/nvim-polar/queries/polar/Then, update the newly-created init.lua with a plugin manager and tree-sitter
config. Note that you'll need to update the parser URL to point to this
repository on your system
`init.lua`
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
-- Setup lazy.nvim
require("lazy").setup({
spec = {
{
"scottmckendry/cyberdream.nvim",
lazy = false,
priority = 1000,
opts = {
italic_comments = true,
},
},
{
"nvim-treesitter/nvim-treesitter",
build = ":TSUpdate",
event = { "BufReadPost", "BufNewFile" },
opts = {
indent = {
enable = false
},
highlight = {
enable = true,
disable = {},
additional_vim_regex_highlighting = false
}
},
config = function(_, opts)
require("nvim-treesitter.configs").setup(opts)
end,
}
},
-- automatically check for plugin updates
checker = { enabled = true },
})
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
parser_config.polar = {
install_info = {
url = "/path/to/tree-sitter-polar", -- local path or git repo
files = {"src/parser.c"},
generate_requires_npm = false, -- if stand-alone parser without npm dependencies
requires_generate_from_grammar = false, -- if folder contains pre-generated src/parser.c
},
filetype = "polar",
}
vim.api.nvim_create_autocmd("BufRead", { pattern = "*.polar", command = "set ft=polar" })
vim.treesitter.language.register("polar", "polar")Then, launch Neovim: NVIM_APPNAME=nvim-polar nvim
Lazy.nvim and the associated plugins should automatically install, but it's generally a safe call to restart nvim for a fresh session.
Once launched, install the Treesitter parser :TSInstall polar.
If you load a Polar file and it isn't being highlighted, you may need to ensure;
- The Treesitter parser is enabled for the buffer:
:TSBufEnable polar - Neovim is treating the Polar file as such:
:set ft=polar
Once everything looks good, you can experiment with queries by writing
S-expressions in the :EditQuery prompt. Placing the cursor over the capture
name in the query buffer should highlight the relevant code segments in the
Polar buffer.
Once you're happy with the state of your query in the editor, you can copy it
back to queries/highlights.scm, and then restart Neovim to observe and refine
your changes.
Assuming tree-sitter is already configured on your system, create the topiary config:
mkdir -p ~/.config/topiary/queries/
ln -s /path/to/tree-sitter-polar/queries/formatter.scm ~/.config/topiary/queries/polar.scmexport TOPIARY_LANGUAGE_DIR=~/.config/topiary/queriesin a shell.- Pick a Polar policy you want to validate against
- Start the watcher:
./watchformat.sh <path/to/policy.polar>in the same shellTOPIARY_LANGUAGE_DIRis set.- Any additional positional args will be passed through to
topiary format.
- Any additional positional args will be passed through to
- Edit
formatter.scm. The output from thewatchformat.shsession will update when either the policy or format query files are updated.
We use ts_query_ls to format and validate tree-sitter queries.
# Lint queries
make lintquery
# Format queries
make formatquery
# Check queries for issues (lints and formats, used by CI)
make checkquery
# Do all of the above in order
make query