Editor for papermario-dx mods
Contributing#
Enter the dev shell with nix develop (or use direnv), then:
just run
Dependencies#
- Dependencies that could feasibly be used by multiple crates should go in the workspace
Cargo.toml. - When adding a new dependency, ensure it is up to date.
Formatting#
Run just fmt before committing. This formats code and adds
REUSE-compliant SPDX license headers to any new
files, using your git config user.name and git config user.email as the
copyright holder.
If you contribute to an existing file, you may add your own
SPDX-FileCopyrightText line alongside the existing one.
Style#
- Check your code against
just checkandjust test. - Try to follow the Rust API Guidelines Checklist.
- Write unit tests for all public functions containing business logic, data transformations, or state management. They go in a
#[cfg(test)] mod testsat the bottom of each file. GUI/rendering code does not require unit tests. - Write integration tests using
egui_kittestfor GUI code. Binary crates (likekammy) cannot use thetests/directory at the crate root because there is no library target to import. Instead, use asrc/tests.rsmodule gated behind#[cfg(test)], with submodules insrc/tests/organized by feature (e.g.src/tests/undo.rs). Shared test utilities go insrc/tests.rs. Library crates should use the standardtests/directory at the crate root. - Prefer module-level inner doc comments (
//!) at the top of a file over outer doc comments (///) on themoddeclaration. This keeps the documentation next to the code it describes. - Avoid just
#[expect]or#[allow]ing lines. The checks are there for a reason. For example,asshould usually be.into(), or.try_into()?.
Error handling#
- The code should only panic if there is a bug in the code. User input should never cause a panic.
- Use
thiserrorto validate user data and return errors. - Use
anyhowto attach context to errors as they bubble up the stack. - Never ignore an error: either pass it on, or log it.
- If a problem is recoverable, use
ka_log::warn!and recover. - UI code should never panic. Do not use
#[expect(clippy::expect_used)]etc. in UI code - warn and have a fallback.
Strive to encode code invariants and contracts in the type system as much as possible. Parse, don't validate. If you can't enforce a contract in the type system, enforce them using assert and in documentation (if its part of a public API).
Logging#
Use tracing, or, if a library isn't multithreaded, use log.
error!is for unrecoverable problems. The program couldn't complete an operation.- Libraries should ideally not log error, but instead return Err in a Result.
warn!is for when you recover from an error. The operation completed, but it couldn't do exactly what it was asked to do.- Sometimes an
Erris handled by logging it as a warning and then running some fallback code. - Warnings are also used for things that might be errors, but could be intended.
- If data is lost, it is an error and not a warning.
- Sometimes an
info!should be used by application code to write interesting and rare things to the user. For instance, you might log that a file was saved to a specific path.debug!is a level you opt-in to debug. These are logged when high-level, important operations are performed.trace!is a last resort and is mostly for spam. If it generates a lot of continuous logging (e.g.uifunction called every frame), it should go to trace.
Use debug formatting {:?} in logs.