This guide explains how to get useful editor support for the T
programming language: opening .t files, getting syntax
highlighting, running code in a REPL, enabling the language server, and
using the bundled tree-sitter grammar where your editor supports it.
If you are new to this, start with your editor’s section below and
copy the commands exactly. Replace /absolute/path/to/tlang
with the full path to your local clone of this repository.
T editor support has two separate pieces. You do not always need both.
| Feature | What it does | Usually needed for |
|---|---|---|
| T editor mode / extension | Teaches the editor that .t files are T files. Usually
provides basic highlighting, commands, and keybindings. |
VS Code, Positron, Vim, Neovim, Emacs |
T language server (t-lsp) |
Provides editor features such as completion, diagnostics, hover help, and go to definition. | VS Code, Positron, Vim/Neovim LSP, Emacs eglot |
| Tree-sitter grammar | Provides modern parser-based syntax highlighting and syntax-aware editor features when the editor supports local tree-sitter grammars. | Neovim, Emacs 29+, Helix, Zed, and some advanced Vim/VS Code setups |
[!TIP] If you only want to write and run T scripts, install the normal editor extension/mode first. Add tree-sitter only if your editor supports it or if you specifically want tree-sitter highlighting.
The T language server provides advanced features like Autocompletion (context-aware suggestions), Diagnostics (real-time error checking), Hover Information (tooltips showing signatures/docs), and Go to Definition.
The t-lsp server is implemented in OCaml. When you enter
a T project via nix develop, the correctly versioned binary
is put in your PATH.
[!IMPORTANT] Launching the LSP: For your editor to find the
t-lspbinary, you must either launch your editor from within anix developshell, or use a tool like direnv withuse flaketo automatically load the environment.
Check that the language server is visible before debugging editor configuration:
nix develop
which t-lspIf which t-lsp prints nothing, your editor will not be
able to start the T language server either.
T ships a reusable tree-sitter grammar in
editors/tree-sitter-t. Only the source grammar, queries,
metadata, and grammar tests are committed. Generated parser sources are
expected to be created locally when needed.
npx existsThe commands below use npx. npx comes with
Node.js/npm, so install Node.js first if your shell says
npx: command not found.
The simplest one-off Nix command is:
nix-shell -p nodejsThat opens a temporary shell with node,
npm, and npx available. Confirm it worked:
node --version
npm --version
npx --versionYou can also use any normal Node.js installation method for your system. Nix is recommended because it avoids system-wide changes.
Run these commands from your T repository clone:
cd /absolute/path/to/tlang/editors/tree-sitter-t
npx tree-sitter-cli generate
npx tree-sitter-cli testWhen prompted by npx to install
tree-sitter-cli, answer y.
This creates these generated files locally:
src/parser.csrc/grammar.jsonsrc/node-types.jsonsrc/tree_sitter/Those files are ignored by Git and should not be committed.
Each editor has a slightly different way to consume a local tree-sitter grammar:
editors/tree-sitter-t and reuse the query files in
editors/tree-sitter-t/queries/.nvim-treesitter with
editors/tree-sitter-t, then run
:TSInstallFromGrammar t.editors/vim/. Tree-sitter requires an extra Vim tree-sitter
plugin; if you use one, point it at the same grammar directory.treesit-language-source-alist, then run
M-x treesit-install-language-grammar.If tree-sitter setup fails, first verify that
src/parser.c exists:
ls /absolute/path/to/tlang/editors/tree-sitter-t/src/parser.cVS Code and Positron use the same extension format, so these instructions apply to both.
The T VS Code extension gives you:
.t file recognitiont-lspYou do not need to build the tree-sitter grammar for
the normal VS Code/Positron extension. The extension uses VS Code’s
standard grammar system and talks to t-lsp for language
features.
.vsix file (recommended)Download the latest release: t-lang-0.51.0.vsix
(or download from the repository assets).
Install the extension from the command line:
code --install-extension /path/to/downloaded/t-lang-0.51.0.vsixIn Positron, use the equivalent positron command if it
is available:
positron --install-extension /path/to/downloaded/t-lang-0.51.0.vsixIf the command-line launcher is not available, open the editor, go to
the Extensions view, click the ... menu, and choose
Install from VSIX….
If you have already cloned the T repository locally:
cd /absolute/path/to/tlang
code --install-extension editors/vscode/t-lang-0.51.0.vsixFor Positron, replace code with positron if
that command exists:
cd /absolute/path/to/tlang
positron --install-extension editors/vscode/t-lang-0.51.0.vsixThe most common beginner mistake is launching the editor from a
normal desktop shortcut. That often means the editor cannot find
t-lsp.
Do this instead:
cd /absolute/path/to/your-t-project
nix develop
code .For Positron:
cd /absolute/path/to/your-t-project
nix develop
positron .Once the editor opens, open a .t file. Recommended entry
points are:
src/pipeline.tsrc/main.t.t extension so the editor knows to
activate T support.The built-in T extension does not require tree-sitter. If you have installed a separate VS Code tree-sitter extension and it asks for a grammar path, use:
/absolute/path/to/tlang/editors/tree-sitter-t
Use these query files if the extension asks for them:
/absolute/path/to/tlang/editors/tree-sitter-t/queries/highlights.scm
/absolute/path/to/tlang/editors/tree-sitter-t/queries/injections.scm
/absolute/path/to/tlang/editors/tree-sitter-t/queries/locals.scm
Because third-party tree-sitter extensions differ, the exact setting names depend on the extension. If you are unsure, skip this step; the official VS Code/Positron extension is the beginner-friendly path.
Vim and Neovim can use either the classic Vim support files or
tree-sitter. Beginners should install the classic support files first.
Neovim users can then add tree-sitter highlighting with
nvim-treesitter.
Run these commands from the T repository root:
cd /absolute/path/to/tlang
# Detect .t files
mkdir -p ~/.vim/ftdetect
cp editors/vim/ftdetect/t.vim ~/.vim/ftdetect/t.vim
# Syntax rules
mkdir -p ~/.vim/syntax
cp editors/vim/syntax/t.vim ~/.vim/syntax/t.vim
# Filetype plugin: REPL command, send-line/send-region mappings, completion
mkdir -p ~/.vim/ftplugin
cp editors/vim/ftplugin/t.vim ~/.vim/ftplugin/t.vimOpen a T file:
vim example.tInside Vim, verify the filetype:
:set filetype?
It should print:
filetype=t
With editors/vim/ftplugin/t.vim installed, these
commands and mappings are available in .t buffers:
| Action | Vim command or key |
|---|---|
| Start a T REPL terminal | :TRepl |
| Send the current line to the REPL | <leader>r in normal mode |
| Send the selected lines to the REPL | <leader>r in visual mode |
| Send the whole buffer to the REPL | <leader>b in normal mode |
| Trigger omni-completion | Ctrl-x Ctrl-o |
Your <leader> key is usually \ unless
you changed it in your Vim configuration.
The LSP setup requires t-lsp to be in your
PATH. Start Vim/Neovim from nix develop, or
configure your plugin manager to inherit the Nix environment.
coc.nvimOpen :CocConfig and add:
{
"languageserver": {
"tlang": {
"command": "t-lsp",
"filetypes": ["t"],
"rootPatterns": ["tproject.toml", ".git"]
}
}
}Then restart Vim and open a .t file.
nvim-lspconfigAdd this to your init.lua:
local lspconfig = require('lspconfig')
local configs = require('lspconfig.configs')
if not configs.tlang then
configs.tlang = {
default_config = {
cmd = { "t-lsp" },
filetypes = {'t'},
root_dir = lspconfig.util.root_pattern('tproject.toml', '.git'),
settings = {},
}
}
end
lspconfig.tlang.setup{}Start Neovim from a T project shell:
cd /absolute/path/to/your-t-project
nix develop
nvim src/pipeline.tInstall and enable nvim-treesitter using your normal
Neovim plugin manager. Then add this to your init.lua after
loading nvim-treesitter:
local parser_config = require('nvim-treesitter.parsers').get_parser_configs()
parser_config.t = {
install_info = {
url = "/absolute/path/to/tlang/editors/tree-sitter-t",
files = { "src/parser.c" },
generate_requires_npm = true,
requires_generate_from_grammar = true,
},
filetype = "t",
}
vim.treesitter.language.register("t", "t")Then run this inside Neovim:
:TSInstallFromGrammar t
Open a .t file and run:
:InspectTree
If a syntax tree opens, tree-sitter is working. If
:TSInstallFromGrammar t fails because it cannot run
npx, leave Neovim, start a shell with Node.js, and try
again:
nix-shell -p nodejs
cd /absolute/path/to/tlang/editors/tree-sitter-t
npx tree-sitter-cli generateThen reopen Neovim and run :TSInstallFromGrammar t
again.
Classic Vim does not include tree-sitter by default. If you use a Vim tree-sitter plugin, configure it with:
Grammar directory: /absolute/path/to/tlang/editors/tree-sitter-t
Parser source: /absolute/path/to/tlang/editors/tree-sitter-t/src/parser.c
Queries: /absolute/path/to/tlang/editors/tree-sitter-t/queries/
Filetype: t
File extension: .t
Plugin setting names vary, so use the plugin’s documentation for the exact syntax.
Emacs support has two layers:
t-mode, the normal major mode for .t
files.treesit.Install t-mode first. Add tree-sitter afterwards if your
Emacs version supports it.
t-modeAdd the editors/emacs/ directory to your
load-path in init.el:
(add-to-list 'load-path "/absolute/path/to/tlang/editors/emacs")
(require 't-mode)
Open a .t file. Emacs should use t-mode
automatically. To check, run:
M-x describe-mode
You should see T or t-mode in the mode
description.
t-mode provides these commands and keybindings:
| Action | Command | Keybinding |
|---|---|---|
| Start or switch to a T REPL | M-x run-t |
C-c C-z |
| Send the whole buffer | M-x t-send-buffer |
C-c C-c |
| Send selected region | M-x t-send-region |
C-c C-r |
| Send current line | M-x t-send-line |
C-c C-l |
If Emacs cannot find the t executable, start Emacs from
a T/Nix shell:
cd /absolute/path/to/your-t-project
nix develop
emacs .Add the following to your init.el:
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(t-mode . ("t-lsp"))))
;; Automatically start eglot when opening a .t file
(add-hook 't-mode-hook 'eglot-ensure)
Again, t-lsp must be visible in Emacs’ environment. If
LSP does not start, run Emacs from nix develop.
Emacs 29 introduced built-in tree-sitter support through
treesit. Add this to your init.el:
(when (treesit-available-p)
(add-to-list 'treesit-language-source-alist
'(t "/absolute/path/to/tlang/editors/tree-sitter-t")))
Then restart Emacs and install the grammar:
M-x treesit-install-language-grammar RET t RET
If Emacs cannot build the grammar because npx or Node.js
is missing, install Node.js first:
nix-shell -p nodejsThen regenerate the parser manually:
cd /absolute/path/to/tlang/editors/tree-sitter-t
npx tree-sitter-cli generateFinally, restart Emacs and retry:
M-x treesit-install-language-grammar RET t RET
This makes the T parser available to treesit-aware
packages and any custom t-ts-mode built on top of the
bundled grammar. The bundled t-mode remains the safe
default if you do not have a separate tree-sitter-based major mode
installed.
For literate programming with executable {t} chunks, add
Quarto to your T project tools in tproject.toml:
[additional-tools]
packages = ["quarto"]Then run t update and enter the project with
nix develop. T will provision
_extensions/tlang automatically. Enable the
tlang filter in your document front matter:
---
filters:
- tlang
---The same parser package can also be reused by editors that consume local tree-sitter grammars, including:
Point those editors at editors/tree-sitter-t and reuse
the bundled query files from queries/.
For any editor, the important paths are:
Grammar: /absolute/path/to/tlang/editors/tree-sitter-t
Queries: /absolute/path/to/tlang/editors/tree-sitter-t/queries
Parser: /absolute/path/to/tlang/editors/tree-sitter-t/src/parser.c
npx: command not foundInstall Node.js, then try again:
nix-shell -p nodejs
npx --versiontree-sitter: command not foundUse npx tree-sitter-cli ... instead of
tree-sitter ..., or install the CLI globally:
npm install --global tree-sitter-clit-lspStart the editor from inside nix develop:
cd /absolute/path/to/your-t-project
nix develop
code . # VS Code
positron . # Positron
nvim . # Neovim
emacs . # EmacsYou can also check from the same shell:
which t-lsp.t files are not
highlightedCheck that the editor knows the filetype/language is T:
T or
tlang. If not, click it and choose T.:set filetype?. It
should say filetype=t.M-x describe-mode. It
should show t-mode.Check the generated parser exists:
ls /absolute/path/to/tlang/editors/tree-sitter-t/src/parser.cIf it does not exist, regenerate it:
cd /absolute/path/to/tlang/editors/tree-sitter-t
npx tree-sitter-cli generateIf you are developing T itself, you can rebuild the LSP server with:
nix build .#defaultThe binary will be located at result/bin/t-lsp.