pmacs/Cargo.toml

338 lines
17 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[workspace]
# Session 1 of the pmacs-gpu arc landed `pmacs-protocol` as a workspace
# member (the wire-types crate). Session 2 (this) adds `pmacs-gpu` as
# the GPU/GUI frontend binary — wgpu/winit/cosmic-text/glyphon — with
# hello-world rendering. Protocol consumption arrives in session 3.
# See `docs/pmacs-gpu-design.md`.
members = [".", "pmacs-protocol", "pmacs-gpu"]
[workspace.dependencies]
# Shared between `pmacs` and `pmacs-protocol`. Pinned here so both
# crates use byte-identical postcard / serde versions — the wire
# format depends on it.
serde = { version = "1", features = ["derive"] }
postcard = { version = "1", features = ["use-std"] }
thiserror = "2"
# Shared between `pmacs` (terminal screen) and `pmacs-protocol`
# (`TerminalFrame::validate`). Pinned here so the producer and the
# validator agree on every glyph's column width.
unicode-width = "0.2"
[package]
name = "pmacs"
default-run = "pmacs"
version = "1.1.0"
edition = "2024"
rust-version = "1.95"
description = "Parallel Emacs --- a Rust-cored, Lua-scripted editor in the Emacs tradition"
license = "MIT OR Apache-2.0"
authors = ["Pmacs contributors"]
readme = "README.md"
repository = "https://git.levineuwirth.org/neuwirth/pmacs"
homepage = "https://levineuwirth.org/essays/pmacs"
documentation = "https://docs.rs/pmacs"
keywords = ["editor", "emacs", "tui"]
categories = ["text-editors"]
[lib]
name = "pmacs"
path = "src/lib.rs"
[[bin]]
name = "pmacs"
path = "src/main.rs"
[[bin]]
name = "pmacs-audit"
path = "src/bin/pmacs_audit.rs"
[lints.rust]
unsafe_code = "forbid"
missing_docs = "warn"
[lints.clippy]
all = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }
cargo = { level = "warn", priority = -1 }
# Allows: pedantic lints that fight readable code.
module_name_repetitions = "allow"
must_use_candidate = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
cast_possible_truncation = "allow"
cast_sign_loss = "allow"
cast_precision_loss = "allow"
similar_names = "allow"
multiple_crate_versions = "allow"
[features]
# Pick exactly ONE Lua flavor at build time. v0.1 default is LuaJIT
# (spec §3 Checkpoint 6); lua54 is a buildable fallback for environments
# without LuaJIT support (e.g. some CI hosts, big-endian machines).
#
# `luajit` and `lua54` are MUTUALLY EXCLUSIVE — they select mlua's
# mutually-exclusive Lua backends. `--all-features` enables both and CANNOT
# build; the `mlua-sys` build script errors ("You can enable only one of
# the features: …") before this crate compiles, so pmacs can't preempt it
# with a friendlier message — the fix is to build one flavor. See the
# feature matrix in README.md; build a non-default flavor with
# `--no-default-features --features lua54` (audit F-002).
default = ["luajit"]
luajit = ["mlua/luajit", "mlua/vendored"]
lua54 = ["mlua/lua54", "mlua/vendored"]
# T M10.2: gate the CRDT-backed buffer mode behind an opt-in feature
# so v0.1 builds carry zero CRDT overhead (no loro dependency, no
# field on the Buffer struct layout, no branch on apply_edit). v1.0
# builds enable `crdt`; the rope-projection redirect from M10.1 means
# the feature flip is invisible to v0.1 frontends and to workers.
crdt = ["dep:loro", "pmacs-protocol/crdt"]
[dependencies]
crossterm = "0.28"
thiserror = { workspace = true }
unicode-width = { workspace = true }
unicode-segmentation = "1"
# Regex engine for in-buffer regex search (Q#RX1). `regex::bytes::Regex`
# matches over rope-snapshot bytes and yields byte offsets directly.
# Already in the lockfile transitively; promoted to a direct dependency.
regex = "1"
# Work-stealing deque, MPMC channels, and parking primitives for the
# M3 worker pool (spec §6.3). The umbrella crate re-exports
# `crossbeam_deque`, `crossbeam_channel`, and `crossbeam_utils`.
crossbeam = "0.8"
# Wire format for the M3 message bus (spec §5.2). `serde` derives the
# trait, `rmp-serde` is the MessagePack codec the spec calls out by
# name; in-process and out-of-process workers must look identical to
# Lua, which means even the in-process bus encodes through MessagePack.
serde = { workspace = true }
rmp-serde = "1"
# Wire-types crate (session 1 of pmacs-gpu arc). Owns the
# `InstanceMessage` / `FrontendEvent` / capability / `SemanticFrame`
# family, plus the cell/buffer/rope wire types they reference. The
# `pmacs` crate re-exports through `crate::protocol`, `crate::cell`,
# `crate::buffer`, and `crate::rope` so existing internal imports keep
# working unchanged.
pmacs-protocol = { version = "1.0.0", path = "pmacs-protocol" }
# Wire format for the M5 frontend ↔ instance protocol (T M5.5b).
# Length-prefix framing wraps postcard-encoded payloads. Chosen for
# compactness on the cell-stream traffic (60 Hz cell deltas dominate
# the wire) and for its no-std future-option (a thin attach client or
# embedded REPL bridge can use the same parser). Schema evolution is
# handled by an explicit version handshake (`PROTOCOL_VERSION`); see
# `src/protocol.rs::Hello`. The worker-protocol encoding (§5.5 spec)
# remains MessagePack via `rmp-serde`; different subsystems with
# different requirements (compactness vs schema evolution).
postcard = { workspace = true }
# Signal handling for the M5.5 daemon (T M5.5e). Provides a safe
# wrapper for installing handlers that set an AtomicBool flag, which
# our accept loop polls between iterations. Used for SIGTERM/SIGINT
# (graceful shutdown) and SIGPIPE/SIGHUP (no-op handlers so writes
# return EPIPE rather than killing the process).
signal-hook = "0.3"
# mlua is feature-gated; the `default-features = false` here lets the
# top-level features above pick the Lua flavor without conflict.
mlua = { version = "0.10", default-features = false }
# Tree-sitter incremental-parser core (T M4.1). The bundled grammars
# below (T M4.2) sit on top of this crate.
tree-sitter = "0.26"
# Bundled grammars (T M4.2). Detection is by file extension; loading
# is lazy --- the C-side language object isn't materialized until the
# first buffer of that language opens. Adding a new grammar requires
# only a new dependency line here plus one entry in
# `crate::syntax::BUILTIN_LANGUAGES`.
tree-sitter-rust = "0.24"
tree-sitter-lua = "0.5"
# T M_B3 — C / C++. Bundled so opening a `.c`/`.cpp`/header file in
# the grid TUI gets lexical highlighting (keywords/strings/operators)
# via tree-sitter, with `LspStyleView` layered on top for semantic
# refinement (functions/types/macros via clangd's semantic tokens).
# `.h` is ambiguous C / C++; the `c` entry below claims it by default,
# matching the LSP filetype map in `builtin/runtime/lsp.lua`.
tree-sitter-c = "0.24"
tree-sitter-cpp = "0.23"
# CUDA (`.cu`/`.cuh`). CUDA is C++ with device extensions, but its own
# grammar recognizes `__global__`/`__device__` kernels, `<<<...>>>`
# launch syntax, and CUDA builtins that the C++ grammar would misparse.
# Loading is lazy like the others; `LspStyleView` layers clangd's CUDA
# semantic tokens on top (clangd serves `.cu`/`.cuh` off the same
# binary as C/C++). The crate exports `LANGUAGE`/`HIGHLIGHTS_QUERY`
# (plural, the rust/lua idiom) and rides `tree-sitter-language 0.1`, so
# it shares the ABI crate with the other grammars — no second
# `tree-sitter` in the graph (its own `tree-sitter` dep is dev-only).
tree-sitter-cuda = "0.21"
# Shell / bash. Lexical highlighting for `.sh`/`.bash` and the wider
# shell family (`.zsh`/`.ksh`/`.ash`/`.bats`) — the LSP half
# (bash-language-server + shellcheck/shfmt) was already wired in
# `builtin/runtime/lsp.lua`; this fills in the missing grammar. bash
# does not inherit another grammar, so `HIGHLIGHT_QUERY` (singular, the
# c/cpp/md idiom) is self-contained — no base-query composition like
# `cuda`. Exports `LANGUAGE` over `tree-sitter-language 0.1` (shared ABI
# crate, no second `tree-sitter` in the graph). Note: because the
# grammar's language name (`bash`) matches the `pmacs.lsp.config.bash`
# key, every extension claimed here also auto-attaches
# bash-language-server (shellcheck refuses zsh, so `.zsh` diagnostics
# may be sparse; highlighting is unaffected).
tree-sitter-bash = "0.25"
# Filename-identified languages (no useful extension): Dockerfile, Make,
# CMake. Highlighting for files detected by BASENAME (`Dockerfile`,
# `Makefile`, `CMakeLists.txt`) via the new filename map, plus their
# extensions (`.dockerfile`/`.mk`/`.cmake`). All three ride
# `tree-sitter-language 0.1` with `tree-sitter` dev-only (no second core
# in the graph) and export `LANGUAGE`/`HIGHLIGHTS_QUERY`.
# * Dockerfile: `tree-sitter-containerfile` — the maintained,
# ABI-current grammar (the older `tree-sitter-dockerfile` is pinned to
# `tree-sitter ^0.20` and would fork the graph). Covers Containerfile.
# * Make / CMake serve `dockerfile`/`cmake` LSP servers too (see lsp.lua);
# Make has no language server.
tree-sitter-containerfile = "0.9"
tree-sitter-make = "1.1"
tree-sitter-cmake = "0.7"
# Grammar-gap languages: these already have LSP configs (basedpyright /
# gopls / tsserver / taplo / zls) but shipped no tree-sitter grammar, so
# they rendered with no lexical color. Fill the gap. All ride
# `tree-sitter-language 0.1` (tree-sitter dev-only) and export
# `LANGUAGE`/`HIGHLIGHTS_QUERY`. TypeScript is special: one crate ships
# TWO grammars (`LANGUAGE_TYPESCRIPT`/`LANGUAGE_TSX`) and its highlights
# inherit JavaScript, so the `typescript*` entries compose the JS query
# ahead of the TS one (see `crate::syntax::BUILTIN_LANGUAGES`). JavaScript
# parses both `.js` and `.jsx`.
tree-sitter-python = "0.25"
tree-sitter-go = "0.25"
tree-sitter-javascript = "0.25"
tree-sitter-typescript = "0.23"
tree-sitter-toml-ng = "0.7"
tree-sitter-zig = "1.1"
# JSON + YAML — config formats + the honest gate on the Jupyter path
# (JSON). Both are ABI-current (`LANGUAGE: LanguageFn` via
# `tree-sitter-language`), NOT a `tree-sitter ^0.20` fork. Registering
# yaml also lights up markdown `---` frontmatter through the #122
# injection engine (the block injection query already sets yaml for it).
tree-sitter-json = "0.24"
tree-sitter-yaml = "0.7"
# T M9.7: markdown grammar so prompt result buffers with
# `_meta.format = "markdown"` get structured highlighting through the
# same M4 path as rust/lua — no special-case painter in Lua.
# Pinned to `0.5` (caret-excludes-major for 0.x; see
# `tree-sitter-rust = "0.24"` style above). The crate is the official
# tree-sitter-org grammar (`tree-sitter-md` on crates.io); the
# alternative names `tree-sitter-markdown*` are forks of varying
# maintenance status — pick the upstream one.
tree-sitter-md = "0.5"
# LaTeX / TeX (`.tex`/`.latex`/`.sty`/`.cls`) — the "basic LaTeX mode"
# foothold and the tier-1 detection substrate for the inline-math arc (lane
# framing `docs/latex-grammar-math-substrate-framing.md`). The canonical crate name
# `tree-sitter-latex` is squatted by a broken 0.1.0 repackage that ships no
# `scanner.c` for its declared external tokens and therefore CANNOT LINK
# (undefined `tree_sitter_latex_external_scanner_*`). `codebook-tree-sitter-latex`
# is a linkable republish of the real, maintained `latex-lsp/tree-sitter-latex`
# (MIT, texlab's author) modernized to the `LanguageFn` shim: it ships
# `scanner.c`, exports `LANGUAGE` over `tree-sitter-language 0.1` (tree-sitter
# dev-only, shared ABI crate — no second core in the graph), and its
# `grammar.js`/`scanner.c` are byte-identical to upstream (provenance diff
# discharged in the framing). It exports NO query constants, so highlighting
# uses the in-repo overlay `builtin/queries/latex/highlights.scm` (the first
# such overlay; `include_str!`'d in `crate::syntax::BUILTIN_LANGUAGES`).
codebook-tree-sitter-latex = "0.6"
# Web grammars: HTML + CSS (`.html`/`.htm`/`.xhtml`, `.css`). The official
# tree-sitter-org grammars; both export `LANGUAGE` + query constants over
# `tree-sitter-language 0.1` (shared ABI crate, `tree-sitter` dev-only), so no
# overlay is needed. HTML's `INJECTIONS_QUERY` lights up `<script>` ->
# javascript (already registered) and `<style>` -> css via the #122 injection
# engine (see `crate::syntax::BUILTIN_LANGUAGES`).
tree-sitter-html = "0.23"
tree-sitter-css = "0.25"
# Lean 4 (`.lean`) — Arc 8 Stage 1 (`docs/lean4-mode-framing.md`, Q#LN1).
# `leanprover` ships no tree-sitter grammar (Lean parses with its own
# kernel), so both candidates are third-party. The obvious-looking
# `tree-sitter-lean4` is NOT usable: it depends on `tree-sitter = "0.25"`
# DIRECTLY rather than the shared `tree-sitter-language` ABI crate, which
# `^0.25` makes incompatible with our 0.26 and would fork the graph (the
# same defect that rules out `tree-sitter-dockerfile` above); it exports
# only `pub fn language()` while its README advertises a `LANGUAGE` const
# that does not exist; and its package `include` omits `queries/`, so it
# ships no highlights at all. `arborium-lean` is a republish from the
# arborium grammar collection that does it correctly: `tree-sitter-language
# 0.1` as its sole runtime dep, a pre-generated ABI-15 `parser.c` plus
# `scanner.c` (no CLI at build time), and `HIGHLIGHTS_QUERY` /
# `INJECTIONS_QUERY` / `LOCALS_QUERY` constants. Note the shape: it exports
# `const fn language() -> LanguageFn`, so the entry in
# `crate::syntax::BUILTIN_LANGUAGES` reads `arborium_lean::language().into()`
# rather than the `LANGUAGE.into()` every other entry uses.
arborium-lean = "2.18"
# T M4.4 process supervisor: signal sending without `unsafe`. Keep
# the feature surface tight to keep build time low. `poll` feeds the
# compile-mode group readers (cancellable poll-based reads, Q#CM3).
#
# `process` is listed explicitly even though it already arrives
# transitively: nix's own `signal` feature depends on it, so `getpgid`
# and `tcgetpgrp` compile today without being asked for. That is
# stable but invisible, and a real requirement that depends on another
# feature's internals is one refactor away from vanishing. The signal
# diagnostic calls both directly.
nix = { version = "0.29", default-features = false, features = ["signal", "user", "fs", "term", "socket", "poll", "process"] }
# T M4.4 PTY mode: portable abstraction over openpty / fork+exec
# with controlling-tty wiring. The crate uses internal `unsafe`
# but exposes a fully safe API; pmacs's own `unsafe_code = "forbid"`
# rule still holds.
portable-pty = "0.9"
# Safe file-descriptor duplication, already in the tree through
# `portable-pty`. Declared directly because the signal diagnostic calls
# `OwnedHandle::dup` itself: `MasterPty` exposes only a `RawFd`, and
# every std route from a raw fd to something implementing `AsFd` is
# `unsafe`. `dup` takes any `AsRawFd` through a safe blanket impl and
# returns an owned handle that IS `AsFd`, which is what lets pmacs call
# `nix::unistd::tcgetpgrp` — and keep the errno portable-pty discards —
# without a single `unsafe` block of its own.
filedescriptor = "0.8"
# T M4.5 LSP wire format: JSON-RPC 2.0 bodies inside Content-Length
# framing. Used only on LSP and similar protocols that require JSON
# specifically; in-process workers continue to use MessagePack
# (spec §5.2). `preserve_order` is off --- LSP doesn't require it
# and the default `BTreeMap` keeps allocation low.
serde_json = "1"
# T M7.1 package manifest format (spec §sec:packages-future): TOML at
# the package's root (`pmacs.toml`). Read at install time, not at every
# load.
toml = "0.8"
# T M7.1 semantic versioning for `version` and `pmacs_required` fields.
# `serde` feature gives us localized parse errors during deserialization
# (rejected at parse time, not at install time).
semver = { version = "1", features = ["serde"] }
# T M7.6 lockfile content-hashing. SHA-256 over `git archive --format=tar`
# bytes detects upstream tampering even when the host serves a SHA-1
# collision. Pure-Rust implementation; no system dep.
sha2 = "0.10"
# T M10.2 sequence CRDT for the v1.0 multi-frontend promotion. Selected
# in M10.1 (Decision section under spec §sec:m10-crdt-choice) on the
# basis of: per-op throughput dominance under realistic mixed-workload
# (190× faster than yrs at 30s window), ~100× more compact wire
# representation, stable v1.x API, and explicit spec mention. The pin
# is exact (`=1.12.0`) per the M10.1 commitment language: library
# updates are deliberate work (re-run M10.1 benchmarks, run convergence
# proptest, run acceptance suite), not Cargo background activity.
# Optional + feature-gated: zero footprint in v0.1 builds.
loro = { version = "=1.12.0", optional = true }
[dev-dependencies]
proptest = "1"
tempfile = "3"
# T M10.2 Day 7 perf bench (tests/m10_2_perf.rs) — seeded RNG plus
# log-normal op-size distribution matching the M10.1 methodology.
# Dev-only; not in release builds. rand 0.8 + edition 2024 requires
# `r#gen` for the (now-reserved) `gen` method name.
rand = "0.8"
rand_distr = "0.4"
[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 1
debug = "line-tables-only"
strip = "debuginfo"
[profile.bench]
opt-level = 3
lto = "thin"
codegen-units = 1
debug = "line-tables-only"