Skip to content

Repository files navigation

cind

cind is a C++ editor core with incremental C/C++ syntax analysis, structural editing, Emacs-style commands and shared terminal and graphical frontends. The graphical frontend uses SDL3 for the platform window and input, and Skia for self-drawn UI rendering.

Requirements

The project requires CMake 3.28 or newer, Ninja or another CMake-supported build tool, and a C++23 compiler.

On Fedora, install the development dependencies with:

sudo dnf install \
  cmake ninja-build gcc gcc-c++ make autoconf automake libtool gperf gettext-devel texinfo \
  pkgconf-pkg-config ripgrep gc-devel libffi-devel libunistring-devel gmp-devel \
  libtool-ltdl-devel libxcrypt-devel utf8proc-devel libuv-devel SDL3-devel \
  libepoxy-devel freetype-devel fontconfig-devel \
  libicu-devel libjpeg-turbo-devel libpng-devel harfbuzz-devel

Skia and its WebKit-maintained CMake build files are included in third_party/skia. Building the GUI does not require a separate Skia checkout, GN, depot_tools, or an external source directory. CMake builds a project-private Guile runtime and Fibers dependency, and downloads doctest when tests are enabled. Their initial builds require network access. Ares Scheme sources are included in third_party/guile-ares-rs.

C++ semantic completion uses clangd from PATH. Local word and path completion remain available when no language server is installed.

On macOS with Homebrew, install the native dependencies with:

brew install cmake ninja pkgconf autoconf automake libtool gperf gettext texinfo \
  bdw-gc libffi libunistring gmp utf8proc libuv sdl3 freetype fontconfig \
  icu4c@78 jpeg-turbo libpng harfbuzz

Build the GUI

Configure and build with standard CMake commands:

cmake -S . -B build-gui -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCIND_BUILD_GUI=ON
cmake --build build-gui -j

Homebrew installs ICU as a keg-only dependency. On macOS, add its prefix while configuring:

cmake -S . -B build-gui -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCIND_BUILD_GUI=ON \
  -DCMAKE_PREFIX_PATH="$(brew --prefix icu4c@78)"

The first GUI build compiles the vendored Skia library and can take longer than subsequent builds.

Open a file in the graphical editor:

./build-gui/src/cind-gui path/to/file.cpp

An optional +LINE argument selects the initial line. The GUI asks Fontconfig for the generic monospace family by default. Font family, size and smoothing can be overridden:

./build-gui/src/cind-gui \
  --font-family Iosevka \
  --font-size 16 \
  --font-smoothing smooth \
  +120 path/to/file.cpp

Use --inspect to expose the GUI inspector for debugging self-drawn UI state. See GUI inspector for its commands and socket protocol.

Configuration

The graphical and terminal editors load cind/init.scm from XDG_CONFIG_HOME, or from ~/.config/cind/init.scm when XDG_CONFIG_HOME is unset. The file runs in an isolated Guile module with host, (cind host), (cind command), (cind input), and (cind minibuffer) available:

(define-command! host "user.hello"
  (lambda (context invocation)
    (set-message! host "hello from Scheme")
    (command-completed))
  #f)

(bind-key! host 'editor.default "C-c h" 'user.hello)

Definitions made by the file are installed as one transaction. A condition aborts its registry changes and is reported in the editor message area and scripting inspector state.

File mode and project discovery policy are also Scheme data. define-file-mode-rule! associates suffixes or exact filenames with a major mode, while define-project-provider! declares ancestor markers. Later rules have precedence and participate in the same extension transaction.

The C-h prefix opens editor self-description commands. C-h k describes the command resolved by a key sequence, C-h x describes a command, C-h b lists active bindings, C-h m describes the current mode policy, and C-h f/C-h v describe Scheme functions and variables. Descriptions use a read-only *Help* buffer in both graphical and terminal frontends.

M-: opens the embedded Ares REPL in the command loop. Its minibuffer completes Scheme bindings from the application's persistent user module while accepting arbitrary expressions. The command palette also exposes scheme.eval-region and scheme.eval-buffer; definitions made by any of the three commands remain available to later evaluations and to describe-function / describe-variable. Multiline output is shown in the reusable *Scheme Evaluation* buffer. Scheme source files use scheme-mode, with C-c C-e, C-c C-r, and C-c C-b bound to expression, region, and buffer evaluation. Typing a Scheme symbol opens Ares completion automatically; C-M-i remains available for an explicit request. Candidates include definitions created in the persistent user module by any of those evaluation commands. Scheme input pairs delimiters and quotes, provides structural deletion and form-aware indentation, and highlights Scheme tokens. M-x paredit.mode enables the paredit-mode minor mode; its bindings provide splice and forward/backward slurp and barf operations.

Build without the GUI

The default build produces the terminal editor and command-line analysis tools without compiling Skia or SDL support:

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build -j

Open a file in the terminal editor with:

./build/src/indent-core edit path/to/file.cpp

Run ./build/src/indent-core without arguments to list the available syntax, indentation, fixture and benchmark commands.

Tests

Build and run the configured test suite with:

cmake --build build-gui -j
ctest --test-dir build-gui --output-on-failure

Use the non-GUI build directory instead to run only the frontend-independent and terminal test suite. Replace Release with Debug in the configure command when debug symbols and assertions are preferred.

Documentation

Editor core and interaction:

Workbenches and navigation:

Language services:

Tooling:

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages