org-lsp

Keys in Zed

In Org files the commands are in the code actions (editor: toggle code actions, ctrl-. or cmd-.), which list what applies where the cursor is, and Org's keys run them too once the two files of keys through tasks are pasted:

  • In an Org file: change the TODO state (the next one, the previous one, or one picked from a list), the priority, the timestamp under the cursor; toggle a checkbox; a new heading, item or table row (as M-RET, M-S-RET, C-RET and C-S-RET make them), the cursor then in it; clock in and out; refile; archive; open the agenda (this week, the TODO list, or the agenda menu); capture.
  • In a capture buffer: file the entry, give up, or refile it.

Bind editor::ToggleCodeActions to a key of your own if the menu is too far away.

What a command asks for is asked with buttons: a TODO state, a priority, a refile target, a capture template, yes or no. Zed has no box of its own for a server to ask for typed text, so the commands that want a date (schedule, deadline) or text (a template's %^{…} prompts, a tags search) say what they ask for and answer with a rename at the cursor: rename at the cursor (F2) and type the answer (+2d, fri 10:00, a search) for the new name. Zed sends no empty new name: - alone is the empty answer, the prompt's default (Insert link (default …), Table size Columns x Rows (empty for Org's default), today for a date). Until then a rename answers the question, not renames.

zed.org says how to install and set up the extension.

Keys through tasks#

An extension cannot bind keys, and a key of Zed's cannot run a language server's command, but it can run a task. Two files of the extension set that up, once (and again when they change, after an update):

  1. tasks.json: a task for each command (Org: … and Org agenda: …). Paste its entries into your tasks (zed: open tasks, ~/.config/zed/tasks.json).
  2. keymap.json: binds the agenda's keys, and Org's keys in Org files and capture buffers (ctrl-c ctrl-t, ctrl-c ctrl-c, ctrl-c ,, alt-enter, ctrl-c a, ctrl-c c and the rest), to those tasks. Paste its blocks into your keymap (zed: open keymap).

The tasks use none of Zed's $ZED_FILE or $ZED_ROW: Zed offers no task that uses them in a file outside the project, which the agenda and a capture buffer are. The server follows the cursor itself instead (from the highlights Zed asks for as it moves), and a task runs its command where the cursor last was: on the agenda's line in the agenda, at the cursor in an Org file. A key that means one thing in a capture buffer and another elsewhere, as ctrl-c ctrl-c files the capture there and toggles a checkbox or updates a block elsewhere, runs the command of the buffer the cursor is in.

ctrl-c ctrl-c in a capture buffer files the entry, ctrl-c ctrl-k gives up and ctrl-c ctrl-w refiles it. Its tab stays open afterwards, as Zed lets no server close one; close it with ctrl-w and do not save it.

Opening the agenda#

The agenda, the TODO list, the agenda menu and capture need no Org file open: run them from the task picker (task: spawn, alt-shift-t on Linux; type Org:) anywhere, or with ctrl-c a and ctrl-c c in an Org file or the agenda. When no server runs yet, the task opens the Org file you last opened, in its folder, with Zed's command line (found beside Zed, or zed or zeditor on PATH; on macOS run cli: install once), which starts one, and then runs the command there.

The agenda is a file the server writes, ~/.local/state/org-lsp/agenda/…/Agenda.org-agenda (the same one for the same project folders), opened as Org; the server writes it again when it changes. It is not read-only, as Zed refuses a rename in a read-only file, and a rename answers what the agenda's commands ask; text typed in it by mistake keeps Zed from reading it again (undo it). When Zed starts again with the agenda's tab open, the new server takes the tab over: it shows the agenda of the current week, and its keys work.

How the tasks run#

A task's terminal stays out of sight unless the command fails.

The tasks are yours rather than the extension's because Zed offers an extension's tasks only in files of the project's folders, and the agenda is a file of the server's own, elsewhere: a key bound to one would open the task picker instead. Each task runs ~/.local/state/org-lsp/agenda-command, a script the server writes, which runs the command where the cursor is: the server follows the cursor through the document highlights Zed asks for when it moves (after lsp_highlight_debounce, 75 milliseconds). With agendas open in several windows, the keys act on the one the cursor was last in. The script stays when Zed quits, so that the tasks can start a server.

On Windows, where the script is agenda-command.cmd under your user folder and the shell is PowerShell, make each task's command & "$HOME/.local/state/org-lsp/agenda-command.cmd" org.agenda.later (with its own command at the end).

The keys#

The agenda has the same keys as in every editor, Emacs's agenda keys, with J for a date and the views under v (v d, v w), so that Vim mode keeps its motions.

In the agenda#

KeysCommand or Zed actionWhat it does
qpane::CloseActiveItemClose the agenda
entereditor::GoToDefinitionGo to the entry of the line
tabeditor::GoToDefinitionSplitShow the entry of the line in a split
s, ctrl-x ctrl-sworkspace::SaveAll
forg.agenda.laterAgenda: go forward in time
borg.agenda.earlierAgenda: go backward in time
.org.agenda.todayAgenda: go to today
[org.agenda.query.addAgenda: search for another word, or show inactive timestamps
]org.agenda.query.subtractAgenda: search without a word, or show inactive timestamps
{org.agenda.query.add.regexpAgenda: search for another regexp, or show inactive timestamps
}org.agenda.query.subtract.regexpAgenda: search without a regexp, or show inactive timestamps
shift-jorg.agenda.goto.dateAgenda: go to a date
v dorg.agenda.dayAgenda: day view
v worg.agenda.weekAgenda: week view
v torg.agenda.fortnightAgenda: fortnight view
v morg.agenda.monthAgenda: month view
v yorg.agenda.yearAgenda: year view
rorg.agenda.redoAgenda: rebuild
v lorg.agenda.logAgenda: log mode, what was closed and clocked
shift-korg.agenda.habitsAgenda: show or hide habits
ctrl-x ctrl-worg.agenda.writeAgenda: write it to a file
ctrl-c ctrl-x ctrl-corg.agenda.columnsAgenda: column view
shift-r, v shift-rorg.agenda.clockreportAgenda: the clock report
shift-e, v shift-eorg.agenda.entry.textAgenda: entry text mode, some text of each entry under its line
shift-forg.agenda.followAgenda: follow mode, the cursor's entry in another window
morg.agenda.bulk.markAgenda: mark the entry for a bulk action
uorg.agenda.bulk.unmarkAgenda: unmark the entry
shift-uorg.agenda.bulk.unmark.allAgenda: unmark all entries
alt-morg.agenda.bulk.toggleAgenda: toggle the mark of the entry
*org.agenda.bulk.mark.allAgenda: mark all entries
alt-*org.agenda.bulk.toggle.allAgenda: toggle the marks of all entries
%org.agenda.bulk.mark.regexpAgenda: mark the entries matching a regexp
shift-borg.agenda.bulk.actionAgenda: an action on the marked entries
/org.agenda.filterAgenda: filter by tags, categories, effort and regexps
\org.agenda.filter.tagAgenda: filter by tag
<org.agenda.filter.categoryAgenda: filter by the line's category
=org.agenda.filter.regexpAgenda: filter by a regexp
_org.agenda.filter.effortAgenda: filter by effort
^org.agenda.filter.top.headlineAgenda: filter by the line's top headline
¦org.agenda.filter.removeAgenda: remove all filters
v aorg.agenda.archivesAgenda: include archived trees
v [org.agenda.inactiveAgenda: show inactive timestamps once
v shift-aorg.agenda.archives.filesAgenda: include archived trees and archive files
shift-iorg.clock.inClock in
shift-oorg.clock.outClock out
shift-xorg.clock.cancelCancel the clock
torg.todoChange the TODO state
ctrl-shift-rightorg.todo.nextsetSwitch to the next TODO keyword set
ctrl-shift-leftorg.todo.previoussetSwitch to the previous TODO keyword set
+, shift-uporg.priority.upRaise the priority
-, shift-downorg.priority.downLower the priority
,org.prioritySet the priority
ctrl-c ctrl-x porg.property.setSet a property of the entry
eorg.effort.setSet the effort of the entry
:, ctrl-c ctrl-qorg.tags.setSet the tags of the headline
ctrl-c ctrl-worg.refileRefile the entry
zorg.add.noteAdd a note to the entry
ctrl-c ctrl-oorg.openOpen the link or thing at the cursor
ctrl-c lorg.link.storeStore a link to the place at the cursor
$, ctrl-c ctrl-x ctrl-s, ctrl-c $org.archive.subtreeArchive the subtree
ctrl-c ctrl-x shift-aorg.archive.siblingArchive the subtree under its Archive sibling
ctrl-c ctrl-x aorg.archive.tagToggle the ARCHIVE tag
ctrl-c ctrl-x ctrl-aorg.archive.defaultArchive with the default command
aorg.archive.confirmArchive with the default command, once confirmed
shift-rightorg.date.laterMove the date one day later
shift-leftorg.date.earlierMove the date one day earlier
ctrl-c ctrl-sorg.scheduleSchedule the entry
ctrl-c ctrl-dorg.deadlineSet the deadline of the entry
ctrl-c aorg.agenda.dispatchAgenda commands
ctrl-c corg.captureCapture
ctrl-c n forg.roam.node.findRoam: find a node
ctrl-c n corg.roam.captureRoam: capture to a node
ctrl-c n d norg.roam.dailies.capture.todayRoam: capture to today's daily note
ctrl-c n d dorg.roam.dailies.goto.todayRoam: go to today's daily note
ctrl-c n d torg.roam.dailies.goto.tomorrowRoam: go to tomorrow's daily note
ctrl-c n d yorg.roam.dailies.goto.yesterdayRoam: go to yesterday's daily note
ctrl-c n d vorg.roam.dailies.capture.dateRoam: capture to the daily note of a date
ctrl-c n d corg.roam.dailies.goto.dateRoam: go to the daily note of a date
ctrl-c n d .org.roam.dailies.find.directoryRoam: open the directory of the daily notes
ctrl-c n lorg.roam.buffer.toggleRoam: show or hide the org-roam buffer
ctrl-c j jorg.journal.new.entryJournal: new entry

¦ stands for |, which an Org table cannot hold.

In Org files#

KeysCommand or Zed actionWhat it does
ctrl-c ctrl-ckey:C-c C-cIn a capture buffer: finish; elsewhere: toggle the checkbox
ctrl-c ctrl-wkey:C-c C-wRefile the entry
ctrl-c ctrl-x ctrl-iorg.clock.inClock in
ctrl-c ctrl-x ctrl-xorg.clock.in.lastClock in the last clocked task
ctrl-c ctrl-x ctrl-zorg.clock.resolveResolve open clocks
ctrl-c ctrl-x ctrl-oorg.clock.outClock out
ctrl-c ctrl-x ctrl-qorg.clock.cancelCancel the clock
ctrl-c ctrl-x ctrl-jorg.clock.gotoGo to the clocked entry
ctrl-c ctrl-x ctrl-dorg.clock.displayShow the time clocked under each headline
ctrl-c ctrl-x ctrl-rorg.clock.reportInsert or update a clock table
ctrl-c ctrl-x ctrl-uorg.dblock.updateUpdate the dynamic block
ctrl-c ctrl-x xorg.dblock.insertInsert a dynamic block
ctrl-c ctrl-aorg.attachAttachments of the entry
ctrl-c ctrl-torg.todoChange the TODO state
ctrl-c ,org.prioritySet the priority
ctrl-c ctrl-x porg.property.setSet a property of the entry
ctrl-c ctrl-x eorg.effort.setSet the effort of the entry
ctrl-c ctrl-x shift-eorg.effort.increaseSet the effort to the next allowed value
ctrl-c ctrl-x oorg.ordered.toggleToggle whether subtasks must be done in order (ORDERED)
ctrl-c ctrl-x @org.cite.insertInsert a citation, or edit the one at the cursor
ctrl-c ctrl-qorg.tags.setSet the tags of the headline
alt-enterorg.meta.returnNew heading, item or table row
alt-shift-enterorg.insert.todo.headingNew TODO heading, or item with a checkbox
ctrl-enterorg.insert.heading.afterNew heading after the subtree
ctrl-shift-enterorg.insert.todo.heading.afterNew TODO heading after the subtree
ctrl-c ctrl-x torg.inlinetask.insertInsert an inline task
ctrl-oorg.open.lineOpen a line, or in a table insert a row
ctrl-c -org.table.hlineInsert a rule below the table row
ctrl-c enterorg.table.hline.moveInsert a rule below the table row and go below it
ctrl-c ^org.sortSort the entries, the items or the table rows
ctrl-c /org.sparse.treeShow a sparse tree
ctrl-c ctrl-rorg.revealShow the context of the cursor
ctrl-c ctrl-x ctrl-worg.cut.subtreeCut the subtree
ctrl-c ctrl-x alt-worg.copy.subtreeCopy the subtree
ctrl-c ctrl-x ctrl-yorg.paste.subtreePaste the subtree
ctrl-c alt-worg.refile.copyCopy the entry to a refile target
ctrl-c ctrl-zorg.add.noteAdd a note to the entry
ctrl-c ctrl-v t, ctrl-c ctrl-v ctrl-torg.babel.tangleTangle the file's code blocks
ctrl-c ctrl-v e, ctrl-c ctrl-v ctrl-eorg.babel.executeEvaluate the code block or call at the cursor through Emacs
ctrl-c ctrl-v b, ctrl-c ctrl-v ctrl-borg.babel.execute.bufferEvaluate the file's code blocks through Emacs
ctrl-c ctrl-v s, ctrl-c ctrl-v ctrl-sorg.babel.execute.subtreeEvaluate the subtree's code blocks through Emacs
ctrl-c ctrl-v korg.babel.remove_resultRemove the results of the code block at the cursor
ctrl-c ctrl-norg.heading.nextMove to the next heading
ctrl-c ctrl-porg.heading.previousMove to the previous heading
ctrl-c ctrl-forg.heading.forwardMove to the next heading of the same level
ctrl-c ctrl-borg.heading.backwardMove to the previous heading of the same level
ctrl-c ctrl-uorg.heading.upMove to the parent heading
ctrl-c ctrl-x ctrl-norg.link.nextMove to the next link
ctrl-c ctrl-x ctrl-porg.link.previousMove to the previous link
ctrl-c ctrl-jorg.gotoGo to a heading of the file
ctrl-c ctrl-x forg.footnote.actionMake a footnote, or go between a footnote and its definition
ctrl-c ;org.toggle.commentToggle the COMMENT keyword of the heading
ctrl-c ctrl-x ctrl-forg.emphasizeInsert emphasis markers
ctrl-c ctrl-,org.structure.templateInsert a block (structure template)
ctrl-c ctrl-x dorg.drawer.insertInsert a drawer
ctrl-c ctrl-x corg.subtree.cloneClone the subtree, shifting its dates
ctrl-c +org.table.sumSum the numbers of the table column
ctrl-c ?org.table.field.infoShow the references of the table field
ctrl-c ¦org.table.createInsert an empty table
ctrl-c " gorg.plot.gnuplotPlot the table with gnuplot
ctrl-c " aorg.table.ascii.plotDraw the column at the cursor as bars
ctrl-c ctrl-v n, ctrl-c ctrl-v ctrl-norg.babel.nextMove to the next code block
ctrl-c ctrl-v p, ctrl-c ctrl-v ctrl-porg.babel.previousMove to the previous code block
ctrl-c ctrl-v gorg.babel.gotoGo to a named code block
ctrl-c ctrl-v iorg.babel.lob.ingestAdd the file's named code blocks to the Library of Babel
ctrl-c alt-forg.block.nextMove to the next block
ctrl-c alt-borg.block.previousMove to the previous block
ctrl-c 'org.edit.specialEdit the block in a file of its own
ctrl-x n sorg.narrow.subtreeNarrow to the subtree: it in a file of its own
ctrl-x n borg.narrow.blockNarrow to the block: it in a file of its own
ctrl-x n worg.narrow.widenWiden: the narrowed file written back and closed
ctrl-c ctrl-x borg.tree.indirectShow the subtree in a file of its own
ctrl-c `org.table.edit.fieldEdit the table field in a file of its own
ctrl-c ctrl-x ctrl-corg.columnsColumn view
ctrl-c ctrl-x ctrl-vorg.link.previewPreview the images of links
ctrl-c ctrl-x ctrl-lorg.latex.previewPreview LaTeX fragments
ctrl-c ctrl-x 0org.timer.startStart the relative timer
ctrl-c ctrl-x .org.timer.insertInsert the timer's value
ctrl-c ctrl-x -org.timer.itemInsert a list item with the timer's value
ctrl-c ctrl-x ,org.timer.pausePause or continue the timer
ctrl-c ctrl-x _org.timer.stopStop the timer
ctrl-c ctrl-x ;org.timer.setSet a countdown timer
ctrl-c ctrl-eorg.export.dispatchExport the file through Emacs
ctrl-c taborg.table.toggle.column.widthShrink or expand the table column
ctrl-c *org.table.recalculate.lineRecalculate the table's current line
ctrl-c {org.table.formula.debuggerTurn the formula debugger on or off
ctrl-c ctrl-oorg.openOpen the link or thing at the cursor
ctrl-c lorg.link.storeStore a link to the place at the cursor
ctrl-c ctrl-lorg.link.insertInsert a link, or edit the one at the cursor
ctrl-c alt-lorg.link.insert.lastInsert the last stored link
ctrl-c ctrl-alt-lorg.link.insert.allInsert all stored links
ctrl-c ctrl-x ctrl-s, ctrl-c $org.archive.subtreeArchive the subtree
ctrl-c ctrl-x shift-aorg.archive.siblingArchive the subtree under its Archive sibling
ctrl-c ctrl-x aorg.archive.tagToggle the ARCHIVE tag
ctrl-c ctrl-x ctrl-aorg.archive.defaultArchive with the default command
ctrl-c n iorg.roam.node.insertRoam: insert a link to a node
ctrl-c n d forg.roam.dailies.goto.nextRoam: go to the next daily note
ctrl-c n d borg.roam.dailies.goto.previousRoam: go to the previous daily note
ctrl-c j forg.journal.next.entryJournal: next entry
ctrl-c j borg.journal.previous.entryJournal: previous entry
ctrl-c j sorg.journal.searchJournal: search between two dates
ctrl-c ctrl-korg.capture.abortCapture: abort
ctrl-c ctrl-sorg.scheduleSchedule the entry
ctrl-c ctrl-dorg.deadlineSet the deadline of the entry
ctrl-c .org.timestamp.insertInsert or change a timestamp
ctrl-c !org.timestamp.insert.inactiveInsert or change an inactive timestamp
ctrl-c ctrl-x ctrl-torg.timestamp.overlays.toggleShow timestamps in the custom formats, or not
ctrl-c >org.goto.calendarShow the calendar at the date of the line
ctrl-c aorg.agenda.dispatchAgenda commands
ctrl-c corg.captureCapture
ctrl-c n forg.roam.node.findRoam: find a node
ctrl-c n corg.roam.captureRoam: capture to a node
ctrl-c n d norg.roam.dailies.capture.todayRoam: capture to today's daily note
ctrl-c n d dorg.roam.dailies.goto.todayRoam: go to today's daily note
ctrl-c n d torg.roam.dailies.goto.tomorrowRoam: go to tomorrow's daily note
ctrl-c n d yorg.roam.dailies.goto.yesterdayRoam: go to yesterday's daily note
ctrl-c n d vorg.roam.dailies.capture.dateRoam: capture to the daily note of a date
ctrl-c n d corg.roam.dailies.goto.dateRoam: go to the daily note of a date
ctrl-c n d .org.roam.dailies.find.directoryRoam: open the directory of the daily notes
ctrl-c n lorg.roam.buffer.toggleRoam: show or hide the org-roam buffer
ctrl-c j jorg.journal.new.entryJournal: new entry

¦ stands for |, which an Org table cannot hold.