diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..813c2ca --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,242 @@ +# Contributing to Modus + +Thanks for your interest in contributing to Modus! This guide covers everything you need to get started. + +## Table of Contents + +- [Prerequisites](#prerequisites) +- [Setup](#setup) +- [Project Structure](#project-structure) +- [Development Workflow](#development-workflow) +- [Code Style](#code-style) +- [Commit Messages](#commit-messages) +- [Pull Requests](#pull-requests) +- [Reporting Bugs](#reporting-bugs) +- [Requesting Features](#requesting-features) + +## Prerequisites + +- Arch Linux with [Hyprland](https://hyprland.org/) (Wayland compositor) +- Python 3.13+ +- [uv](https://docs.astral.sh/uv/) package manager +- [Meson](https://mesonbuild.com/) + Ninja (for C backends) +- GCC (for Global Menu shim) + +Install all dependencies: + +```bash +paru -S uv fabric-cli-git cliphist gnome-bluetooth-3.0 slurp ffmpeg hypridle hyprsunset hyprpicker hyprshot grim libnotify matugen-bin playerctl gtk-session-lock awww apple-fonts swappy wl-clipboard webp-pixbuf-loader wf-recorder acpi brightnessctl power-profiles-daemon uwsm cinnamon-desktop ddcutil at-spi2-core gcc make pkgconf appmenu-gtk-module libdbusmenu-gtk3 libdbusmenu-qt5 meson ninja wayland-protocols --needed +``` + +## Setup + +```bash +# Fork and clone +git clone https://github.com//Modus.git ~/.config/Modus +cd ~/.config/Modus + +# Install dependencies +uv sync + +# Compile App Switcher C backend +cd src/window/switcher/app-capture +meson setup builddir +meson compile -C builddir +cd ../../../.. + +# Compile Global Menu shim +cd src/globalmenu +gcc -shared -fPIC -O2 -o libmenu_button_shim.so libmenu_button_shim.c $(pkg-config --cflags --libs gtk+-3.0) -ldl +cd ../.. + +# Run +uv run start +``` + +## Project Structure + +``` +Modus/ +├── src/ +│ ├── main.py # App bootstrap +│ ├── services/ # System service monitors (DBus, signals) +│ ├── shared/ # Reusable widgets and base window classes +│ ├── utils/ # Utility modules +│ ├── window/ # All UI windows +│ │ ├── panel/ # Top bar +│ │ ├── dock/ # macOS-style dock +│ │ ├── controlcenter/ # Quick settings panel +│ │ ├── notification/ # Notification system +│ │ ├── switcher/ # Alt-Tab app switcher (C backend) +│ │ ├── spotlight/ # Super+D search (plugin system) +│ │ ├── osd/ # Volume/brightness on-screen display +│ │ ├── screencapture/ # Screen capture/recording +│ │ ├── desktop/ # Desktop widgets +│ │ ├── settings/ # Settings window +│ │ └── lock.py # Session lock screen +│ ├── globalmenu/ # macOS global menu bar +│ └── styles/ # GTK CSS stylesheets +├── config/ # User-facing config (TOML) +│ ├── config.toml # Main settings +│ ├── mods.toml # Custom panel buttons +│ ├── dock.toml # Pinned dock apps +│ └── plugins/ # User-installed spotlight plugins +├── examples/ # Example plugins +├── docs/ # Documentation +├── pyproject.toml # Project config + Ruff linting +└── start.py # Entry point +``` + +## Development Workflow + +1. **Create a branch** from `dev`: + ```bash + git checkout dev + git checkout -b feat/my-feature + ``` + +2. **Make your changes** and ensure they pass linting: + ```bash + # Lint + .venv/bin/ruff check + + # Auto-fix lint issues + .venv/bin/ruff check --fix + + # Format + .venv/bin/ruff format + + # Check formatting without changing files + .venv/bin/ruff format --check + ``` + +3. **Test your changes** by running the app: + ```bash + uv run start + ``` + +4. **Commit** with a descriptive message (see [Commit Messages](#commit-messages)). + +5. **Push** and open a Pull Request against `dev`. + +## Code Style + +Modus uses [Ruff](https://docs.astral.sh/ruff/) for both linting and formatting. The full config is in `pyproject.toml`. + +### Key Rules + +- **Formatter**: Double quotes, 4-space indentation, 88 char line length +- **Import sorting**: Grouped as stdlib / third-party / first-party, alphabetical within groups +- **Type hints**: Use `Optional[X]` and `typing.List`, `typing.Dict` style (not PEP 604 unions) +- **Logging**: Use `logger` from `fabric.utils`, not `print()` (except in CLI entry points) +- **Docstrings**: Not enforced, but encouraged for public APIs + +### Enforced via Ruff + +| Rule | What it catches | +|------|----------------| +| `E`, `W` | Pycodestyle style errors | +| `F` | Pyflakes (unused imports, undefined names) | +| `I` | Import sorting (isort) | +| `UP` | Python upgrade suggestions | +| `B` | Bugbear (common bugs) | +| `SIM` | Simplification suggestions | +| `C4` | Unnecessary comprehensions | +| `RET` | Return statement issues | +| `RUF` | Ruff-specific rules | +| `T20` | `print()` detection | + +### Running Ruff + +```bash +# Check for issues +.venv/bin/ruff check + +# Auto-fix safe issues +.venv/bin/ruff check --fix + +# Auto-fix including unsafe changes +.venv/bin/ruff check --fix --unsafe-fixes + +# Format all files +.venv/bin/ruff format + +# Check formatting (CI-friendly) +.venv/bin/ruff format --check +``` + +## Commit Messages + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +(): +``` + +### Types + +| Type | Use for | +|------|---------| +| `feat` | New feature | +| `fix` | Bug fix | +| `refactor` | Code restructuring without behavior change | +| `perf` | Performance improvement | +| `docs` | Documentation changes | +| `style` | Code style changes (formatting, no logic change) | +| `chore` | Build, CI, tooling, dependencies | +| `test` | Adding or updating tests | + +### Scopes + +Use the module name: `services`, `window`, `dock`, `panel`, `spotlight`, `notification`, `switcher`, `osd`, `config`, `docs`, etc. + +### Examples + +``` +feat(dock): add magnifier hover effect +fix(notification): prevent crash on empty body +refactor(services): extract battery polling to separate thread +docs: update installation guide for Arch Linux +style: enforce consistent codestyle via ruff config +``` + +### Rules + +- Use imperative mood: "add" not "added" or "adds" +- Keep subject line under 72 characters +- Reference issues when applicable: `Closes #42` +- Body is optional — use it only to explain **why**, not **what** + +## Pull Requests + +### Before Submitting + +- [ ] Code passes `ruff check` with no errors +- [ ] Code passes `ruff format --check` +- [ ] Changes are tested on a live Hyprland session +- [ ] Commit messages follow [Conventional Commits](#commit-messages) + +### PR Guidelines + +- Target the `dev` branch (not `main`) +- Keep PRs focused — one feature or fix per PR +- Write a clear description of what changed and why +- Include screenshots or screen recordings for UI changes +- Reference related issues + +## Reporting Bugs + +Open an issue with: + +1. **Description**: What happened vs. what you expected +2. **Steps to reproduce**: Exact commands or actions +3. **Environment**: OS, Hyprland version, Python version +4. **Logs**: Relevant output from terminal or journal + +## Requesting Features + +Open an issue with: + +1. **Use case**: What problem does this solve? +2. **Proposed solution**: How should it work? +3. **Alternatives considered**: Other approaches you thought about