org-lsp

Org in Sublime Text

LSP-org (editors/sublime/LSP-org) is a package for sublimelsp/LSP that runs Org through the server.

Installing#

curl -fsSL https://github.com/kristijanhusak/org-lsp/releases/download/nightly/install.sh | bash -s -- sublime

or, in a checkout of this repository:

scripts/install.sh sublime            # the nightly build
scripts/install.sh --source sublime   # links editors/sublime/LSP-org, and builds the server (cargo)

The script finds Sublime Text's Packages folder (set SUBLIME_PACKAGES when it cannot), puts the package there as LSP-org, adds LSP to Package Control's packages, so that it is installed when Sublime Text starts, and puts the server in ~/.local/bin (ORG_LSP_BIN_DIR names another directory). Then restart Sublime Text and open an .org file. Run it again to update.

By hand: install LSP with Package Control, and copy or link editors/sublime/LSP-org into the Packages folder (Preferences › Browse Packages…), keeping the name LSP-org.

The server needs nothing more. The package starts the first of:

  1. the command in its settings, when it is not the default ["org-lsp"];
  2. org-lsp on PATH, or in ~/.cargo/bin, ~/.local/bin, /usr/local/bin or /opt/homebrew/bin (Sublime Text started from a desktop launcher often has a shorter PATH than a terminal);
  3. the build in the checkout the package is linked from (target/release/org-lsp, then target/debug/org-lsp);
  4. the server of the package's own release for your platform (the nightly build for the nightly package, v0.2.0 for version 0.2.0), downloaded into a folder of that release in Sublime Text's Package Storage/LSP-org; a package updated to another release downloads its own, and the old server goes.

Org: Download the latest server fetches that release's server again and restarts the server.

Setting it up#

The settings are under Preferences › Package Settings › LSP › Servers › LSP-org. The server's options go in initializationOptions, the package's own beside them:

{
  "initializationOptions": {
    "org_agenda_files": ["~/org"],
    "org_todo_keywords": ["TODO(t)", "NEXT(n)", "|", "DONE(d!)"],
    "org_capture_templates": [
      { "key": "t", "description": "Task", "target": ["file+headline", "~/org/inbox.org", "Tasks"], "template": "* TODO %?\n  %U" }
    ],
    "org_agenda_custom_commands": [
      { "key": "n", "description": "Next actions", "type": "todo", "match": "NEXT" }
    ]
  },
  "org_keys": "vim"
}

The server's colors need LSP's "semantic_highlighting": true (in Preferences › Package Settings › LSP › Settings) and a color scheme that allows them: Sublime Text's own schemes do, and another needs the rule that LSP's docs give, added with UI: Customize Color Scheme:

{ "rules": [{ "scope": "meta.semantic-token", "background": "#00000101" }] }

The time clocked and the … of shrunk columns come as inlay hints, with LSP's "show_inlay_hints": true.

The server also reads the shared configuration file, ~/.config/org-lsp/config.toml, which every editor shares; initializationOptions goes on top of it. configuration.org has everything else: the package's settings and every option of the server with its default.

Using it#

The package binds Emacs's keys in Org files (Ctrl+C Ctrl+T, Tab …) and the agenda's keys in the agenda, but those Sublime Text uses for text (Shift and the arrows, Ctrl+A …), and Ctrl+C copies a selection; org_keys picks "emacs_full" (all of Emacs's keys), "vim" (for Vintage and NeoVintageous) or "custom" instead. The commands are in the Command Palette under Org:. keys/sublime.org lists every key of each preset, and how to bind your own.

Its syntaxes color Org files and the agenda by their patterns: headlines by level, TODO keywords, priorities, tags, planning lines and timestamps, drawers, lists and checkboxes, links, emphasis, tables, blocks and comments, and the code of source and export blocks and of inline source blocks in its language's syntax, for the languages Sublime Text ships. The server's colors go further: the TODO keywords of your files, the agenda's today, weekends and overdue items, the clocked entry.

Files with org-indent-mode (org_startup_indented, #+STARTUP: indent) show indented by level, without being changed: blanks before the lines, as phantoms. The leading stars still show, and the lines a long line wraps into are indented only by the line's own leading whitespace (Sublime Text's indent_subsequent_lines), not as Org indents them.

The agenda and capture need no Org file open: from the Command Palette (Org: Agenda commands, Org: Capture …) in any view, the package starts the server first, with a tab that says so and closes when the agenda opens.

What works#

FeatureParitySublime TextWhat does not work, and why
Highlighting100%❓Links, emphasis markers, pretty entities and sub- and superscripts are not concealed: Sublime Text cannot hide text in a view. The colors need LSP's semantic_highlighting on. A headline's look does not go on to the edge of the window (org_fontify_whole_heading_line): Sublime Text colors a line past its text only with a region filled in one color of the color scheme, as the agenda's clocked line, not in the look semantic tokens give the headline.
Folding and visibility91%❓A closed fold ends in Sublime Text's own marker: a package cannot change it (org_ellipsis).
Headings and structure96%✅
Lists and checkboxes93%✅
TODO keywords100%❓Faces of particular keywords and priorities are not shown in the file: Sublime Text colors text by its color scheme only. The list of TODO states shows them in the color of each item's kind, the nearest of those Sublime Text has.
Priorities100%✅
Tags88%❓Faces of particular tags are not shown: Sublime Text colors text by its color scheme only.
Properties and column view100%❓Column view is left out: it draws over the headlines, which Sublime Text cannot. A custom property hidden (org.custom.properties.toggle) is in a fold from the end of the line before, which shows the fold's marker: Sublime Text hides text only in folds.
Dates and times100%❓Dates are typed, without the calendar: the package asks with an input panel.
Agenda97%❓Column view in the agenda is left out: it draws over the lines, which Sublime Text cannot. The days of a habit's graph take the colors of text, not Org's backgrounds: Sublime Text colors a token by its color scheme.
Clocking100%✅
Capture100%✅
org-protocol86%✅
Notes (org-roam)94%✅
A journal (org-journal)93%❓The calendar and the keys org-journal adds to it are left out: the package shows no date prompt.
Refile and archive100%✅
Links96%✅
Footnotes100%✅
Tables100%❓A shrunk column shows its whole text and …: Sublime Text cannot hide text in a view.
Table formulas100%✅
Code blocks (Babel)100%✅
Export and publishing100%✅
Citations82%✅
Diagnostics (org-lint)100%✅
Indentation and formatting100%❓Virtual indentation shows as phantoms, the leading stars still showing; new lines are not indented as they are typed. The lines a long line wraps into are not indented as Org does: Sublime Text indents them by the line's own leading whitespace (indent_subsequent_lines).
Notes and logging100%✅
Completion and editing helpers100%✅
Timers100%✅
Attachments100%✅
Encryption100%✅
Inline images and LaTeX previews100%❓An image shows below its line (a phantom), not over the link; PNG, JPEG and GIF only. Counts through a key's args.
All of Org97%

✅ all that org-lsp does works there, ❓ some does not (the last column says what and why), ❌ none does, — nothing to support yet. Parity is the share of what Emacs Org does in that area that org-lsp does; parity.org lists both.

TESTING.org lists what to try by hand.

Developing#

node editors/sublime/generate.mjs writes the package's keymap, commands and token scopes from the server's manifest (--check fails if they are out of date), and python3 editors/sublime/test/test_plugin.py runs the plugin against stand-ins for Sublime Text and LSP.