6.2 KiB
6.2 KiB
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(insrc/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 andAppApimust 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 anAppApiinstance passed in) instead of mutatingWorkspace,PanelState,KeyMap, orLspManagerdirectly. - Methods that are implementation details of
AppApistay 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 AppApiblock annotated with#[mlua::userdata_impl]is automatically exposed asapp:method(...). - When adding functionality, add it to
AppApiand 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 returnmlua::Result/ convert errors tomlua::Error::RuntimeErrorotherwise. - 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 exampleactive_tab_index→active_tab). - Lua API naming: lower
snake_case, tabs and indices are zero-based, panels are accessed asapp.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
AppApimethods, not manipulate state directly. Examples:- window close button →
app:close()(i.e.AppApi::close) - minimize button →
app:minimize() - maximize / restore →
app:toggle_maximize()orapp:set_maximized(bool); read the current state withapp:is_maximized() - tab close button →
app:close_tab(index) - "new tab" button →
app:open_tab() - panel toggles →
app.right_panel:toggle()and friends
- window close button →
- Rendering code may read state (for example
workspace.borrow()to draw the active document), but must not mutate it. Mutations belong toAppApi. - Window operations are queued as
WindowCommands and applied byapply_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 callsAppApi.
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_shortcutandis_completion_shortcutinsrc/app.rsare technical debt: when touching this area, move those defaults into theKeyMapmechanism 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_keymapis used for both key down and key up (<...>vs!key). Preserve this behavior. - Any
KeyMapchange 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
AppApiorPanelApimethods; - changed arguments, return values, or error behavior;
- new supported languages, LSP configuration fields, CLI flags, or
include/requirebehavior; - 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 fmtandcargo test, thencargo buildif 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
AppApimethod. DOCS.md(andinit.luacomments if needed) are updated.cargo fmtandcargo testpass (or explain why they could not run).