diff options
Diffstat (limited to 'docs/handbook/mnv/code-style.md')
| -rw-r--r-- | docs/handbook/mnv/code-style.md | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/docs/handbook/mnv/code-style.md b/docs/handbook/mnv/code-style.md new file mode 100644 index 0000000000..f80412f09b --- /dev/null +++ b/docs/handbook/mnv/code-style.md @@ -0,0 +1,408 @@ +# MNV — Code Style + +## Overview + +MNV follows a distinctive coding style inherited from the Vi/Vim tradition. +The style is partially documented in `.clang-format` and `.editorconfig` at +the project root, and largely defined by example in the existing codebase. + +--- + +## Indentation and Whitespace + +### `.editorconfig` rules + +```ini +[*] +indent_style = tab +tab_width = 8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{c,h,proto}] +indent_size = 4 + +[*.{md,yml,sh,bat}] +indent_style = space +indent_size = 2 + +[*.mnv] +indent_style = space +indent_size = 2 +``` + +Key takeaways: + +- **C/H files use hard tabs** with `tabstop=8`, `shiftwidth=4`. +- **Script files (`.mnv`) use spaces** with indent 2. +- **Markdown, YAML, shell scripts use spaces** with indent 2. + +This matches the modeline at the top of every source file: + +```c +/* vi:set ts=8 sts=4 sw=4 noet: */ +``` + +Meaning: +- `ts=8` — tab stop at 8 columns. +- `sts=4` — soft tab stop, making tabs appear 4 columns wide for editing. +- `sw=4` — shift width is 4. +- `noet` — do NOT expand tabs to spaces. + +### `.clang-format` configuration + +The `.clang-format` file specifies detailed formatting rules: + +```yaml +Language: Cpp +IndentWidth: 8 +TabWidth: 8 +UseTab: Always +ColumnLimit: 0 +BreakBeforeBraces: Allman +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: Align +``` + +Note: `clang-format` is available as a reference but is **not universally +applied** — the codebase still relies heavily on manual formatting. + +--- + +## File Headers + +Every `.c` and `.h` file begins with: + +```c +/* vi:set ts=8 sts=4 sw=4 noet: + * + * MNV - MNV is not Vim by Bram Moolenaar + * + * Do ":help uganda" in MNV to read copying and usage conditions. + * Do ":help credits" in MNV to see a list of people who contributed. + * See README.txt for an overview of the MNV source code. + */ +``` + +The first line is a **modeline** that configures the editor for the correct +whitespace settings. Every source file must have this. + +--- + +## Function Definition Style + +MNV uses a distinctive **K&R-like but separated** function definition style. +The return type and qualifiers go on the line **above** the function name, +which starts at column 4 (one tab indent): + +```c + static void +gui_check_pos(void) +{ + ... +} +``` + +```c + int +vwl_connection_flush(vwl_connection_T *self) +{ + ... +} +``` + +Public functions similarly: + +```c + void +gui_start(char_u *arg UNUSED) +{ + ... +} +``` + +Rules: +- Return type and storage class on its own line, indented by one tab (4 visual + columns). +- Function name starts at column 0. +- Opening brace on its own line at column 0 (Allman style). +- Parameter list may wrap with alignment. + +### Static function declarations + +Forward declarations follow the same pattern: + +```c +static void gui_check_pos(void); +static void gui_reset_scroll_region(void); +static int gui_screenchar(int off, int flags, guicolor_T fg, guicolor_T bg, int back); +``` + +--- + +## Variable Declarations + +Local variables are declared at the top of a function, before any statements. +This is required for C89 compatibility (though MNV uses C99): + +```c + void +gui_start(char_u *arg UNUSED) +{ + char_u *old_term; +#ifdef GUI_MAY_FORK + static int recursive = 0; +#endif + + old_term = mnv_strsave(T_NAME); + ... +} +``` + +Alignment of variable names to the same column (using tabs) is common: + +```c + int ret; + char_u *buf; + long lnum; + pos_T pos; +``` + +--- + +## Comments + +### Block comments + +Use `/* ... */` style. Never `//` for multi-line comments: + +```c +/* + * This is a block comment explaining the next function. + * Multiple lines follow the same pattern. + */ +``` + +### Inline comments + +Single-line comments use `//`: + +```c +static int has_dash_c_arg = FALSE; // whether -c was given +``` + +This is a newer convention; older code uses `/* */` even for inline comments. + +### Section headers + +Major sections within a file are marked with comment banners: + +```c +/* + * Different types of error messages. + */ +``` + +In the CMake file, section headers use hash-line banners: + +```cmake +############################################################################### +# Build options +############################################################################### +``` + +--- + +## Naming Conventions + +### Functions + +- Core functions: `lowercase_with_underscores` — e.g., `gui_start()`, + `command_line_scan()`, `enter_buffer()`. +- Machine-specific functions: `mch_` prefix — e.g., `mch_early_init()`, + `mch_exit()`. +- GUI backend functions: `gui_mch_` prefix — e.g., `gui_mch_flush()`. +- Wayland functions: `vwl_` for abstractions, `wayland_` for global + connection — e.g., `vwl_connection_flush()`, `vwl_connection_dispatch()`. +- MNV9 functions: `mnv9_` prefix — e.g., `in_mnv9script()`. +- Test functions: named after what they test, e.g., `json_test`, `kword_test`. + +### Types + +- Struct typedefs end with `_T`: `buf_T`, `win_T`, `pos_T`, `typval_T`, + `garray_T`, `gui_T`, `mparm_T`, `cellattr_T`, `vwl_connection_T`. +- Internal struct tags use `_S` suffix: `struct vwl_seat_S`, + `struct vwl_connection_S`, `struct terminal_S`. +- Enum values: `UPPERCASE_SNAKE_CASE` — e.g., `VWL_DATA_PROTOCOL_NONE`, + `EDIT_FILE`, `ME_UNKNOWN_OPTION`. + +### Macros + +- All uppercase: `FEAT_GUI`, `HAVE_CONFIG_H`, `UNUSED`, `EXTERN`, `INIT()`. +- Feature guards: `FEAT_` prefix (`FEAT_TERMINAL`, `FEAT_EVAL`, + `FEAT_WAYLAND`). +- Detection results: `HAVE_` prefix (`HAVE_STDINT_H`, `HAVE_SELECT`, + `HAVE_DLOPEN`). +- Dynamic library names: `DYNAMIC_` prefix (`DYNAMIC_LUA_DLL`). + +### Global variables + +Declared in `globals.h` with the `EXTERN` macro: + +```c +EXTERN long Rows; +EXTERN long Columns INIT(= 80); +EXTERN schar_T *ScreenLines INIT(= NULL); +``` + +The `INIT(x)` macro expands to `= x` in `main.c` and to nothing elsewhere. + +--- + +## Preprocessor Conventions + +### Feature guards + +MNV uses `#ifdef FEAT_*` extensively. Feature code is wrapped tightly: + +```c +#ifdef FEAT_FOLDING +EXTERN foldinfo_T win_foldinfo; +#endif +``` + +Functions that only exist with certain features use `#ifdef` blocks: + +```c +#if defined(FEAT_GUI_TABLINE) +static int gui_has_tabline(void); +#endif +``` + +### Platform guards + +```c +#ifdef MSWIN + // Windows-specific code +#endif + +#ifdef UNIX + // Unix-specific code +#endif + +#if defined(MACOS_X) + // macOS +#endif +``` + +### N_() for translatable strings + +User-visible strings are wrapped in `N_()` for gettext extraction: + +```c +N_("Unknown option argument"), +N_("Too many edit arguments"), +``` + +--- + +## Typedef Conventions + +Commonly used types: + +```c +typedef unsigned char char_u; // unsigned character +typedef signed char int8_T; // signed 8-bit +typedef double float_T; // floating point +typedef long linenr_T; // line number +typedef int colnr_T; // column number +typedef unsigned short short_u; // unsigned short +``` + +The custom `char_u` type is used instead of `char` throughout the codebase to +avoid signed-char bugs. + +--- + +## Error Handling Patterns + +### Error message functions + +| Function | Use | +|---|---| +| `emsg()` | Display error message | +| `semsg()` | Formatted error (like `sprintf` + `emsg`) | +| `iemsg()` | Internal error (bug in MNV) | +| `msg()` | Informational message | +| `smsg()` | Formatted informational message | + +### Return conventions + +- Many functions return `OK` / `FAIL` (defined as `1` / `0`). +- Pointer-returning functions return `NULL` on failure. +- Boolean functions return `TRUE` / `FALSE`. + +--- + +## MNV9 Script Style + +For `.mnv` files (MNV9 syntax): + +- Indent with 2 spaces (per `.editorconfig`). +- Use `def`/`enddef` instead of `function`/`endfunction`. +- Type annotations: `var name: type = value`. +- Use `#` for comments (not `"`). + +--- + +## Guard Macros in Headers + +Headers use traditional include guards: + +```c +#ifndef MNV__H +#define MNV__H +... +#endif +``` + +```c +#ifndef _OPTION_H_ +#define _OPTION_H_ +... +#endif +``` + +--- + +## Test Code Style + +Test files (`*_test.c`) follow the same style as production code. Tests in +`src/testdir/` are MNVscript files following the `.mnv` indent style (2 spaces). + +The CI enforces code style via `test_codestyle.mnv` — contributions must pass +this check. + +--- + +## Summary of Key Rules + +| Aspect | Rule | +|---|---| +| Tabs vs spaces in C | Hard tabs, `tabstop=8`, `shiftwidth=4` | +| Tabs vs spaces in .mnv | Spaces, indent 2 | +| Function definition | Return type on separate line, indented one tab | +| Braces | Allman style (opening brace on new line) | +| Variable declarations | Top of function, before statements | +| Naming | `lowercase_underscores` for functions, `_T` suffix for types | +| Feature guards | `#ifdef FEAT_*` | +| Translatable strings | `N_("...")` | +| Modeline | Required in every `.c` / `.h` file | +| Prototype generation | `src/proto/*.pro` files | + +--- + +*This document describes MNV 10.0 as of build 287 (2026-04-03).* |
