Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/actions/setup-python/action.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
---
name: "Setup Python and uv"
description: "Setup Python and uv with caching"
runs:
using: "composite"
steps:
- name: Set up Python
uses: actions/setup-python@v6
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version-file: "pyproject.toml"
python-version-file: "pyproject.toml"
- name: Install uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
with:
enable-cache: auto
version: 0.9.*
enable-cache: auto
version: 0.9.*
- name: Install dependencies
shell: bash
run: uv sync --locked --all-extras --dev
Expand Down
21 changes: 16 additions & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
---
name: checks
on:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: ./.github/actions/setup-python
- run: |
uv run ruff check --fix
uv run ruff format
uv run ruff check --fix
uv run ruff format

typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: ./.github/actions/setup-python
- run: uv run ty check

vulture:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: ./.github/actions/setup-python
- run: uv run vulture --min-confidence 100 --exclude ".venv" .
35 changes: 24 additions & 11 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
name: pytest
on:
pull_request:
Expand All @@ -10,21 +11,33 @@ jobs:
pytest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: ./.github/actions/setup-python
- run: |
uv run pytest

# Browser/Playwright tests are excluded by default (pytest.ini) and run
# only on pull requests, where we install Chromium for them.
- name: Install Playwright browser
if: github.event_name == 'pull_request'
run: |
uv run playwright install --with-deps chromium
- name: Run browser tests
if: github.event_name == 'pull_request'
run: |
uv run pytest -m browser

- name: Run tests (with coverage)
shell: bash # adds pipefail so test failures survive the tee
run: |
uv run pytest \
--junitxml=pytest.xml \
--cov-report=term-missing:skip-covered \
--cov=. \
| tee pytest-coverage.txt
uv run pytest \
--junitxml=pytest.xml \
--cov-report=term-missing:skip-covered \
--cov=. \
| tee pytest-coverage.txt

- name: Pytest coverage comment
uses: MishaKav/pytest-coverage-comment@a01708271d42c5703d489b13eb503ba47c01e82a # main
uses: MishaKav/pytest-coverage-comment@dda025d84b1dd831193ed9cd5b1d7e33c79efa9b # v1.1.59
with:
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest.xml
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest.xml
9 changes: 9 additions & 0 deletions .pre-commit-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---

repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.4
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format
73 changes: 53 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ A simple tool to create and manage portable keyboard shortcut cheat sheets.

KoalaKeys generates and organizes portable, interactive HTML cheat sheets for keyboard shortcuts. It's designed for developers, designers, and power users who want to keep their essential shortcuts easily accessible.

> **Quick Start**: To create a cheat sheet, add a YAML file to the `cheatsheets` directory and run `python src/generate_cheatsheet.py`. For detailed YAML formatting instructions, see the [YAML Cheat Sheet Specification Guide](yaml_cheatsheet_spec.md).
> **Quick Start**: Run `uvx koalakeys init` to scaffold a project, `cd koalakeys`, add or edit YAML files in its `cheatsheets/` directory, then run `uvx koalakeys generate`. For detailed YAML formatting instructions, see the [YAML Cheat Sheet Specification Guide](yaml_cheatsheet_spec.md).

## Screenshots

Expand All @@ -25,6 +25,7 @@ KoalaKeys generates and organizes portable, interactive HTML cheat sheets for ke

- Generate HTML cheat sheets from YAML files
- Interactive keyboard layout with real-time highlighting
- Six built-in themes (catppuccin, dracula, gruvbox, nord, rosé-pine, solarized) plus user themes and custom CSS

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor · Functional Correctness · Quick win

🔎 Supported by static analysis

Script executed:

#!/bin/bash
# Check the built-in identifier and any normalisation in theme resolution.
rg -n -C 5 'rose-pine|rosé-pine|def resolve_theme|BUILTIN' \
  src/koalakeys/theming.py src/koalakeys/themes/rose-pine.yaml yaml_cheatsheet_spec.md

