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

@inhuman.tools/arrival-codemirror

v0.9.9

Published

CodeMirror 6 for arrival Scheme (Scheme + sugarcoat). Language, structural editing, ghost, param hints, and full IDE surface (lint/hover/completion/goto) over a SchemeIdeBackend seam.

Readme

@inhuman.tools/arrival-codemirror

CodeMirror 6 for @inhuman.tools/arrival Scheme (Scheme + sugarcoat).

Two mounts — vanilla CM6 extensions, or <SchemeEditor> from ./react.

Install

npm i @inhuman.tools/arrival-codemirror

Quick start

import { defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
import { EditorView, lineNumbers } from "@codemirror/view";
import { createBrowserSchemeLanguageService } from "@inhuman.tools/arrival-lsp/browser";
import { schemeIde, schemeStructural, schemeSugarcoat } from "@inhuman.tools/arrival-codemirror";

new EditorView({
  parent: document.querySelector("#editor")!,
  doc: `(define (greet name)\n  (string-append "hello, " name))\n\n(greet 42)\n`,
  extensions: [
    lineNumbers(),
    syntaxHighlighting(defaultHighlightStyle), // otherwise this snippet is unstyled
    schemeSugarcoat(),
    schemeStructural(),
    schemeIde(createBrowserSchemeLanguageService()),
  ],
});

schemeIde already includes ghost unless you pass { ghost: false }. createBrowserSchemeLanguageService() runs tsc on the main thread.

(greet 42) gets a real type error — tsc's, lifted to the .scm span.

React

<SchemeEditor> from ./react. Structural editing is opt-in — it steals Alt-↑ / Mod-Shift-K.

import { useState } from "react";
import { SchemeEditor } from "@inhuman.tools/arrival-codemirror/react";

export function App() {
  const [value, setValue] = useState(`(define (greet name)\n  (string-append "hello, " name))\n`);
  const [view, setView] = useState<"scheme" | "sugarcoat">("scheme");
  return <SchemeEditor value={value} onChange={setValue} view={view} structuralEditing />;
}

What's in the box

| Export | | | ---------------------------------------------- | ----------------------------------------------------------------------------- | | schemeSugarcoat() | Language mode: Scheme and Sugarcoat. Highlight tags only — bring a theme. | | schemeStructural() | Paredit on the Scheme lens. Real reader + verify-reparse net. | | schemeIde(backend) | Lint, hover, completion, goto, semantic highlight, and ghost. | | paramHintsExtension("scheme" \| "sugarcoat") | Inlay parameter-name hints. | | sugarcoatIdeBackend(backend) | Same IDE on the Sugarcoat face. | | /react | <SchemeEditor> + useSchemeIde() (SharedWorker → Worker → in-thread). |

The seam

Every IDE extension is wired to exactly one method of a structural SchemeIdeBackend:

interface SchemeIdeBackend {
  getSemanticDiagnostics(scheme: string): MaybePromise<SchemeIdeDiagnostic[]>;
  getQuickInfoAtPosition(scheme: string, offset: number): MaybePromise<SchemeIdeQuickInfo | null>;
  getCompletionsAtPosition(scheme: string, offset: number): MaybePromise<SchemeIdeCompletionEntry[]>;
  getDefinitionAtPosition(scheme: string, offset: number): MaybePromise<SchemeIdeDefinition[]>;
  getSemanticClassifications?(scheme: string): MaybePromise<SchemeIdeClassifiedSpan[]>; // optional
  getCompletionContext?(scheme: string, offset: number): MaybePromise<SchemeIdeCompletionContext>; // optional
}

Methods may answer sync or with a Promise, so an in-process service and a worker behind a message port satisfy the same seam — @inhuman.tools/arrival-lsp fits directly, in either mode. The optional methods are presence-gated feature unlocks: getSemanticClassifications turns on semantic highlighting, getCompletionContext upgrades completion and the ghost to the Σ∩T-ranked pipeline. Coordinates are always Scheme; Sugarcoat buffers translate through sugarcoatIdeBackend.

Structural keymap

Four transformation chords (slurp, barf, splice, kill-sexp), plus the selection ladder and a force-delete escape hatch. Browser-safe, zero Ctrl+Alt+char (AltGr-safe). A failed transformation chord does nothing (falling through to a default like Delete Line would be a destructive surprise); selection chords degrade gracefully.

| Chord | Op | | --------------------------------------- | ------------------------------------------------------------ | | Alt-↑ / Alt-↓ | expand / contract selection (the ladder remembers its steps) | | Mod-Shift-K | slurp forward — (a \| b) c → (a b c) | | Mod-Shift-J | barf forward — (a \| b c) → (a b) c | | Alt-S | splice — (a \| b c) → a b c | | Mod-Shift-Backspace | kill-sexp | | Alt-Backspace (mac: Ctrl-Backspace) | force delete — the strict-protection escape hatch |

Strict delete protection refuses any Backspace/Delete that would unbalance a currently-balanced buffer — the caret steps over the delimiter instead, paredit-style.

Honest edges

  • Structural ops are Scheme-lens-only, by design. Sugarcoat's indentation is semantic — slurp/barf there would be wrong, not just unmapped.
  • The IDE on Sugarcoat goes through span alignment. A position inside sugar that has no Scheme token answers empty; diagnostics inside sugar lift to the enclosing paired node. Unparseable Sugarcoat degrades to no answers (the editor keeps its last good state).
  • #\… char literals and #|…|# block comments are outside the structural reader's vocabulary — their presence suspends structure (conservative: they would mis-parse rather than throw). Highlighting and the IDE are unaffected.
  • The ghost and the completion popup never race — the unprompted moment at a narrowed argument slot belongs to the ghost; Ctrl-Space always brings the list; the popup hides the ghost.

Demos

Runnable setups live in demos/.

License

MIT.