Skip to content

nutt-y/seams

Repository files navigation

Seams 🪡

Demo A GameMaker Studio language server made in Typescript, utilizing Butterscotch Shenanigan's gml-parser for parsing a GML project.

Note

This project is still a work in progress, certain functionality might break!

Supported LSP methods

Method
textDocument/didOpen
textDocument/didChange
textDocument/didSave
textDocument/completion
textDocument/definition
textDocument/references
textDocument/hover
textDocument/signatureHelp
textDocument/inlayHint
textDocument/semanticTokens/full
textDocument/documentHighlight
🚧 textDocument/codeAction

Installation

You can download the binary for your current system under Releases. This server uses standard i/o to communicate with a client. Below is an example on how to set up this LSP.

Neovim

-- Register GML file type
vim.filetype.add({
 extension = {
  gml = "gml",
 },
})

vim.lsp.config("gml", {
    cmd = {"./seams"},
    filetypes = {"gml"}
    root_markers = {"project.yyp"} -- This should be the specific to your project
})

Contributing

If you find any bugs or issues, you are more than welcome to open a pull request or leave an issue ticket and I'll check it out!

Setup

Install deno version 2.7.*. Run deno run build to compile the binary locally for your machine's specifications. This project uses Deno's in-built type checker.

Linting and Formatting

Biome is used for linting and formatting the project. Consult biome.json for the rules and overrides.

Project Structure

src/server/methods/
├── message.ts              # Main entry point - routes LSP requests to handlers
│
├── abstract.ts             # Base class for all handlers
│   └── AbstractHandler     # Provides: message, project, logger, responses, getFile()
│
├── message.types.ts        # LSP Types
│
└── <other files>.ts      # LSP methods that have been implemented in the project so far

Adding a New Handler

To add a new LSP method handler:

  1. Create a new file in src/server/methods/ (e.g., textDocument_*.ts)
  2. Extend AbstractHandler and implement the handle() method
  3. Add the method name to the Methods enum in message.ts
  4. Add the handler class to the HANDLERS map in message.ts

Neovim Setup Recommendation

I use Neovim as my personal text editor with lazy.nvim as my plugin manager. Here's a small snippet of the .lazy.lua file I have been using when editing this project.

-- Register GML file type
vim.filetype.add({
 extension = {
  gml = "gml",
 },
})

local dir = vim.fn.getcwd()
local path = vim.fn.expand(dir)

vim.lsp.set_log_level(vim.log.levels.TRACE)

return {
 {
  "neovim/nvim-lspconfig",
  opts = {
   ---@module "nutt.plugins.code.nvim-lspconfig"
   ---@type table<string, LspServerConfig>
   servers = {
    gml = {
     cmd = { path .. "/seams" },
     filetypes = { "gml" },
     root_markers = { "a.yyp", ".git" }, -- Set the root marker to wherever you want to test the LSP in
    },
    biome = {
     cmd = { "deno", "run", "-A", "npm:@biomejs/biome", "lsp-proxy" },
    },
   },
  },
 },
 {
  "stevearc/conform.nvim",
  ---@module "conform"
  ---@type conform.setupOpts
  opts = {
   formatters_by_ft = {
    typescript = { "biome", lsp_format = "fallback" },
    json = { "biome", lsp_format = "fallback" },
   },
   formatters = {
    biome = {
     command = "deno",
     args = { "run", "-A", "npm:@biomejs/biome", "format", "--stdin-file-path", "$FILENAME" },
    },
   },
  },
 },
}

Acknowledgment

Thank you so much to Butterscotch Shenanigans for doing all the heavy lifting in their Stitch gml-parser package. Without that package, this LSP would not have been possible to implement!