~kris/suckless

dwm

ref: 9ba6c8e751a1bf236b6e3f0839121d78a4a940f7 dwm/.claude/CLAUDE.md -rw-r--r-- 6.9 KiB
9ba6c8e7 — Kris Yotam Rebind reading mode to Super+Q, add directional tagmondir, enable selfrestart 7 months ago

#DWM - Development Rules

#Build System: dwm-flexipatch

This is a flexipatch build. Patches are toggled via #define flags, NOT by applying .diff files.

#Critical File Hierarchy

File Role Committed?
config.def.h Source of truth for all configuration YES
patches.def.h Source of truth for patch enable/disable flags YES
config.h Local working copy (generated from config.def.h) NO (gitignored)
patches.h Local working copy (generated from patches.def.h) NO (gitignored)
config.mk Compiler/linker flags, library paths YES
dwm.c Core window manager (includes config.h at line 878) YES
patch/*.c patch/*.h Patch implementations and headers YES
patch/include.c patch/include.h Conditional patch includes (do NOT edit by hand) YES

#Rules for Editing Configuration

  1. ALWAYS edit config.def.h for keybindings, layouts, rules, colors, and custom functions.
  2. ALWAYS edit patches.def.h to enable/disable patches (#define PATCH_NAME 0 or 1).
  3. ALSO update config.h and patches.h to match, so local builds work without regenerating.
  4. NEVER edit only config.h or patches.h — those are gitignored and will be lost.
  5. When config.h does not exist, make generates it by copying config.def.h. Same for patches.h.

#Build & Deploy Process

Local build (this desktop):

cd /home/krisyotam/dev/dwm
sudo make clean install

Deploy to laptop (khr1st):

# 1. Commit and push from desktop
cd /home/krisyotam/dev/dwm
git add config.def.h patches.def.h
git commit -m "description"
git push

# 2. SSH to laptop, pull, rebuild
ssh khr1st
cd ~/.local/src/dwm && git pull && sudo make clean install

# 3. Self-restart dwm (preserves all windows — no session kill)
# Trigger via sysact menu or a keybinding mapped to self_restart

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.


#Code Style (Suckless C Conventions)

#Formatting

  • Indentation: Tabs (width 8). Never spaces for indentation.
  • Brace style: K&R — opening brace on same line, closing at column 0.
  • Line length: ~80 characters preferred, not strictly enforced.
  • No trailing whitespace.

#Naming

  • CamelCase for types and structs: Client, Monitor, Layout, Key, Button
  • lowercase or lowercasemultiword for functions: focusmon, tagmon, sendmon, killclient
  • UPPERCASE for macros and constants: MODKEY, NUMTAGS, CLEANMASK, SHCMD
  • Enum values: SchemeNorm, SchemeSel, NetSupported

#Functions

static void
functionname(const Arg *arg)
{
	/* body indented with tabs */
}
  • Return type on its own line.
  • Function name on the next line.
  • Opening brace on its own line (for function definitions only — NOT for if/for/while).
  • Minimize variable declarations; declare at top of scope.

#Comments

  • /* C89-style block comments */ preferred in source.
  • // C99 inline comments acceptable in config files for brief annotations.
  • Preprocessor guards: #endif // PATCH_NAME

#Conditional Compilation (Patch Guards)

#if SOME_PATCH
/* patch-specific code */
#endif // SOME_PATCH
  • Always include the patch name in the #endif comment.
  • Custom (non-patch) code added to config.def.h does NOT need guards.

#Example: Adding a Custom Function in config.def.h

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.


#Layout Array Reference

The layout array uses flextile-deluxe. Index matters for keybindings.

Index Symbol Layout Notes
0 []= Tile Default
1 ><> Floating
2 [M] Monocle
3 ||| Columns
4 >M> Floating master
5 [D] Deck
6 TTT Bottom stack
7 === Bottom stack horiz
8 |M| Centered master
9 -M- Centered master horiz
10 ::: Gappless grid
11 [\\] Fibonacci dwindle
12 (@) Fibonacci spiral
13 [T] Tatami mats
14 RRR Reading mode (3 vertical panes) Custom: nmaster=3

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.


#Currently Enabled Patches

Patches set to 1 in patches.def.h:

Bar: BAR_DWMBLOCKS, BAR_LTSYMBOL, BAR_STATUS, BAR_STATUSCMD, BAR_TAGS, BAR_WINTITLE, BAR_HIDEVACANTTAGS

Core: CFACTS, COOL_AUTOSTART, CYCLELAYOUTS, PERTAG, RESTARTSIG, SCRATCHPADS, SEAMLESS_RESTART, SELFRESTART, SHIFTTAG, SHIFTVIEW, STACKER, STICKY, SWALLOW, TOGGLEFULLSCREEN, VANITYGAPS, XRESOURCES

Layouts: BSTACK, CENTEREDMASTER, CENTEREDFLOATINGMASTER, COLUMNS, DECK, FIBONACCI_DWINDLE, FIBONACCI_SPIRAL, NROWGRID, TILE, MONOCLE


#Current Custom Keybindings

Binding Action
Super+Q Reading mode (RRR layout)
Super+Shift+Q Kill client (close window)
Super+Backspace sysact (system actions menu)
Super+Left/Right/Up/Down Send window to monitor in that direction
Super+Comma/Period Focus previous/next monitor
Super+T Tile layout
Super+F Floating layout

#Rules for Making Changes

  1. Read before writing. Always read the relevant section of config.def.h before modifying it. Understand the surrounding #if guards.
  2. Count layout indices. Never assume a layout index. Count from 0 in the layouts[] array every time.
  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.
  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.
  5. Keep both files in sync. Every edit to config.def.h must also be applied to config.h (and vice versa for patches).
  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.
  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/.
  8. Do not modify patch/include.c or patch/include.h unless adding a completely new patch file to the patch/ directory.
  9. Commit messages: Imperative mood, concise. Example: "Rebind reading mode to Super+Q, add directional tagmon". No "Co-Authored-By" lines.