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

@codincod/codemirror-lang-r

v0.1.0

Published

R language support for the CodeMirror code editor

Readme

@codincod/codemirror-lang-r NPM version

[ CHANGELOG ]

This package implements R language support for the CodeMirror code editor, using a Lezer grammar ported from R's own.

CodeMirror 6 has never shipped R. What stands in for it is the stream mode carried over from CodeMirror 5, which colours a keyword list and builds no tree, so nothing above it can fold a function, indent an argument list or ask what the name under the cursor is. There is one other Lezer grammar for R on npm, and it reads under a third of real R: no unary minus, no < or >, no :, no |>, no %in%, no braceless body, no \(x), no raw string.

Written in part for CodinCod, a competitive coding platform, where it colours the editor people solve puzzles in.

This code is released under an MIT license.

Usage

import {EditorView, basicSetup} from "codemirror"
import {r} from "@codincod/codemirror-lang-r"

const view = new EditorView({
  parent: document.body,
  doc: `greet <- function(name = "world") {
  sprintf("Hello, %s!", name)
}
`,
  extensions: [basicSetup, r()]
})

Coverage

R 4.5. Every assignment R has, including :=; functions written with function and with \(x); if, for, while and repeat with braces and without; calls with named, empty and dotted arguments; [, [[ and their empty subscripts; ::, :::, $ and @; formulas; the native pipe and the ones packages define between percent signs; raw strings; backtick names; integer, double, hexadecimal and complex literals; roxygen comments; and ..., ..1 and the pipe placeholder.

Measured against 2 322 R files from eight open source projects (R itself, ggplot2, dplyr, tidyr, data.table, shiny, testthat and devtools), which is 15 MiB of code, of which 99.70% parse with no error node. The seven files that do not are not R: three are fixtures in R's own test suite that hold a deliberate parse error, two are shiny templates holding {{ }} placeholders, one is testthat's syntax-error fixture, and one is written in Latin-1.

What the grammar cannot say

The grammar is a port of src/main/gram.y from the R sources, which is an LALR grammar and so nearly a Lezer grammar already. Its precedence table is R's read from the other end, and every production answers to one there. Three things are settled in src/tokens.ts instead, because no context free rule can decide them.

A line break ends an expression when the expression is finished. R has no statement terminator. x <- 1 followed by a line holding -2 is two expressions, and x <- 1 + followed by a line holding 2 is one. The tokenizer offers a terminator of no width at every line break and the parser takes it only where an expression may end, which is nowhere inside a bracket and nowhere after an operator still waiting for its right hand side. That is the whole rule, and it needs one exception: a line may open with else, which R itself allows inside braces and refuses outside them.

A raw string carries its own delimiter. r"(a\d+)" holds a backslash and ends at )". r"---(x)---" ends only at the dashes it opened with, and how many there were is not something a regular expression can remember.

A string is cut into pieces. The escapes inside it are coloured apart from the text around them, so the tokenizer hands over a start, the runs of text, the escapes and an end. Each quote character has its own set of those tokens, which is how the tokenizer knows what it is looking for without keeping any state.

Testing

npm test                       # the parse specs, then highlighting and indentation
npm run corpus -- path/to/code # error nodes over a directory of real R files

No corpus ships with the package, because none of that code is ours to redistribute. test/corpus.ts takes a directory and reports the share of files that parse with no error node, grouped by directory so that a project which drags the total down names itself.