highlight

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 21, 2025 License: Apache-2.0 Imports: 12 Imported by: 2

README

go-tree-sitter-highlight

This highlighter is based on the Rust tree-sitter-highlight crate. It provides a simple way to highlight text via tree-sitter, using the go-tree-sitter module.

This is a fork of https://github.com/gopad-dev/go-tree-sitter-highlight.

Usage

Add the package as a dependency:

go get -u tangled.sh/zerolimits.dev/go-tree-sitter-highlight

Then you can use it in your code:

package main

import (
	"os"
	"fmt"

	tsh "tangled.sh/zerolimits.dev/go-tree-sitter-highlight"
	tsh_types "tangled.sh/zerolimits.dev/go-tree-sitter-highlight/types"

	tree_sitter_go "github.com/tree-sitter/tree-sitter-go/bindings/go"
)

func getLang(langName string) tsh.Language {
	// Here you would have a switch statement to select the language based on `langName`.

	highlights, _ := os.ReadFile("path/to/highlights.scm")
	injections, _ := os.ReadFile("path/to/injections.scm")
	locals, _ := os.ReadFile("path/to/locals.scm")

	language := tsh.NewLanguage(langName, tree_sitter_go.Language(), highlights, injections, locals)
	return language
}

func main() {
	code := `
package main

import "fmt"

func fib(n int) int {
	a := 0
	b := 1
	for range n {
		a, b = b, a+b
	}
	return a
}

func main() {
	fmt.Println(fib(10))
}
`

	language := getLang("go")

	// The node names you want to match. These can be anything, and each language
	// has its own set of queries that you can look at for relevant names.
	highlightNames := []string{"function", "variable", "keyword", "constant"}
	config, _ := tsh.NewConfiguration(language, highlightNames)

	// This function runs when tree-sitter encounters an injection. This is when
	// another language is embedded into one currently being parsed. For example,
	// CSS and JS can be embedded into HTML. If you were parsing HTML, this
	// function would run when it encountered CSS or JS, provided it was included
	// in `injections.scm`. Simply return a new configuration from inside the
	// function for the new language.
	var injectionCallback tsh_types.InjectionCallback = func(languageName string) *tsh_types.Configuration {
		language := getLang(languageName)
		config, _ := tsh.NewConfiguration(language, highlightNames)
		return config
	}

	// This runs for every single output `<span>` element, and is used to add
	// attributes to the element. You can use this to add class names, inline
	// styles based on a theme, or whatever else you'd like. For example, if you
	// return `class="ts-highlight"` from inside the function, every `<span>`
	// element in your output will look like `<span class="ts-highlight">`.
	var attributeCallback tsh_types.AttributeCallback = func(h uint, languageName string) string {
		className := highlightNames[h]
		return fmt.Sprintf(`class="%s"`, className)
	}
	highlightedText, _ := tsh.Highlight(*config, code, injectionCallback, attributeCallback)

	fmt.Println(highlightedText) // <span class="..."> ... </span>
}

The errors have been omitted for brevity, but should be handled properly when using the library.

Built-in languages

There are a number of languages built-in, which you can get using languages.Get():

package main

import (
	"tangled.sh/zerolimits.dev/go-tree-sitter-highlight/languages"
)

func main() {
	lang := languages.Get("go") // tsh.Language

	// ...
	// see above example for usage
}

If there are any languages you need that aren't built in, you can either contribute them, or manually add them in your project using the NewLanguage() function as shown above.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Highlight

func Highlight(cfg types.Configuration, source string, injectionCallback types.InjectionCallback, attributeCallback types.AttributeCallback) (string, error)

Highlight highlights the given source code using the given configuration. The source code is expected to be UTF-8 encoded. The function returns the highlighted HTML or an error.

cfg := tsh.NewConfiguration(...)
source := "..."
injectionCallback := func(languageName string) *Configuration { ... }
attributeCallback := func(h uint, languageName string) string { ... }

highlighted, err := tsh.Highlight(cfg, source, injectionCallback, attributeCallback)

func NewConfiguration

func NewConfiguration(lang Language, recognisedNames []string) (*types.Configuration, error)

NewConfiguration creates a new highlight configuration from a Language and a list of recognised names.

lang := tsh.NewLanguage(...)
recognisedNames := []string{"function", "variable", "keyword", ...}
cfg, err := tsh.NewConfiguration(lang, recognisedNames)

Types

type Language

type Language struct {
	Name            string
	HighlightsQuery []byte
	InjectionQuery  []byte
	LocalsQuery     []byte
	Lang            *tree_sitter.Language
}

A language object. This collects all the fields used in this library into a single struct for easier usage and cleaner code. This includes the Name, the HighlightsQuery, InjectionQuery and LocalsQuery, and the tree_sitter.Language in Lang.

func NewLanguage

func NewLanguage(name string, ptr unsafe.Pointer, highlightsQuery, injectionQuery, localsQuery []byte) Language

This function is used to create a new Language. highlightsQuery, injectionQuery, and localsQuery can all be nil, though highlightsQuery being nil wouldn't serve much purpose in a syntax highlighter.

highlightsQuery := []byte("...")
injectionQuery := []byte("...")
localsQuery := []byte("...")
lang := tsh.NewLanguage("go", tree_sitter_go.Language(), highlightsQuery, injectionQuery, localsQuery)

Source Files

  • config.go
  • highlight.go
  • language.go

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL