npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

m68k-lsp-server

v0.13.0

Published

Motorola 68000 assembly language server in node.

Readme

Motorola 68000 family language server

example workflow npm version

Language Server Protocol implementation for Motorola 68000 family assembly, using m68k-parser

Features

  • Auto-completion:
    • Instruction mnemonics
    • Assembler directives
    • Registers
    • Symbols
  • Code Linting
    • Parser errors
    • Processor support
  • Code Folding
  • Document Formatting
  • Document Highlights
  • Document Links
  • Document Symbols
  • Register usage and availability analysis, navigation, swapping and remapping; macro calls are expanded, including macros defined in included files
  • Workspace indexing and assembly-unit-aware symbol lookup
  • Find References
  • Go to definition
  • Call Hierarchy
  • Hover
    • Instruction/directive documentation
    • Symbol info
  • Inlay Hints
    • Evaluated value of constant assignments (equ/fequ/=/set)
  • Multiple workspaces
  • Rename Symbols
  • Signature Help

Requires Node.js 22.15.1 or later. The VS Code extension requires VS Code 1.101 or later.

Installation

Install the package via npm:

npm install --global m68k-lsp-server

Usage

Neovim

Configure using nvim-lspconfig

e.g.

require('lspconfig').m68k.setup{
  on_attach = on_attach,
  init_options = {
    includePaths = { '../include', '/home/myuser/includes' },
    format = {
      case = {
        instruction = 'upper'
      }
    }
  }
}

Emacs

See emacs-m68k

Standalone server

Start the server e.g.:

m68k-lsp-server --stdio

Configuration

The LSP client can configured using the following settings, either as initialization options, or as a .m68krc.json file in your workspace folder or a directory above it, for project specific overrides.

.m68krc.json is also read by the linter and its language server for the options they share: processors, includePaths and caseSensitive. A relative include path is taken from the directory of that file. Other keys are ignored by them.

The assembler is run with the custom vasm.args followed by what these options imply: -I for each include path, -m for each processor and -nocase when caseSensitive is false, each only if the arguments do not already say so. A -nocase or -I among the arguments is likewise read back as the option, so the two forms agree. Setting caseSensitive: true alongside -nocase logs a warning. A relative -I in vasm.args is relative to where vasm is run, the source root (see below), and then to the main source's directory, as vasm tries it; the linter reads it the same way.

A JSON schema for the file is published as m68krc.schema.json in this package, and is bundled with the VS Code extension. In other editors, reference it from the file:

{
  "$schema": "https://cdn.jsdelivr.net/npm/m68k-lsp-server@0/m68krc.schema.json"
}

Processors:

Lists the processor(s) that your code is targeted at. This controls completion suggestions and provides diagnostics.

{
  "processors": ["mc68030", "mc68881"]
}

Default: ["mc68000"]

Supported values: mc68000 ,mc68010 ,mc68020 ,mc68030 ,mc68040 ,mc68060 ,mc68881 ,mc68851 ,cpu32

Include Paths:

Additional paths to use to resolve include directives. This is equivalent to INCDIR in source. It should probably include anything you pass to vasm -I arguments. Can be absolute or relative; in a .m68krc.json, relative paths are taken from that file's directory.

{
  "includePaths": ["../include", "/home/myuser/includes"]
}

Default: []

Source root:

The directory that relative paths in the source, such as include "lib/defs.i", resolve from. It is where vasm is run, so it should be where your build runs it, usually the project root. Relative to the .m68krc.json it is in (or the workspace folder, from editor settings). Unset, each file's own directory is used, which is also where vasm is run. The linter and its language server look here for includes too, after the file's own directory and before the include paths.

{
  "sourceRoot": "."
}

Default: unset

Inferred include paths:

