summaryrefslogtreecommitdiff
path: root/docs/handbook/mnv/code-style.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/handbook/mnv/code-style.md')
-rw-r--r--docs/handbook/mnv/code-style.md408
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).*