GSX Language Support for VS Code
Syntax highlighting and language support for .gsx files used with the go-tui framework.
Features
-
Syntax Highlighting: Full highlighting support for the GSX DSL
- Component declarations:
templ Name(params) { ... }andtempl (c *Type) Render() { ... } - Keywords:
for,if,else,:= - Element tags:
<div>,<span>,<p>,<button>,<input>,<textarea>,<table>,<progress>, etc. - Ref bindings:
ref={myRef}on elements - Reactive state:
tui.NewState(),.Get(),.Set(),.Update() - Event attributes:
onFocus,onBlur - Attributes with string, number, and expression values
- Go expressions inside
{} - Comments:
//and/* */
- Component declarations:
-
Language Configuration
- Auto-closing brackets and quotes
- Comment toggling
- Code folding
- Smart indentation
-
LSP Support (via
tui lsp)- Real-time diagnostics
- Go-to-definition for components, functions, refs, and state
- Hover documentation for elements, attributes, keywords, and state
- Auto-completion for elements, attributes, Tailwind classes, and Go expressions
- Find references across workspace
- Document and workspace symbols
- Semantic token highlighting
- Code formatting
-
File Nesting: Collapses each generated
*_gsx.gofile under its.gsxsource in the Explorer (opt-in, see below)
Installation
From Source
-
Clone the go-tui repository:
git clone https://github.com/grindlemire/go-tui.git -
Copy the extension to your VS Code extensions folder:
cp -r go-tui/editor/vscode ~/.vscode/extensions/gsx-language -
Reload VS Code
From VSIX (Package)
-
Build the extension:
cd go-tui/editor/vscode npm install npx vsce package -
Install the
.vsixfile:- Open VS Code
- Go to Extensions (Ctrl+Shift+X)
- Click the
...menu and select "Install from VSIX..." - Select the generated
.vsixfile
Usage
Simply open any .gsx file and the syntax highlighting will be applied automatically.
Example
package main
import (
"fmt"
tui "github.com/grindlemire/go-tui"
)
type counter struct {
count *tui.State[int]
incBtn *tui.Ref
decBtn *tui.Ref
}
func Counter() *counter {
return &counter{
count: tui.NewState(0),
incBtn: tui.NewRef(),
decBtn: tui.NewRef(),
}
}
func (c *counter) KeyMap() tui.KeyMap {
return tui.KeyMap{
tui.On(tui.Rune('+'), func(ke tui.KeyEvent) { c.count.Update(func(v int) int { return v + 1 }) }),
tui.On(tui.Rune('-'), func(ke tui.KeyEvent) { c.count.Update(func(v int) int { return v - 1 }) }),
tui.On(tui.Rune('q'), func(ke tui.KeyEvent) { ke.App().Stop() }),
}
}
func (c *counter) HandleMouse(me tui.MouseEvent) bool {
return tui.HandleClicks(me,
tui.Click(c.incBtn, func() { c.count.Update(func(v int) int { return v + 1 }) }),
tui.Click(c.decBtn, func() { c.count.Update(func(v int) int { return v - 1 }) }),
)
}
templ (c *counter) Render() {
<div class="flex-col gap-2 p-2 border-rounded items-center">
<span class="font-bold">{fmt.Sprintf("Count: %d", c.count.Get())}</span>
<div class="flex gap-2">
<button ref={c.decBtn} class="px-1">{"-"}</button>
<button ref={c.incBtn} class="px-1">{"+"}</button>
</div>
<span class="font-dim">+/- or click buttons, q to quit</span>
</div>
}
File Nesting
Each .gsx file generates a sibling *_gsx.go file in the same directory (header.gsx produces header_gsx.go). The extension registers a VS Code file nesting pattern that tucks the generated file under its source, so the Explorer shows one entry per component instead of two.
The pattern ships with the extension, but VS Code's file nesting is off by default. Turn it on once in your settings:
{
"explorer.fileNesting.enabled": true
}
To scope it to a single project, put that line in the project's .vscode/settings.json instead of your user settings. Adding the line there (rather than extension-wide) keeps file nesting from also reorganizing your non-gsx repositories.
Notes:
- This is VS Code only. Other editors have their own nesting mechanisms.
- Source files with hyphens do not nest: the generator rewrites
my-app.gsxtomy_app_gsx.go, which the file nesting glob cannot match. Dot and underscore names nest normally.
Supported Constructs
| Construct | Example |
|---|---|
| Component | templ Name(params) { ... } |
| Method component | templ (c *Type) Render() { ... } |
| For loop | for i, v := range items { ... } |
| If/Else | if condition { ... } else { ... } |
| Let binding | label := <span>text</span> |
| Component call | @ComponentName(args) |
| Element | <div class="flex-col gap-1">children</div> |
| Self-closing element | <hr />, <br />, <input />, <progress /> |
| Ref binding | <button ref={myRef}>text</button> |
| State access | c.count.Get(), c.count.Set(v), c.count.Update(fn) |
| Event attributes | onFocus={handler}, onBlur={handler} |
| Go expression | {fmt.Sprintf(...)} |
| Helper function | func helper(s string) string { ... } |
LSP Configuration
The extension automatically starts the GSX language server when you open a .gsx file. Configure via VS Code settings:
| Setting | Default | Description |
|---|---|---|
gsx.lsp.enabled |
true |
Enable/disable the language server |
gsx.lsp.path |
tui |
Path to the tui binary |
gsx.lsp.logPath |
"" |
Path for LSP log file (empty = no logging) |
If the tui binary is not found, the extension will offer to install it automatically via go install.
Contributing
Contributions are welcome! Please see the go-tui repository for contribution guidelines.
License
MIT License. See the LICENSE file for details.