The server works out which includes vasm would not find, from where vasm looks: the directory it is run in, the directory of the main source, the -I paths and incdirs, and not beside the file that names the include. For each it looks for project files that end in the same path. If include "lib/defs.i" would not be found and the project has <dir>/lib/defs.i, vasm is given <dir> as an include path, so the include is found and the rest of the file is checked. If vasm still cannot open an include, for one made by a macro say, it is run again with the same kind of guess. An information diagnostic on the include says so, with quick fixes to add the directory to includePaths or set it as the sourceRoot in .m68krc.json, whichever is meant: to vasm the two are the same. A path that could be resolved more than one way is left alone. Turn it off with inferIncludePaths: false.

{
  "inferIncludePaths": false
}

Default: on

Escape sequences:

Whether the assembler reads backslash escapes in strings (vasm -esc), so dc.b "Hello\n" holds a newline. Without it a backslash is an ordinary character. Leave it unset and an -esc among the vasm args is honoured instead; -esc is added to the arguments when this is true. The linter uses it to size string data and to decide whether to warn about escapes that would not mean what they say.

{
  "escapeSequences": true
}

Default: unset (off unless -esc is in the vasm arguments)

Case Sensitivity:

Whether Foo and foo are different symbols (labels, constants and macros). They are, unless vasm is given -nocase, so this is on by default. Leave it unset and a -nocase among the vasm args is honoured instead; set it to override that either way. Instruction and directive names are always matched without regard to case. Changing it re-reads every document.

{
  "caseSensitive": false
}

Default: unset (case-sensitive unless -nocase is in the vasm arguments)

vasm diagnostics:

The server can use vasm to provide diagnostic messages. When enabled it will assemble source files on save/open and display any errors or warnings.

The server will use a local vasmm68k_mot executable if one exists in your path or is configured in vasm.binPath, otherwise it will default to a bundled version complied in Web Assembly.

{
  "vasm": {
    "provideDiagnostics": true,
    "binPath": "vasmm68k_mot",
    "args": [],
    "preferWasm": false,
    "exclude": []
  }
}

(defaults)

| Property | Description | | -------------------- | --------------------------------------------------------------------------------------------------------------- | | provideDiagnostics | Enable vasm diagnostics | | binPath | Filename or full path of vasm executable binary | | args | Custom arguments to pass to vasm. Include paths and processor(s) from server config will automatically be added | | preferWasm | Always use bundled Web Assembly vasm | | exclude | File patterns to ignore and not build directly e.g. ["*.i"] |

Inlay hints:

Shows the evaluated value of constant assignments (equ, fequ, =, set) inline, when the expression is more than a bare literal.

{
  "inlayHints": {
    "enabled": true
  }
}

Formatting:

Formatting is provided by the m68k-formatter workspace package, which also includes a standalone CLI. Build it with pnpm run build:formatter, then run node packages/m68k-formatter/cli.js --write 'src/**/*.s' or use --check for CI.

Both the CLI and language server read the nearest .m68k-format.json above the source file. This file contains the options below directly, without the format wrapper. File settings override editor configuration; formatting-request options such as tab size and spaces/tabs take precedence.

The language server supports document formatting which can be configured using the following options:

Case

Enforce consistency of upper/lower case on elements which are normally case insensitive.

| Option | Behaviour | | ------- | ------------------ | | upper | Upper case | | lower | Lower case | | any | Do not change case |

This can either be configured globally for all elements:

{
  "format": {
    "case": "lower"
  }
}

or per element type

{
  "format": {
    "case": {
      "instruction": "lower",
      "directive": "lower",
      "control": "upper",
      "sectionType": "lower",
      "register": "lower",
      "hex": "lower"
    }
  }
}

| Element | Description | | ------------- | ----------------------------------------------------- | | instruction | Instruction mnemonic/size e.g. move.w | | directive | Assembler directive mnemonic/qualifier e.g. include | | control | Assembler control keywords e.g. ifeq/endc | | sectionType | Section type e.g. bss | | register | Register name e.g. d0,sr | | hex | Hexadecimal number literal |

Default: "lower"

Label colon

Determines whether labels should have a colon suffix.

Can be set for all labels:

{
  "format": {
    "labelColon": "on"
  }
}