Repository: rtuszik/KoalaKeys

Length of output: 2261


Script executed:

#!/bin/bash
printf '%s\n' '--- resolver ---'
nl -ba src/koalakeys/theming.py | sed -n '186,225p'
printf '%s\n' '--- README ---'
nl -ba README.md | sed -n '24,32p'

Repository: rtuszik/KoalaKeys

Length of output: 2485


Use the accepted theme identifier.

The built-in identifier is rose-pine. Replace rosé-pine in the README.

Suggested fix
--- "a/README.md"
+++ "b/README.md"
@@ -25,7 +25,7 @@
 
 - Generate HTML cheat sheets from YAML files
 - Interactive keyboard layout with real-time highlighting
-- Six built-in themes (catppuccin, dracula, gruvbox, nord, rosé-pine, solarized) plus user themes and custom CSS
+- Six built-in themes (catppuccin, dracula, gruvbox, nord, rose-pine, solarized) plus user themes and custom CSS
 - Categorized shortcuts with descriptions
 - Index page for quick access to all cheat sheets
 - Search functionality
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Six built-in themes (catppuccin, dracula, gruvbox, nord, rosé-pine, solarized) plus user themes and custom CSS
- Six built-in themes (catppuccin, dracula, gruvbox, nord, rose-pine, solarized) plus user themes and custom CSS

- Categorized shortcuts with descriptions
- Index page for quick access to all cheat sheets
- Search functionality
Expand Down Expand Up @@ -58,42 +59,74 @@ Explore the demo to see how KoalaKeys works and to get ideas for creating custom

## Requirements

