Getting started

cdin is a small text editor in C and Lua. The C side owns the window, the renderer and the OS; everything you would call “the editor” — documents, views, commands, the keymap, syntax highlighting, styling — is Lua in data/core/ next to the binary. If you can read Lua, you can read the whole editor.

This page covers running it and finding your way around. To compile it, see building from source.

Running

Download a release, or build it — with one caveat:

git clone https://github.com/m-mdy-m/cdin-x   # the mandatory set lives here
git clone https://github.com/m-mdy-m/cdin
cd cdin
make run

A fresh clone of cdin alone cannot make. make assembles data/, and the mandatory set — vim mode, the extension manager, the default theme, the fonts — comes from cdin-x, which must be a sibling checkout or be named with CDINX_DIR. make bin compiles the binary alone and needs neither. Building from source has the whole story.

The binary lands at build/<platform>-<build>/cdin — cdin.exe on Windows — and that directory is self-contained. data/ has to travel with it, which is the one thing to be careful about if you move the binary somewhere.

You can pass files and a directory:

cdin notes.md src/          # open some files, work in src/
cdin --no-plugins notes.md  # site plugins off; vim and the manager stay
cdin -u NONE notes.md       # the same thing, vim's spelling

A directory argument becomes the working directory, and the working directory is the project: the file list, the ignore rules and the git status all come from it. With no directory, the last one you used is restored — cdin-x’s session plugin writes it, and with no session file it falls back to the executable’s own directory.

Careful with -u: it swallows the next argument unconditionally, so cdin -u notes.md opens nothing and you get an empty editor.

--no-plugins turns off site plugins only — the directory a cdin-x checkout and your own plugins live in. Vim mode, the manager, the default theme and the fonts are part of the build and always load, and what you installed from the panel is in neither place, so it keeps loading too. See configuration for the whole boundary.

First launch

You get the empty view: recent files and directories, and a short quick reference underneath.

key does
Ctrl+N a new empty document
↑ / ↓ move through the recent items — printed, but not wired yet
Tab switch between files and directories — printed, but not wired yet
Return open the selected one — printed, but not wired yet
Esc clear the selection — printed, but not wired yet

Clicking a recent item opens it. The four struck-through rows are a known gap, not a design: the empty view handles those keys in an on_key_pressed that nothing in the runtime calls, and the commands those strokes name all need an open prompt. Commands has the mechanism; it is a two-line dispatch and it is the one thing on this screen that lies to you.

There is no command palette row, no “find file” row, no “open folder” row — those features are not part of this editor, so listing them would print keystrokes that do nothing. Install the extensions that provide them and their entries appear here, appended, so the list on screen stays exactly as long as what the runtime owns.

With no document open, Ctrl+N is the whole editor. It works with nothing installed, which is the test that the two halves of this project are really separate.

What you get, and what you have to add

In every build, because the editor cannot start without them:

vim mode modal editing and the : line. Ctrl+Alt+V toggles it for the session — both the key and the setting belong to the vim plugin, not to the runtime
the extension manager the panel that lists, searches, installs and removes extensions. Ctrl+Shift+M
the default theme
the fonts the text pipeline has nothing to render with otherwise

The manager is in every build because “what is installed, and how do I change that” is a question the editor has to be able to answer itself. Everything it offers is still optional; what is not optional is the ability to ask. With no cdin-x installed it lists exactly what the build carries, which is a truthful answer rather than an empty panel.

Not in the build, because they are workflows rather than mechanics. None of these keystrokes works until you install the thing that owns it:

binds for
command palette Ctrl+Shift+P run any command by name
finder Ctrl+P, Ctrl+O, Ctrl+Shift+O find a file, open a path, open a folder
project tree Ctrl+\, F3 show and focus it
tabs Ctrl+Tab, Ctrl+T switch, create
find and replace Ctrl+F in the document
project-wide search Ctrl+Shift+F across files
session restore Ctrl+Shift+R recent files
git no keys status in the tree and the status bar
syntax highlighting no keys one extension per language, six to start with
themes no keys nine more beyond default

Plus autocomplete, the vim integrations, and cdin-x’s optional/ trio.

Splits and panes are the exception, and they are the runtime’s. Alt+Shift+J/L/I/K splits, Alt+J/L/I/K moves between panes, and Ctrl+W closes a view — because laying out a window needs no extension. cdin-x’s window extension adds an alternative set (Alt+h/j/k/l, Ctrl+\) and, where the two overlap, it wins: Alt+J will do what window says.

All of it is cdin-x, and you get it from inside the editor. Press Ctrl+Shift+M, move to what you want, press Space. The manager downloads that one extension — not the repository — and loads it without a restart. Extensions has every key, what each one collides with, what is downloaded, and where it goes.

You need a cdin-x checkout to build cdin, and not to use it. Cloning one and running make link is for working on cdin-x itself: it puts the checkout into your site directory so your edits are live.

If you only want one thing, it is the command palette — it runs every command in this reference by name, which is the fastest way to learn what exists. Find palette in the panel and press Space. finder is the second: three keys for the three ways of getting a file open, and the empty view delegates to it by name, so installing it is what makes “open file” on the start screen work.

The parts you will use every day

Moving and editing. Arrow keys, Ctrl for word-at-a-time, Ctrl+←/→ for words, Ctrl+[/] for bracketed blocks, Home/End for the line, Ctrl+Home/End for the file. Selections are Shift plus any of those. Tab indents, Shift+Tab outdents, Ctrl+/ toggles comments.

Saving. Ctrl+S, which prompts for a path the first time. Ctrl+Shift+S saves under a different name.

Splitting. Alt+Shift+J/L/I/K splits the pane in that direction, Alt+J/L/I/K moves between panes, Ctrl+W closes the active view. Splitting carries the current document into the new pane, so you never end up staring at half a split.

Jumping. Ctrl+G takes a line number, or a string to fuzzy-match against the document’s lines — so a distinctive phrase is usually faster than counting.

Quitting. Any command runner’s quit, or close the window. You are asked before discarding unsaved changes.

the command reference has all of it, with the command name for each.

Configuring

One file:

~/.config/cdin/user/init.lua
local keymap = require "core.input.keymap"
keymap.add { ["ctrl+g"] = "doc:go-to-line" }

config and core are not globals — the editor raises on any undeclared global, so require them:

local config = require "core.config"
config.indent_size = 4

Your file runs before plugins load. Configuration has every key, and the reasoning behind the load order — which decides whether a plugin or you gets the last word on a keystroke.

When something does not work

Press Ctrl+Shift+L, which is core:open-log. The runtime binds it itself, so it works in a build with nothing installed.

Everything the log view shows is also written to cdin-log.txt next to the binary, together with the C logger’s own lines, tracebacks included. That one text file is what to attach to a bug report. See troubleshooting.

Troubleshooting has the specific failures, build and otherwise, and a short list of make targets that do not work.

Where to go next

Commands every command and key, as a table
Configuration every config key
Extensions what a build contains, the panel, installing, where things land
Plugins the loader, and writing one
Architecture if you are about to change something
Extension contract if you are about to change what is guaranteed