or individually for global and local labels:

{
  "format": {
    "labelColon": {
      "global": "on",
      "local": "off"
    }
  }
}

| Option | Behaviour | | ------------ | ----------------------------------------------------- | | on | Add colon | | off | Remove colon | | notInline | No colon for labels on same line as instruction | | onlyInline | Only add colon for labels on same line as instruction | | any | Do not change |

Default: "on"

Operand space

Include space between operands e.g. move d0, d1. VASM needs -spaces or -phxass option to support this.

| Option | Behaviour | | ------ | ------------- | | on | Add space | | off | Remove space | | any | Do not change |

Default: "off"

{
  "format": {
    "operandSpace": "off"
  }
}

Quotes

Quote style to use for strings and paths.

{
  "format": {
    "quotes": "single"
  }
}

| Option | Behaviour | | -------- | ------------------ | | single | Single quotes: ' | | double | Double quotes: " | | any | Do not change |

Default: "double"

Align

Indents elements to align by type.

{
  "format": {
    "align": {
      "mnemonic": 8,
      "operands": 16,
      "comment": 48,
      "operator": 0,
      "value": 0,
      "indentStyle": "space",
      "tabSize": 8,
      "autoExtend": "line"
    }
  }
}

(defaults)

| Property | Description | | ------------------- | ------------------------------------------------------------------------------------- | | mnemonic | Position of instruction/directive mnemonic and size e.g. move.w,include. | | operands | Position of operands e.g. d0,d1. | | comment | Position of comment following statement. Comments on their own line are not affected. | | operator | Position of = character in constant assignment | | value | Position of value in constant assignment | | standaloneComment | Position / behaviour of comment with no other elements on the same line. | | indentStyle | Character to use for indent - tab or space. | | tabSize | Width of tab character to calculate positions when using tab indent style. | | autoExtend | Behaviour when a component exceeds the available space between positions. See below. |

Block contents can be indented independently with format.align.indentConditional, format.align.indentRept, and format.align.indentMacro. Each is an additional width in columns, defaulting to 0 (disabled). For example:

{
  "format": {
    "align": {
      "indentConditional": 4,
      "indentRept": 4,
      "indentMacro": 4
    }
  }
}

Nested widths add together. Opening, alternative (else/elseif), and closing directives align at the enclosing level. Mnemonics, operands, assignments, and aligned comments shift together; labels remain in column zero. Existing indentStyle and tabSize settings control the whitespace used. Comments in column zero and comments configured with standaloneComment: "ignore" stay put.

Options for standaloneComment:

| Option | Behaviour | | ------------- | -------------------------------------------------------------------------------------------------------------------- | | "nearest" | Align to nearest element position (default). E.g. if current position is closest to mnemonic it snaps to that column | | "ignore" | Don't align | | elementName | Align to named element position e.g. "label", "mnemonic", "operands" | | number | Numeric literal position |

Options for autoExtend:

| Option | Behaviour | | ------- | ----------------------------------------------------------------------------------------------------------------------------- | | line | Adjust the position for the affected line only | | block | Adjust the position, maintaining alignment for all lines within the same block i.e. code separated by two or more line breaks | | file | Adjust the position, maintaining alignment for all lines in the source file |

Trim whitespace

Remove trailing whitespace from lines?

{
  "format": {
    "trimWhitespace": true
  }
}

default: true

Final new line

Require line break on final line?

{
  "format": {
    "finalNewLine": true
  }
}

End-of-line character

New line type: lf, cr, crlf

{
  "format": {
    "endOfLine": "lf"
  }
}

default: lf

TODO

  • Full documentation for 68010+ instructions
  • Diagnostics
    • Instruction signatures
  • Amiga or other platform specific docs?

License

This project is made available under the MIT License.

Development

Open the monorepo root and follow the workspace development instructions. Select Assembly: Extension + server in VS Code to debug both processes.

Release notes and licence

See CHANGELOG.md for released changes. Pending release notes live in the root .changeset directory. This package is MIT licensed.