129 lines
6.2 KiB
Markdown
129 lines
6.2 KiB
Markdown
# AGENTS.md
|
|
|
|
Instructions for AI coding agents working on this repository. Read this file
|
|
before changing code. The rules below are architectural requirements, not
|
|
suggestions.
|
|
|
|
## Project shape
|
|
|
|
| Path | Responsibility |
|
|
| --- | --- |
|
|
| `src/api.rs` | `AppApi` / `PanelApi` — the single control surface of the application |
|
|
| `src/script.rs` | Lua engine; publishes `app`, `include`, and `require` |
|
|
| `src/keymap.rs` | Key binding parsing (`KeyBinding`) and dispatch (`KeyMap`) |
|
|
| `src/app.rs` | GPUI view, rendering, event wiring |
|
|
| `src/editor.rs` | `Workspace`, documents, tabs |
|
|
| `src/panel.rs` | `PanelState` for left/right/bottom panels |
|
|
| `src/lsp.rs` | LSP server manager |
|
|
| `src/constants.rs` | CLI arguments and script directory |
|
|
| `init.lua` | Example startup script (also a usage reference) |
|
|
| `DOCS.md` | User-facing Lua API documentation |
|
|
|
|
## 1. `AppApi` is the center of the application
|
|
|
|
- `AppApi` (in `src/api.rs`) is the one object through which the application is
|
|
controlled. All operations on documents, tabs, panels, the window, syntax
|
|
highlighting, key bindings, and LSP go through it.
|
|
- Shared state is held as `Rc<RefCell<_>>` handles (workspace, keymap, panels,
|
|
LSP manager). The UI and `AppApi` must observe the *same* instances; never
|
|
create a second copy of the state.
|
|
- Rust code that needs to act on the application should call
|
|
`AppApi::global()` (or an `AppApi` instance passed in) instead of mutating
|
|
`Workspace`, `PanelState`, `KeyMap`, or `LspManager` directly.
|
|
- Methods that are implementation details of `AppApi` stay private or are
|
|
marked `#[lua(skip)]`. Do not add a second, parallel control path.
|
|
|
|
## 2. Every `AppApi` capability is available from Lua
|
|
|
|
- Everything in the `impl AppApi` block annotated with
|
|
`#[mlua::userdata_impl]` is automatically exposed as `app:method(...)`.
|
|
- When adding functionality, add it to `AppApi` and expose it to Lua at the same
|
|
time. An operation that a user can trigger in the UI must also be callable
|
|
from a Lua script.
|
|
- Use `#[lua(infallible)]` where the method cannot fail, and return
|
|
`mlua::Result` / convert errors to `mlua::Error::RuntimeError` otherwise.
|
|
- Generic Rust methods are not exported. Add a thin non-generic Lua wrapper,
|
|
following the existing pattern: `save` / `lua_save`, `open` / `lua_open`,
|
|
`set_active_text` / `lua_set_active_text`, `set_language` /
|
|
`lua_set_language`.
|
|
- Use `#[lua(name = "...")]` when the Lua name should differ from the Rust
|
|
name (for example `active_tab_index` → `active_tab`).
|
|
- Lua API naming: lower `snake_case`, tabs and indices are zero-based, panels
|
|
are accessed as `app.left_panel`, `app.right_panel`, `app.bottom_panel`.
|
|
|
|
## 3. All UI actions and keyboard shortcuts go through the API
|
|
|
|
### UI actions
|
|
|
|
- UI event handlers and rendered controls must invoke `AppApi` methods, not
|
|
manipulate state directly. Examples:
|
|
- window close button → `app:close()` (i.e. `AppApi::close`)
|
|
- minimize button → `app:minimize()`
|
|
- maximize / restore → `app:toggle_maximize()` or
|
|
`app:set_maximized(bool)`; read the current state with `app:is_maximized()`
|
|
- tab close button → `app:close_tab(index)`
|
|
- "new tab" button → `app:open_tab()`
|
|
- panel toggles → `app.right_panel:toggle()` and friends
|
|
- Rendering code may *read* state (for example `workspace.borrow()` to draw the
|
|
active document), but must not mutate it. Mutations belong to `AppApi`.
|
|
- Window operations are queued as `WindowCommand`s and applied by
|
|
`apply_window_commands`; keep this mechanism as the only way the UI and Lua
|
|
request window changes.
|
|
- If an external component (for example `gpui_kit::component::TitleBar`)
|
|
performs an action internally, do not leave it as a separate control path:
|
|
intercept the action or replace the component so that it calls `AppApi`.
|
|
|
|
### Keyboard shortcuts
|
|
|
|
- Every key binding must be registered through `AppApi::map_key` /
|
|
`KeyMap`. There must be no hard-coded shortcuts that scripts cannot inspect,
|
|
override, or remove.
|
|
- Existing hard-coded checks such as `is_save_shortcut` and
|
|
`is_completion_shortcut` in `src/app.rs` are technical debt: when touching
|
|
this area, move those defaults into the `KeyMap` mechanism so they can be
|
|
rebound from Lua.
|
|
- Default bindings should be installed through the same mechanism that scripts
|
|
use (or a documented equivalent), so that `app:map_key(...)` can replace them.
|
|
Rebinding the same chord must replace the previous handler.
|
|
- Dispatch order matters: the key interceptor runs before key bindings, and
|
|
`dispatch_keymap` is used for both key down and key up (`<...>` vs `!key`).
|
|
Preserve this behavior.
|
|
- Any `KeyMap` change must keep the documented chord syntax working:
|
|
`a`, `1`, `!a`, `<S-c>`, `<C-z>`, `<A-!r>`, named keys (case-insensitive).
|
|
- Editor text input itself is not a shortcut, but all app-level commands
|
|
(save, close, panels, completion popup navigation, etc.) must be remappable.
|
|
|
|
## 4. Keep `DOCS.md` in sync
|
|
|
|
`DOCS.md` is the source of truth for the Lua API. In the **same change** that
|
|
modifies the public surface, update the docs:
|
|
|
|
- added/removed/renamed `AppApi` or `PanelApi` methods;
|
|
- changed arguments, return values, or error behavior;
|
|
- new supported languages, LSP configuration fields, CLI flags, or
|
|
`include`/`require` behavior;
|
|
- changed default shortcuts or their syntax.
|
|
|
|
Also update the usage comments in `init.lua` when they describe behavior that
|
|
changed. Documentation must describe the code as it actually behaves — no
|
|
aspirational APIs.
|
|
|
|
## Conventions
|
|
|
|
- Keep changes focused and consistent with the existing style; comments and
|
|
user-facing documentation are written in Russian.
|
|
- Rust API docs use `///`; write them for every new public method.
|
|
- Validate with `cargo fmt` and `cargo test`, then `cargo build` if behavior
|
|
changed. Do not commit unless explicitly asked.
|
|
|
|
## Checklist
|
|
|
|
Before finishing a change, verify:
|
|
|
|
- [ ] The new behavior is implemented in `AppApi`, not in a UI handler.
|
|
- [ ] The operation is callable from Lua and has a documented signature.
|
|
- [ ] No new hard-coded keyboard shortcut bypasses `KeyMap`.
|
|
- [ ] UI controls call the corresponding `AppApi` method.
|
|
- [ ] `DOCS.md` (and `init.lua` comments if needed) are updated.
|
|
- [ ] `cargo fmt` and `cargo test` pass (or explain why they could not run).
|