From: Christian Brabandt Date: Sun, 26 Apr 2026 08:07:18 +0000 (+0000) Subject: No guidance for AI coding agents X-Git-Tag: v9.2.0394~2 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=1de887681d278c8add0d28fbac1fe06642aa7d85;p=thirdparty%2Fvim.git No guidance for AI coding agents Problem: No guidance for AI coding agents working in the Vim repository. Solution: Add AGENTS.md to the repository documenting build and test commands, repository layout, commit format, C and Vim9-script conventions, test conventions, help file style, and release policy, so that AI agents can produce patches that match project expectations. closes: #20039 Signed-off-by: Christian Brabandt --- diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..291c07900b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,325 @@ +# AGENTS.md + +Guidance for AI coding agents working in the Vim repository. + +## Project + +Vim is a text editor written in C. The canonical repository is +https://github.com/vim/vim. The code is old and has grown organically over +the past 30+ years. Some files are vendored from upstream projects +(`src/xdiff`, `src/libvterm`); parts of the runtime are occasionally shared +with forks like Neovim. + +Vim strives to be portable across several different operating systems and +aims to be a stable, robust editor gradually developing new features while +remaining backwards compatible as much as possible. + +At the same time, Vim can be compiled with different feature sets, from the +POSIX compatible minimal vi to a full-fledged GUI editor which includes +additional scripting interfaces. + +See `runtime/doc/develop.txt` for the high level design goals. + +## Build and test + + # Full build on Unix/Linux (from src/): + make + + # Run the full test suite: + make test + + # Generate proto files + make proto + + # Run a single test file: + cd src/testdir && make test_name.res + +Output is in testdir/messages and testdir/test.log + +Builds on Windows depend on the Environment, see `src/INSTALLpc.txt` +for Cygwin/MSYS and MSVC ways to build Vim + +Before submitting any patch, at minimum: +1. The build succeeds without new warnings. +2. Relevant tests pass. +3. The code matches the style of the file being edited. + +## Layout + +- `src/` - the C source. Subsystem names are usually obvious from filenames + (`buffer.c`, `window.c`, `search.c`, `vim9compile.c`, etc.). +- `src/proto/` - function prototypes, one `.pro` file per source file. + Regenerated; do not hand-edit unless you know what you're doing. +- `src/po` - Translations +- `src/xxd` - for the xxd subproject +- `src/xdiff` - for the xdiff library (imported from git) +- `src/libvterm` - for the libvterm library +- `src/testdir/` - tests. Vim-script files named `test_*.vim`. + Screendump expected output lives in `src/testdir/dumps/`. +- `runtime/doc/` - user-facing documentation in Vim help format, when updating, + also update the Last Change header +- `runtime/syntax/generator` - Syntax script for Vim Script, automatically generated + from Vims source +- `runtime/` - runtime files shipped with Vim, when updating, also update the + Last Change header and a short description if this file has no maintainer + If the file has a maintainer, changes should go via them (so make a merge + request against the upstream repo instead) +- `src/version.c` - contains the `included_patches[]` list. Every + patch touching anything below `src/` (with the exception of `src/po`) needs a + new entry at the top, will be updated only when merging into + the master tree. + +## Commit format + +Vim uses a strict commit message format. The subject line is a +one-sentence **problem statement**, not a description of the fix: + + patch 9.2.NNNN: short description of the problem + + Problem: Restatement of the problem as a full sentence, possibly + with a reporter attribution in parentheses. + Solution: Short description of the fix, ending with the author's + name in parentheses. + + optional longer description of the problem and solution goes here in prose. + Do not use bullet points. + + fixes: #NNNN + related: #NNNN + closes: #NNNN + + Co-authored-by: Name + Signed-off-by: Author Name + +Rules: + +- **Subject line states the problem**, not the solution. "fix typo" is + wrong; "typo in foo() causes OOB read" is right. +- **Problem line is a full sentence with a trailing period.** It mirrors + the subject. +- **Solution line ends with `(Author Name)`** — parentheses, period + after them. +- **Longer prose**, if any, goes after the Problem/Solution header +- **`fixes:` references the issue** the patch fixes. + **`closes:` references the PR** that introduces the fix. + **`related:` references related issues**, including issues that caused this + one. + All can appear. Colon, aligned, no trailing period. +- **`Signed-off-by:` is required** — DCO. +- **`Co-Authored-By:` is allowed** and is the accepted way to + acknowledge AI assistance transparently. Human + coauthors should usually also have their own Signed-off-by. + +## C code conventions + +- **Indentation is 4 spaces per level.** Existing files use tabs with + `ts=8 sts=4 sw=4 noet` (set by the modeline in the file), + so tabs of width 8 appear where two levels of indent collapse. `sign.c`, + `sound.c`, and any new file must use spaces only and follow the style from + the .editorconfig file. +- **Opening braces go on their own line (Allman style)** — for function + definitions and for control-flow constructs (`if`/`else`/`for`/`while`/ + `do`) alike. +- **Function definitions**: return type on its own indented line, with + the function name beginning on the next line. +- Initialize locals where a reader cannot trivially see the first + assignment (common for pointers and return-value accumulators). + Don't add `= 0` initializers for values that are always assigned + before use — they can hide real uninitialized-read bugs from + the compiler. +- `for (int i = 0; ...)` loop declarations are fine in files that + use them; older files may declare the counter at the top of the + block. +- **Function-scope declarations at the top of a block** is the historical + style, but mid-block declarations are acceptable in files that have + adopted them. Match the surrounding code. +- **Custom types end in `_T`** (e.g., `buf_T`, `linenr_T`, `pos_T`). + Never use `_t` — it collides with POSIX typedefs. +- **C language is C95 plus specific C99 features**: `//` comments, + mixed declarations and statements, `__func__`, `bool`/`_Bool`, + variadic macros, compound literals, `static inline`, trailing enum + commas. Do not reach for later C standards — Vim still must build + with Compaq C on OpenVMS. See `*assumptions-C-compiler*` in + `develop.txt` for the full list. +- **`bool` / `true` / `false` are acceptable.** Vim is transitioning + from `int` with `TRUE`/`FALSE` to C99 `bool`. Do not "fix" `bool` + back to `int`. Within a single patch, be consistent — don't mix + `true` and `TRUE` in new code. +- **Do not mass-convert** `TRUE`/`FALSE` to `true`/`false` across files + unless that is the patch's explicit purpose. Opportunistic + conversions create noise in diffs. +- **`STRLEN_LITERAL("...")`** should be used when the length of a + string literal is needed. Avoid `STRLEN()` on literals. +- **`vim_snprintf_safelen()`** returns the written length; prefer it + over `vim_snprintf()` when the length is then needed. +- **Prefer `dict_add_string_len()`** when the string length is already + known, over `dict_add_string()` which calls `STRLEN()`. +- **String/buffer parameters go `(char_u *buf, size_t buflen)`** — + length alongside pointer, in bytes. Use `size_t` for byte counts, + `int` only where required by legacy APIs. +- **Guards before divisions.** Check for divisor zero explicitly, even + when a composite earlier guard would prevent it. Relying on + transitive guards is fragile. +- When introducing new allocations, verify the cleanup paths handle all exit + conditions (early return, error branches, etc). + +**Use Vim wrappers instead of libc where one exists:** + +| libc | Vim | Why | +|---------------|------------------------|-----------------------------| +| `free()` | `vim_free()` | Tolerates NULL | +| `malloc()` | `alloc()` / `lalloc()` | Checks for OOM | +| `strcpy()` | `STRCPY()` | Cast for `char_u *` | +| `strchr()` | `vim_strchr()` | Handles special characters | +| `strrchr()` | `vim_strrchr()` | Handles special characters | +| `memcpy()` | `mch_memmove()` | Handles overlapping copies | +| `bcopy()` | `mch_memmove()` | Handles overlapping copies | +| `memset()` | `vim_memset()` | Uniform across systems | +| `isspace()` | `vim_isspace()` | Handles bytes > 127 | +| `iswhite()` | `vim_iswhite()` | TRUE only for tab and space | + +Further rules, not spelled out here, live in `runtime/doc/develop.txt`: + +- `*style-names*` — reserved name patterns (`is*`, `to*`, `str*`, `mem*`, + `wcs*`, `.*_t`, `__.*`), forbidden identifiers (`delete`, `this`, `new`, + `time`, `index`), and the 31-character function-name limit. +- `*style-spaces*`, `*style-examples*` — spacing and one-statement-per-line. +- `*style-various*` — `FEAT_` feature prefix, uppercase `#define`, + `#ifdef HAVE_X` rather than `#if HAVE_X`, no `'\"'`. +- `*assumptions-makefiles*` — POSIX.1-2001 `make` only in the main + Makefiles (no `%` rules, `:=`, `.ONESHELL`, GNU conditionals). +- Vim uses `char_u` instead of `char` type +- Vim uses the macros `STRLEN`, `STRCPY`, `STRCMP`, `STRCAT` that work + with the `char_u` type. +- `*style-clang-format*` — `sign.c` and `sound.c` are formatted with + `clang-format`; re-run it after editing those files. + +## Vim9 script conventions (in tests and runtime files) + +- Write modern Vim style (new files can use Vim9 script, but compatibility + with Neovim and other forks is a concern, so in doubt please ask!) +- **Drop `l:` prefix from local variables** in Vim-script tests. +- **Don't add `CheckFeature` inside individual tests** if it's already + at the top of the file. +- If a test file doesn't gate features at the top, add CheckFeature to + individual tests that depend on specific build features. + +## Test conventions + +- Tests are in `src/testdir/test_*.vim`. +- Reproducible tests beat "it doesn't crash" tests. If a patch fixes + a rendering bug, add a screendump test. If it fixes incorrect output, + assert the output. +- Add comprehensive tests for newly added features and include them + in existing tests if possible +- **Screendump tests** use `CheckScreendump`, `RunVimInTerminal`, + `VerifyScreenDump`, and live dumps in `src/testdir/dumps/`. +- `v9.CheckScriptSuccess(lines)` / `v9.CheckScriptFailure(lines, error, lnum)` + are the standard way to test Vim9 script behavior at script-load time. +- When fixing a bug reported as an issue, include a test that + reproduces the original report, not just a minimal synthetic case. +- Tests for Syntax runtime are in `runtime/syntax/testdir` +- Tests for Indent runtime are in `runtime/indent/testdir` + +## Common gotchas + +- **Distinguish what code enforces from what docs claim.** If a patch + changes documented behavior, say so in the Problem/Solution. +- **Generated files** (`src/auto/configure`, generated Wayland protocol + C, etc.) should only be regenerated when their source changes. + Mixing unrelated regeneration into a functional patch creates noise. + +## Documentation + +- User-facing option or feature changes require a `runtime/doc/*.txt` + update in the same patch. +- When editing an existing help file, bump the `Last change:` header + at the top. + +### Help file style + +See `runtime/doc/helphelp.txt` (`*help-writing*`) for the authoritative +reference. Key conventions: + +- **File header**: first line is `*filename.txt*` then a tab then a + short description. That description appears under `LOCAL ADDITIONS` + in `help.txt`. The version and `Last change:` date go on the second + line, right aligned. +- **Modeline**: every help file ends with a Vim modeline — typically + `vim:tw=78:ts=8:noet:ft=help:norl:`. +- **Layout**: `'textwidth'` 78, `'tabstop'` 8, indent and align with + tab characters. Two spaces between sentences. Run `:retab` + (not `:retab!`, and review the diff) after editing. +- **Tags** are defined as `*tag-name*`, usually right-aligned on the + line where the thing they name is introduced. Tag names must be + unique across all of `runtime/doc/`; for plugin help, prefix with + the plugin name. +- **Cross-references inside help text**: + - `|tag-name|` — hot-link to an existing tag. + - `` `:cmd` `` — Ex command, highlighted as a code block. + - `'option'` — option name, in single quotes. + - `` or `CTRL-X` — special keys. + - `{placeholder}` — user-supplied argument. +- **Sections** are separated by a line of `=` starting in column 1. + Column or subsection headings end with `~` to trigger heading + highlighting. +- **Code blocks** start with `>` at the end of the introducing line + and end with `<` as the first non-blank on a later line (any line + starting in column 1 also implicitly closes the block). Use `>vim` + (or another language name) to request syntax highlighting inside + the block. +- **Notation** — `Note`, `Todo`, `Error` and a few similar words are + auto-highlighted; do not try to fake the highlighting by other means. +- **Language**: gender-neutral language is preferred for new or updated + text; existing wording does not need to be rewritten for this alone. + +## Release policy + +Vim alternates between development cycles and stability periods — see +`runtime/doc/develop.txt` `*design-policy*`. + +- **During a stability period** only clear bug fixes, security fixes, + documentation updates, translations, and runtime file updates are + accepted. No new features, no backwards-incompatible changes. +- **Once released in a minor version**, C-core features must stay + backwards-compatible. Runtime files have a bit more flexibility so + their maintainers can correct old behavior. +- **Deprecated features** stay reachable via config (do not hard-error), + are documented as deprecated, can be disabled at compile time, and + may be removed in a later cycle. + +## Security + +Before reporting a suspected security issue or submitting a patch +that touches security-sensitive code, read `SECURITY.md`. Follow +the disclosure process described there. + +## Before submitting + +1. Commit message follows the format above. +2. All modified code compiles without new warnings. +3. Tests pass, and new functionality has regression tests. +4. Documentation is updated for user-visible changes. +5. Signed-off-by is present. +6. Diff contains only changes relevant to the stated problem — + no stray whitespace fixes, no unrelated refactors, no unrelated + regeneration of `auto/configure`. +7. For multi-patch series: each commit compiles and passes its own + tests. A known-broken intermediate state that a later patch fixes + is not acceptable — squash instead. + +## When in doubt + +- Make the smallest possible change to achieve the goal. Do not rewrite + entire files or functions when a targeted edit suffices. +- Read surrounding code and match its style rather than imposing an + "improvement." +- Err toward smaller, more focused patches. A patch that does three + things is three patches. +- If a patch fixes a symptom of a deeper bug, say so in the Problem + and acknowledge the scope limitation in the Solution. +- Before claiming a bug exists, reproduce it. Before claiming code does X, read + the code. Do not rely on training-data memory of file contents. +- Before running shell commands that modify files outside the working tree, + install packages, push branches, or invoke network operations, confirm with + the user. diff --git a/Filelist b/Filelist index 4832028577..311a1031af 100644 --- a/Filelist +++ b/Filelist @@ -1198,6 +1198,7 @@ IGNORE = \ .github/FUNDING.yml \ .github/labeler.yml \ .github/workflows/label.yml \ + AGENTS.md \ SECURITY.md \ ci/unlisted.make \ ci/hlgroups.make \