- Python 3.8+
- Python 3.9+
- [uv](https://docs.astral.sh/uv/)

## Installation

1. Clone the repository:
### Recommended: run as a tool (no clone)

```
git clone https://github.com/rtuszik/KoalaKeys
cd KoalaKeys
```
Run KoalaKeys directly with [uv](https://docs.astral.sh/uv/), no need to clone the repository:

```
uvx koalakeys init # scaffold ./koalakeys/cheatsheets/ with an example sheet
```

Or install it on your PATH:

2. Create and activate a virtual environment (optional):
```
uv tool install koalakeys # or: pipx install koalakeys
```

### From source (for development)

1. Clone the repository and install dependencies:

```
git clone https://github.com/rtuszik/KoalaKeys
cd KoalaKeys
uv sync --locked
```

3. Set up the output directory:
Create a `.env` file in the project root with:
```
CHEATSHEET_OUTPUT_DIR=path/to/your/output/directory
```
2. Run via `uv run koalakeys ...`.

## Usage

1. Create YAML files for your cheat sheets in the `cheatsheets` directory. For detailed instructions on how to format YAML files, please refer to the [YAML Cheat Sheet Specification Guide](yaml_cheatsheet_spec.md).
KoalaKeys is a multi-command CLI. All commands operate on the **current directory**: they read `cheatsheets/` and write to `output/` (or `CHEATSHEET_OUTPUT_DIR` if set).

2. Generate cheat sheets:
| Command | What it does |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `koalakeys init [path]` | Scaffold a new project directory with an example cheat sheet. Defaults to `./koalakeys`; use `.` for the current directory. Pass `--force` to overwrite existing files. |
| `koalakeys generate` | Generate HTML for every YAML file in `cheatsheets/`, plus an index page. |
| `koalakeys validate [file]` | Validate cheat sheet YAML. Checks all of `cheatsheets/` by default, or a single file. Exits non-zero on failure (CI-friendly). |

```
uv run src/generate_cheatsheet.py
```
Typical first run (with `koalakeys` on your PATH; otherwise prefix each command with `uvx`):

```
koalakeys init
cd koalakeys
koalakeys generate
```

Then open `output/index.html` to view the cheat sheet collection. For detailed YAML formatting, see the [YAML Cheat Sheet Specification Guide](yaml_cheatsheet_spec.md).

### Output directory (optional)

By default cheat sheets are written to `output/` in the current directory. To change this, set `CHEATSHEET_OUTPUT_DIR` (e.g. in a `.env` file):

```
CHEATSHEET_OUTPUT_DIR=path/to/your/output/directory
```

## Theming

Set a theme per cheat sheet with a single key:

3. Find the HTML cheat sheets in the specified output directory.
```yaml
theme: dracula
```

4. Open `index.html` to view the cheat sheet collection.
See the [YAML Cheat Sheet Specification Guide](yaml_cheatsheet_spec.md) for the built-in themes, user-theme authoring, and custom CSS.

## Schema

Expand Down
Binary file modified assets/images/KoalaKeys_Example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions docs/schema/cheatsheet.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@
"default": false,
"description": "When true, free-form shortcut text is allowed; requires RenderKeys=false."
},
"theme": {
"type": "string",
"minLength": 1,
"default": "catppuccin",
"description": "Theme name: a built-in (e.g. 'catppuccin') or a user theme in the project's themes/ directory. Defaults to 'catppuccin'."
},
"custom_css": {
"type": "string",
"description": "Filename of a custom CSS file (resolved from the project's styles/ directory), layered after the theme."
},
"custom_css_inline": {
"type": "string",
"description": "Inline custom CSS, emitted last in the cascade so it overrides the theme and the custom CSS file."
},
"layout": {
"type": "object",
"additionalProperties": false,
Expand Down
6 changes: 6 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[tools]
prek = "latest"
uv = "latest"

[settings]
lockfile = false
37 changes: 32 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
[project]
name = "koalakeys"
version = "0.6.0"
version = "1.0.0"
description = "Build interactive, portable cheatsheets from YAML."
readme = "README.md"
requires-python = ">=3.9"
dependencies = ["jinja2>=3.1.6", "python-dotenv>=1.1.1", "ruamel-yaml>=0.18.14"]

[project.scripts]
koalakeys = "koalakeys.cli:run"

[dependency-groups]
dev = [
"bandit>=1.8.6",
"prek>=0.3.6",
"pytest>=8.4.2",
"pytest-cov>=7.0.0",
"pytest-cov>=7.1.0",
"pytest-playwright>=0.7.1",
"ruff>=0.14.0",
"ty>=0.0.1a22",
"vulture>=2.14",
]

[build-system]
requires = ["uv_build>=0.10.9,<0.11.0"]
build-backend = "uv_build"

[tool.coverage.run]
omit = ["tests/*"]

[tool.ruff]
indent-width = 4
line-length = 120

[tool.ruff.lint]
# select = ["ALL"]
ignore = [
"ANN", # flake8-annotations
"COM", # flake8-commas
"C90", # mccabe complexity
"DJ", # django
"EXE", # flake8-executable
"BLE", # blind except
Expand All @@ -52,6 +61,24 @@ ignore = [
"TRY",
"SIM105", # faster without contextlib
]
extend-select = [
"F", # Pyflakes rules
"W", # PyCodeStyle warnings
"E", # PyCodeStyle errors
"I", # Sort imports properly
"UP", # Warn if certain things can changed due to newer Python versions
"C4", # Catch incorrect use of comprehensions, dict, list, etc
"FA", # Enforce from __future__ import annotations
"ISC", # Good use of string concatenation
"ICN", # Use common import conventions
"RET", # Good return practices
"SIM", # Common simplification rules
"TID", # Some good import practices
"TC", # Enforce importing certain types in a TYPE_CHECKING block
"PTH", # Use pathlib instead of os.path
"TD", # Be diligent with TODO comments
"C90",
]
fixable = ["ALL"]
unfixable = []
# Allow unused variables when underscore-prefixed.
Expand Down
5 changes: 4 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts =
addopts =
-v
--tb=short
--strict-markers
--disable-warnings
-m "not browser"
markers =
browser: browser-based Playwright tests

File renamed without changes.
Loading
Loading