nageyqma·git
HTTPS https://git.nageyqma.icu/nageyqma/wm.git SSH git@git.nageyqma.icu:nageyqma/wm.git

HTTPS 链接可直接 git clone;推送代码请使用 SSH。

7.0 KB · 147 行raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
# AGENT.md

This is a local fork of [dwl](https://github.com/djpohly/dwl), the wlroots port
of [dwm](https://dwm.suckless.org/). The owner is customizing it step by step.
The tree started from upstream; every change after that is deliberately a small
layer, not a rewrite.

Read this before editing. If a rule below conflicts with generic "good
engineering" advice, this file wins. The background is
[suckless philosophy](https://suckless.org/philosophy/) and
[suckless coding style](https://suckless.org/coding_style/).

## The project's bar

Two properties matter more than features:

1. **Small.** A line that is not necessary is a line the owner must read and
   maintain forever. Prefer no code to a little code, and a config value to a
   new function.
2. **Readable.** A stranger who knows C and dwm should understand a change in
   one pass. A clever abstraction that saves repetition but costs a jump is a
   regression here.

The bar is native: `drawbar()` renders it into a pixman image. The
system-information text is read from `$XDG_RUNTIME_DIR/dwl-status`, written by
`~/scripts/status.sh`; tmux reads the compact `$XDG_RUNTIME_DIR/tmux-status`
written by the same script, and starts the script when dwl is not running. Do
not replace it with an external bar program.

The practical consequences:

- Configuration belongs in `config.h`. If a behavior can be selected there,
  implement it there, not as a runtime option.
- Reuse what dwl/wlroots already provides: `spawn`, `SHCMD`, `Arg`, `LISTEN`,
  listeners, wlroots helpers. Do not build a second mechanism beside one that
  already exists.
- No new dependencies beyond the bar (`fcft`, `pixman`), no new source
  files, no build-system layers, no generated code, no configuration parser,
  no IPC, no plugin system, no runtime reload, no animation framework.
- Do not generalize for a hypothetical future request. The owner will ask for
  the next feature when they want it.
- Prefer deleting a special case to adding a flag. Prefer one fixed path to a
  search path. Prefer one command to two blocking/non-blocking variants.
- A change that touches unrelated lines is wrong even if it looks "cleaner".
  Reformatting, sorting, and include churn are not welcome.

## How to approach a request

1. Read the relevant code, `config.def.h`, `config.h`, and the man page first.
   Search for an existing hook before designing one.
2. Choose the smallest lever, in this order: a `config.h` constant, a call to
   an existing function, a small helper, a new file (almost never).
3. Check the side effects: environment (`WAYLAND_DISPLAY`,
   `XDG_RUNTIME_DIR`), child processes and shutdown, focus and keyboard
   groups, multi-monitor, XWayland, and the status output.
4. Write the diff in the surrounding style. It should be hard to tell your hunk
   from upstream code.
5. Build. Do not restart the live session. Report what you verified and what
   you did not.

A worked example from this tree: the dwm autostart patch searches three XDG
directories, supports two script names, and distinguishes blocking from
background startup. The actual requirement was "run one known script once".
The small solution is one `SHCMD` entry in `config.h` plus one `spawn()` call
in `run()`; `/bin/sh` already reports a missing script.

## C style

Match the file. In practice that means:

- Tabs for indentation, spaces for alignment; keep lines near the surrounding
  width.
- Function return type on its own line, name on the next, opening brace on the
  next line. Control-flow braces on the same line.
- Declarations before statements (`-Wdeclaration-after-statement` is on).
- `/* ... */` comments, lowercase names, `static` for file-local functions,
  forward declarations near the top, `ecalloc`/`die` as the rest of dwl uses
  them.
- No new compiler warnings. Do not silence warnings with casts or pragmas when
  the code can simply be written correctly.
- Do not run `clang-format`, sort includes, reorder keybindings, or re-align
  existing tables. Touch only the lines the change needs.
- Comments explain *why*, not *what*. Do not narrate the code.

## config.h and config.def.h

`config.h` is the owner's live, git-ignored config. `config.def.h` is the
tracked default. They are edited separately and intentionally differ: the
owner's tag order is not the default order. Never copy one over the other.

When a change is a new default, add it to both files. When it is only the
owner's preference, leave `config.def.h` alone.

Do not touch the owner's existing keybindings, tag order, monitor rules, DRM
device list, or mouse settings while doing an unrelated change. In particular,
the keyboard layout is US Colemak with `caps:escape`; the key table was
deliberately left alone. dwl matches keysyms, so a binding follows the letter,
not the physical QWERTY position. That is intended.

`Arg autostartcmd` and the `spawn(&autostartcmd)` call in `run()` are the
whole autostart implementation. Keep it that way: one command, one path, no
directory search, and no blocking/non-blocking pair. There is no `-s` command
line option; do not reintroduce one.

## Local invariants

- Build against wlroots 0.20 (`config.mk`). Do not migrate, downgrade, or
  adopt `wlroots-next` APIs without an explicit request.
- The compositor's startup environment is not this repository's business. Do
  not add display-manager, systemd, or login-session integration.
- The live desktop belongs to the owner. This agent does not restart, log out
  of, or reconfigure it to test code.

## Build and verify

- `make` is the only build step. Keep it clean.
- Never run `make -B`: the `config.h:` target has no prerequisites, so `-B`
  forces `cp config.def.h config.h` and overwrites the owner's live,
  git-ignored config. Use plain `make` or `make clean && make`; to force a
  rebuild, remove `dwl` or touch `dwl.c`.
- Compile-time checks are the default. Run `git diff` before reporting.
- Do not start, stop, or restart dwl, KDE, the display manager, or the owner's
  session to test a change. The owner will test it.
- A headless smoke test is acceptable when it cannot touch the real session:
  `WLR_BACKENDS=headless`, a temporary `HOME`, a temporary
  `XDG_RUNTIME_DIR`, and a fake autostart script that only writes a marker.
  Clean up afterwards. Never run the real `~/scripts/autostart-dwl.sh`
  against a throwaway compositor.
- Do not install packages, edit system config, or change the running
  environment.

## Git and reporting

- Do not commit unless asked. Do not amend, rebase, force-push, or touch
  unrelated branches.
- `config.h`, `patches/`, build products, and generated protocol headers are
  ignored; do not "fix" that.
- Report in the language the owner used. Include the files changed, the reason
  for the smallest design, what was built and tested, and what was not tested.
  Do not claim a live-session test you did not perform.
- If you had to make a tradeoff, say it plainly. Do not hide it in a
  changelog entry.

This file is not a changelog. Update it only when the working rules change.

When in doubt, do less, keep the diff obvious, and report the tradeoff.