CLAUDE.md (10671B)
1 # DWM - Development Rules 2 3 ## Build System: dwm-flexipatch 4 5 This is a **flexipatch** build. Patches are toggled via `#define` flags, NOT by applying `.diff` files. 6 7 ### Critical File Hierarchy 8 9 | File | Role | Committed? | 10 |------|------|------------| 11 | `config.def.h` | **Source of truth** for all configuration | YES | 12 | `patches.def.h` | **Source of truth** for patch enable/disable flags | YES | 13 | `config.h` | Local working copy (generated from `config.def.h`) | NO (gitignored) | 14 | `patches.h` | Local working copy (generated from `patches.def.h`) | NO (gitignored) | 15 | `config.mk` | Compiler/linker flags, library paths | YES | 16 | `dwm.c` | Core window manager (includes config.h at line 878) | YES | 17 | `patch/*.c` `patch/*.h` | Patch implementations and headers | YES | 18 | `patch/include.c` `patch/include.h` | Conditional patch includes (do NOT edit by hand) | YES | 19 20 ### Rules for Editing Configuration 21 22 1. **ALWAYS edit `config.def.h`** for keybindings, layouts, rules, colors, and custom functions. 23 2. **ALWAYS edit `patches.def.h`** to enable/disable patches (`#define PATCH_NAME 0` or `1`). 24 3. **ALSO update `config.h` and `patches.h`** to match, so local builds work without regenerating. 25 4. **NEVER edit only `config.h` or `patches.h`** — those are gitignored and will be lost. 26 5. When `config.h` does not exist, `make` generates it by copying `config.def.h`. Same for `patches.h`. 27 28 ### Build & Deploy Process 29 30 **Local build (this desktop):** 31 ```bash 32 cd /home/krisyotam/dev/dwm 33 sudo make clean install 34 ``` 35 36 **Deploy to laptop (khr1st):** 37 ```bash 38 # 1. Commit and push from desktop 39 cd /home/krisyotam/dev/dwm 40 git add config.def.h patches.def.h 41 git commit -m "description" 42 git push 43 44 # 2. SSH to laptop, pull, rebuild 45 ssh khr1st 46 cd ~/.local/src/dwm && git pull && sudo make clean install 47 48 # 3. Self-restart dwm (preserves all windows — no session kill) 49 # Trigger via sysact menu or a keybinding mapped to self_restart 50 ``` 51 52 **NEVER** tell the user to "restart dwm" or "log out and back in" without mentioning self_restart. The SELFRESTART_PATCH is enabled and does an in-place `execv()` that preserves all window positions. 53 54 --- 55 56 ## Suckless Coding Style 57 58 Reference: https://suckless.org/coding_style/ 59 60 The following are guidelines. The most important aspect of style is **consistency**. 61 62 Recommended reading: 63 - https://man.openbsd.org/style 64 - http://doc.cat-v.org/bell_labs/pikestyle 65 - https://www.kernel.org/doc/Documentation/process/coding-style.rst 66 67 ### File Layout 68 69 Organize files in this order: 70 71 1. Comment with LICENSE and file/tool explanation 72 2. Headers 73 3. Macros 74 4. Types 75 5. Function declarations (include variable names; group logically) 76 6. Global variables 77 7. Function definitions matching declaration order 78 8. `main` 79 80 ### C Features 81 82 - Use **C99 without extensions** (ISO/IEC 9899:1999). 83 - Use **POSIX.1-2008**: define `_POSIX_C_SOURCE 200809L` or `_XOPEN_SOURCE 700`. 84 - **Do not mix declarations and code.** 85 - **Do not use for loop initial declarations** (e.g., `for (int i = 0; ...)`). 86 - Use `/* */` for comments, **not `//`**. 87 - Variadic macros are acceptable but be cautious with `__VA_ARGS__`. 88 89 ### Blocks 90 91 - All variable declarations at the **top of the block**. 92 - `{` on the same line, preceded by a single space (except for function definitions). 93 - `}` on its own line unless continuing a statement (`} else {`). 94 95 Use blocks for single statements only when the inner statement needs blocks: 96 ```c 97 for (;;) { 98 if (foo) { 99 bar; 100 baz; 101 } 102 } 103 ``` 104 105 Use blocks when any branch requires them: 106 ```c 107 if (foo) { 108 bar; 109 } else { 110 baz; 111 qux; 112 } 113 ``` 114 115 ### Leading Whitespace 116 117 - Use **tabs for indentation** and **spaces for alignment**. 118 - No tabs except at the beginning of a line. 119 - Use **spaces** (not tabs) for multiline macros, as the indentation level is 0. 120 121 ### Functions 122 123 - Return type and modifiers on a **separate line**. 124 - Function name and argument list on the next line. 125 - Opening `{` on its **own line** (function definitions only). 126 - Functions not used outside the translation unit must be `static`. 127 128 ```c 129 static void 130 usage(void) 131 { 132 eprintf("usage: %s [file ...]\n", argv0); 133 } 134 ``` 135 136 ### Variables 137 138 - Global variables not used outside the translation unit must be `static`. 139 - In pointer declarations, `*` is adjacent to the **variable name**, not the type: 140 ```c 141 char *p; /* correct */ 142 char* p; /* wrong */ 143 ``` 144 145 ### Keywords 146 147 - Use a **space after** `if`, `for`, `while`, `switch` (they are not function calls). 148 - **No space** after `(` or before `)`. 149 - Preferably use `()` with `sizeof`. 150 - **No space** with `sizeof()`: 151 ```c 152 sizeof(int) /* correct */ 153 sizeof (int) /* wrong */ 154 ``` 155 156 ### Switch Statements 157 158 - **Do not indent cases** another level. 159 - **Comment cases that fall through.** 160 161 ```c 162 switch (value) { 163 case 0: /* FALLTHROUGH */ 164 case 1: 165 case 2: 166 break; 167 default: 168 break; 169 } 170 ``` 171 172 ### Headers 173 174 - Place **system/libc headers first**, in alphabetical order. 175 - Add comments if a specific inclusion order is required. 176 - Place **local headers after an empty line**. 177 - Avoid cyclic dependencies; include headers only where needed. 178 179 ### User Defined Types 180 181 - **Do not use `type_t` naming** (reserved for POSIX, less readable). 182 - Typedef opaque structs. 183 - **Do not typedef builtin types.** 184 - Use **`CamelCase`** for typedef'd types. 185 186 ### Line Length 187 188 Keep lines to a reasonable length: **max 79 characters**. 189 190 ### Tests and Boolean Values 191 192 - **Do not use C99 `bool`** types. Stick to integer types. 193 - Use compound assignment and tests unless lines grow too long: 194 ```c 195 if (!(p = malloc(sizeof(*p)))) 196 hcf(); 197 ``` 198 199 ### Error Handling 200 201 - When functions return `-1` for error, **test against `0`**, not `-1`: 202 ```c 203 if (func() < 0) 204 hcf(); 205 ``` 206 - Use `goto` to unwind and cleanup when necessary, instead of multiple nested levels. 207 - `return` or `exit` early on failures instead of deeply nesting. 208 - Unreachable code should have a `/* NOTREACHED */` comment. 209 - For fatal errors in one-shot programs, memory freeing may be skipped, but temporary files should be cleaned. 210 211 ### Enums and #define 212 213 Use enums for semantically grouped values. Use `#define` otherwise: 214 ```c 215 #define MAXSZ 4096 216 #define MAGIC1 0xdeadbeef 217 218 enum { 219 DIRECTION_X, 220 DIRECTION_Y, 221 DIRECTION_Z 222 }; 223 ``` 224 225 --- 226 227 ## DWM-Specific Conventions 228 229 ### Naming in dwm 230 231 - `CamelCase` for types and structs: `Client`, `Monitor`, `Layout`, `Key`, `Button` 232 - `lowercase` or `lowercasemultiword` for functions: `focusmon`, `tagmon`, `sendmon`, `killclient` 233 - `UPPERCASE` for macros and constants: `MODKEY`, `NUMTAGS`, `CLEANMASK`, `SHCMD` 234 - Enum values: `SchemeNorm`, `SchemeSel`, `NetSupported` 235 236 ### Comments in Config Files 237 238 - `/* C89-style block comments */` in `.c` source files (mandatory per suckless style). 239 - `// C99 inline comments` are acceptable in `config.def.h` for brief binding annotations only. 240 - Preprocessor guards: `#endif // PATCH_NAME` 241 242 ### Conditional Compilation (Patch Guards) 243 244 ```c 245 #if SOME_PATCH 246 /* patch-specific code */ 247 #endif // SOME_PATCH 248 ``` 249 - Always include the patch name in the `#endif` comment. 250 - Custom (non-patch) code added to `config.def.h` does NOT need guards. 251 252 ### Adding a Custom Function in config.def.h 253 254 Custom functions go **before** the `static const Key keys[]` array. They can reference any forward-declared function from `dwm.c` (`sendmon`, `focusmon`, `arrange`, `focus`, `selmon`, `mons`, etc.) because `config.h` is included after all declarations in `dwm.c` (line 878). 255 256 --- 257 258 ## Layout Array Reference 259 260 The layout array uses **flextile-deluxe**. Index matters for keybindings. 261 262 | Index | Symbol | Layout | Notes | 263 |-------|--------|--------|-------| 264 | 0 | `[]=` | Tile | Default | 265 | 1 | `><>` | Floating | | 266 | 2 | `[M]` | Monocle | | 267 | 3 | `\|\|\|` | Columns | | 268 | 4 | `>M>` | Floating master | | 269 | 5 | `[D]` | Deck | | 270 | 6 | `TTT` | Bottom stack | | 271 | 7 | `===` | Bottom stack horiz | | 272 | 8 | `\|M\|` | Centered master | | 273 | 9 | `-M-` | Centered master horiz | | 274 | 10 | `:::` | Gappless grid | | 275 | 11 | `[\\]` | Fibonacci dwindle | | 276 | 12 | `(@)` | Fibonacci spiral | | 277 | 13 | `[T]` | Tatami mats | | 278 | 14 | `RRR` | Reading mode (3 vertical panes) | Custom: nmaster=3 | 279 280 **When referencing layouts in keybindings, ALWAYS verify the index by counting from 0 in the `layouts[]` array.** Off-by-one errors here cause the wrong layout to activate with no obvious error. 281 282 --- 283 284 ## Currently Enabled Patches 285 286 Patches set to `1` in `patches.def.h`: 287 288 **Bar:** BAR_DWMBLOCKS, BAR_LTSYMBOL, BAR_STATUS, BAR_STATUSCMD, BAR_TAGS, BAR_WINTITLE, BAR_HIDEVACANTTAGS 289 290 **Core:** CFACTS, COOL_AUTOSTART, CYCLELAYOUTS, PERTAG, RESTARTSIG, SCRATCHPADS, SEAMLESS_RESTART, SELFRESTART, SHIFTTAG, SHIFTVIEW, STACKER, STICKY, SWALLOW, TOGGLEFULLSCREEN, VANITYGAPS, XRESOURCES 291 292 **Layouts:** BSTACK, CENTEREDMASTER, CENTEREDFLOATINGMASTER, COLUMNS, DECK, FIBONACCI_DWINDLE, FIBONACCI_SPIRAL, NROWGRID, TILE, MONOCLE 293 294 --- 295 296 ## Current Custom Keybindings 297 298 | Binding | Action | 299 |---------|--------| 300 | Super+Q | Reading mode (RRR layout) | 301 | Super+Shift+Q | Kill client (close window) | 302 | Super+Backspace | sysact (system actions menu) | 303 | Super+Left/Right/Up/Down | Send window to monitor in that direction | 304 | Super+Comma/Period | Focus previous/next monitor | 305 | Super+T | Tile layout | 306 | Super+F | Floating layout | 307 308 --- 309 310 ## Rules for Making Changes 311 312 1. **Read before writing.** Always read the relevant section of `config.def.h` before modifying it. Understand the surrounding `#if` guards. 313 2. **Count layout indices.** Never assume a layout index. Count from 0 in the `layouts[]` array every time. 314 3. **Check for keybinding conflicts.** Before adding a new binding, grep for the key symbol (e.g., `XK_w`) across `config.def.h` to find all uses and check which patches guard them. 315 4. **Test compilation.** Clang diagnostics on `config.h` standalone are ALWAYS false positives (missing types like `Arg`, `Client`, `Monitor`). The only valid test is `make` in the repo root. 316 5. **Keep both files in sync.** Every edit to `config.def.h` must also be applied to `config.h` (and vice versa for patches). 317 6. **Preserve removed bindings as comments.** When removing a keybinding, comment it out with a `// removed: reason` note rather than deleting the line, so the history is visible. 318 7. **Do not modify `dwm.c` unless absolutely necessary.** Configuration belongs in `config.def.h`. New functions go in `config.def.h` (before the keys array) or as a new file in `patch/`. 319 8. **Do not modify `patch/include.c` or `patch/include.h`** unless adding a completely new patch file to the `patch/` directory. 320 9. **Commit messages:** Imperative mood, concise. Example: `"Rebind reading mode to Super+Q, add directional tagmon"`. No "Co-Authored-By" lines.