diff --git a/docs/_static/custom.css b/docs/_static/custom.css
new file mode 100644
index 0000000..860d680
--- /dev/null
+++ b/docs/_static/custom.css
@@ -0,0 +1,113 @@
+/* Furo centers the layout: on wide screens the sidebar drawer spans the whole
+ left half and right-justifies its content against the text column, leaving a
+ wide margin on the far left. Pin it to a fixed width, flush against the left
+ edge of the window, for a conventional left-sidebar layout. */
+.sidebar-drawer {
+ width: 20em;
+ justify-content: flex-start;
+}
+
+/* The inner container is hardcoded to 15em in Furo; widen it to match the
+ drawer so the brand, search box and nav tree fill the extra space. */
+.sidebar-container {
+ width: 20em;
+}
+
+/* Roomier horizontal padding for the whole sidebar (brand, captions, links). */
+body {
+ --sidebar-item-spacing-horizontal: 1rem;
+}
+
+/* Center the brand block (logo + project name) so it lines up with the
+ centered GitHub button below it. Furo only adds its own `.centered` class
+ for a text logo, not for an image logo. */
+.sidebar-brand {
+ align-items: center;
+ text-align: center;
+}
+
+/* Smaller logo (Furo lets it grow to the full sidebar width by default). */
+.sidebar-logo {
+ max-width: 6em;
+}
+
+/* Furo keeps a few purple accents that don't follow the brand colour:
+ visited links and the generic admonition-title accent. Point them at the
+ teal brand colour in every theme mode (explicit light/dark + auto). */
+body {
+ --color-brand-visited: var(--color-brand-content);
+ --color-admonition-title: var(--color-brand-content);
+}
+@media not print {
+ body[data-theme="dark"] {
+ --color-brand-visited: var(--color-brand-content);
+ --color-admonition-title: var(--color-brand-content);
+ }
+ @media (prefers-color-scheme: dark) {
+ body:not([data-theme="light"]) {
+ --color-brand-visited: var(--color-brand-content);
+ --color-admonition-title: var(--color-brand-content);
+ }
+ }
+}
+
+/* Pygments (light theme): retint the purple keyword tokens to the teal accent.
+ Dark-theme keywords are already green, so they have no purple to fix. */
+.highlight .k,
+.highlight .kc,
+.highlight .kd,
+.highlight .kn,
+.highlight .kp,
+.highlight .kr,
+.highlight .ne,
+.highlight .ow {
+ color: #0d9488;
+}
+
+/* "Why use it?" feature grid on the landing page: add horizontal breathing
+ room between the three columns without overflowing (border-box keeps the
+ 33% widths intact), and zero out the outer edges. */
+.feature-grid td {
+ box-sizing: border-box;
+ padding: 0 1.25rem;
+ /* Shrink the cell text; the `h3` headings use `em`, so the title and body
+ scale down together proportionally. */
+ font-size: 0.85rem;
+}
+.feature-grid td:first-child {
+ padding-left: 0;
+}
+.feature-grid td:last-child {
+ padding-right: 0;
+}
+
+/* Persistent GitHub call-to-action in the sidebar, under the project name. */
+.sidebar-github-cta {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5rem;
+ margin: 0.75rem 1rem 0.25rem;
+ padding: 0.5rem 0.75rem;
+ border: 1px solid var(--color-background-border);
+ border-radius: 0.5rem;
+ color: var(--color-sidebar-link-text);
+ font-size: 0.85rem;
+ font-weight: 600;
+ line-height: 1;
+ text-decoration: none;
+ transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
+}
+
+.sidebar-github-cta:hover,
+.sidebar-github-cta:focus-visible {
+ background: var(--color-background-hover);
+ border-color: var(--color-foreground-border);
+ color: var(--color-sidebar-link-text);
+}
+
+.sidebar-github-cta svg {
+ width: 1.15em;
+ height: 1.15em;
+ flex-shrink: 0;
+}
diff --git a/docs/_templates/sidebar/brand.html b/docs/_templates/sidebar/brand.html
new file mode 100644
index 0000000..992f1f6
--- /dev/null
+++ b/docs/_templates/sidebar/brand.html
@@ -0,0 +1,26 @@
+{#- Furo's default brand, plus a persistent GitHub call-to-action pinned
+ directly under the project name so it's visible from every page. -#}
+
+ {%- block brand_content %}
+ {%- if logo_url %}
+
+ {%- endif %}
+ {% if not theme_sidebar_hide_name %}
+ {{ docstitle if docstitle else project }}
+ {%- endif %}
+ {% endblock brand_content %}
+
+
+
+ View on GitHub
+
diff --git a/docs/api/enums.md b/docs/api/enums.md
index 9a2ac9a..cb77890 100644
--- a/docs/api/enums.md
+++ b/docs/api/enums.md
@@ -2,7 +2,12 @@
## `ScanTypesEnum`
-Comparison modes for `search_by_value` and `search_by_value_between`.
+```{eval-rst}
+.. py:class:: ScanTypesEnum
+
+ Comparison modes for :py:meth:`search_by_value` and
+ :py:meth:`search_by_value_between`.
+```
```python
from PyMemoryEditor import ScanTypesEnum
@@ -36,6 +41,13 @@ with OpenProcess(process_name="game.exe") as process:
## `ProcessOperationsEnum` (Windows only)
+```{eval-rst}
+.. py:class:: ProcessOperationsEnum
+
+ Bitmask of Windows process access rights, passed as the ``permission=``
+ argument of ``OpenProcess`` on Windows.
+```
+
Bitmask of [process access rights](https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights).
Defined as `IntFlag` so members can be combined with `|`:
@@ -81,6 +93,12 @@ This is enough for both read and write operations plus region enumeration
## `MemoryProtectionsEnum` (Windows only)
+```{eval-rst}
+.. py:class:: MemoryProtectionsEnum
+
+ The Win32 ``PAGE_*`` page-protection constants.
+```
+
The Win32 `PAGE_*` constants. Used as the `permission=` argument of
`allocate_memory` and surfaced in `region["struct"].Protect`.
diff --git a/docs/api/errors.md b/docs/api/errors.md
index 7ac6fb0..948d903 100644
--- a/docs/api/errors.md
+++ b/docs/api/errors.md
@@ -32,11 +32,19 @@ more idiomatic match (`PermissionError`, `OSError`, `TypeError`, `ValueError`,
### `PyMemoryEditorError`
+```{eval-rst}
+.. py:exception:: PyMemoryEditorError
+```
+
Base class for every PyMemoryEditor-specific exception. Catch it to handle
*any* library error.
### `ClosedProcess`
+```{eval-rst}
+.. py:exception:: ClosedProcess
+```
+
Raised when you call any method on a process whose handle has already been
closed (manually or by leaving the `with` block).
@@ -52,10 +60,12 @@ process.read_process_memory(0x1000, int) # raises ClosedProcess
Raised when the given `pid=` doesn't correspond to a running process.
```{eval-rst}
-.. py:attribute:: pid
- :type: int
+.. py:exception:: ProcessIDNotExistsError
+
+ .. py:attribute:: pid
+ :type: int
- The PID that was looked up.
+ The PID that was looked up.
```
### `ProcessNotFoundError`
@@ -63,10 +73,12 @@ Raised when the given `pid=` doesn't correspond to a running process.
Raised when no running process matches the given `process_name=`.
```{eval-rst}
-.. py:attribute:: process_name
- :type: str
+.. py:exception:: ProcessNotFoundError
- The process name that was looked up.
+ .. py:attribute:: process_name
+ :type: str
+
+ The process name that was looked up.
```
### `AmbiguousProcessNameError`
@@ -75,16 +87,17 @@ Raised when **more than one** running process matches the given
`process_name=` (typical when using `exact_match=False`).
```{eval-rst}
-.. py:attribute:: process_name
- :type: str
- :no-index:
+.. py:exception:: AmbiguousProcessNameError
+
+ .. py:attribute:: process_name
+ :type: str
- The process name that was looked up.
+ The process name that was looked up.
-.. py:attribute:: pids
- :type: List[int]
+ .. py:attribute:: pids
+ :type: List[int]
- PIDs of the matching processes — pick one and pass it via ``pid=``.
+ PIDs of the matching processes — pick one and pass it via ``pid=``.
```
Example:
diff --git a/docs/api/index.md b/docs/api/index.md
new file mode 100644
index 0000000..1a29904
--- /dev/null
+++ b/docs/api/index.md
@@ -0,0 +1,33 @@
+# API Reference
+
+Every public class, method and helper PyMemoryEditor exposes. For
+task-oriented walkthroughs, see the [User Guide](../guide/index.md).
+
+## At a glance
+
+
+
+```{toctree}
+:maxdepth: 1
+
+openprocess
+enums
+memory-region
+remote-pointer
+pointer-path
+module-info
+thread-info
+errors
+utilities
+```
diff --git a/docs/api/memory-region.md b/docs/api/memory-region.md
index 2f7b4d8..11165c2 100644
--- a/docs/api/memory-region.md
+++ b/docs/api/memory-region.md
@@ -73,7 +73,7 @@ of memory with its address, size, permissions and backing path.
.. py:class:: MemoryRegionSnapshot
A pre-sorted snapshot of memory regions returned by
- :py:meth:`AbstractProcess.snapshot_memory_regions`. Behaves exactly like a
+ :py:meth:`snapshot_memory_regions`. Behaves exactly like a
plain ``list[MemoryRegion]`` — the only purpose of the subclass is to let
the scanning helpers detect via ``isinstance`` that the input is already
sorted by ``address`` and skip the per-call ``sorted(...)`` step.
diff --git a/docs/api/module-info.md b/docs/api/module-info.md
index 22a0458..f97157c 100644
--- a/docs/api/module-info.md
+++ b/docs/api/module-info.md
@@ -33,7 +33,7 @@ Linux, `.dylib` on macOS).
Address where the module is loaded for this run. Combine it with a
static offset (``base_address + offset``) to reach a known location
despite ASLR — the natural feed into
- :py:meth:`AbstractProcess.resolve_pointer_chain`.
+ :py:meth:`resolve_pointer_chain`.
.. py:attribute:: size
:type: int
diff --git a/docs/api/openprocess.md b/docs/api/openprocess.md
index 1b0be2a..806f575 100644
--- a/docs/api/openprocess.md
+++ b/docs/api/openprocess.md
@@ -12,6 +12,14 @@ resolves to:
All three subclass `AbstractProcess` and share the API documented below.
+```{eval-rst}
+.. py:class:: AbstractProcess
+
+ The cross-platform base class every backend implements. ``OpenProcess``
+ returns one of its subclasses; the methods documented on this page are the
+ shared, public surface.
+```
+
## Construction
```{eval-rst}
@@ -208,7 +216,7 @@ with OpenProcess(
```{eval-rst}
.. py:method:: close()
- Close the process handle. Subsequent calls raise :py:class:`ClosedProcess`.
+ Close the process handle. Subsequent calls raise :py:exc:`ClosedProcess`.
.. py:method:: __enter__()
.. py:method:: __exit__(exc_type, exc_value, exc_traceback)
diff --git a/docs/conf.py b/docs/conf.py
index 90fb167..680ded3 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -77,16 +77,30 @@
"source_branch": "main",
"source_directory": "docs/",
"light_css_variables": {
- "color-brand-primary": "#8A2BE2",
- "color-brand-content": "#8A2BE2",
+ "color-brand-primary": "#0D9488",
+ "color-brand-content": "#0D9488",
},
"dark_css_variables": {
- "color-brand-primary": "#B57AFF",
- "color-brand-content": "#B57AFF",
+ "color-brand-primary": "#2DD4BF",
+ "color-brand-content": "#2DD4BF",
},
+ # Persistent GitHub call-to-action, pinned to the sidebar footer on every page.
+ "footer_icons": [
+ {
+ "name": "GitHub",
+ "url": "https://github.com/JeanExtreme002/PyMemoryEditor",
+ "html": """
+
+ """,
+ "class": "",
+ },
+ ],
}
html_static_path = ["_static"]
+html_css_files = ["custom.css"]
# Logo and favicon resolved from the bundled SVG icon.
html_logo = "../PyMemoryEditor/app/assets/icon.svg"
diff --git a/docs/guide/index.md b/docs/guide/index.md
new file mode 100644
index 0000000..e39d77e
--- /dev/null
+++ b/docs/guide/index.md
@@ -0,0 +1,53 @@
+# User Guide
+
+Task-oriented walkthroughs of every PyMemoryEditor workflow, from opening a
+process to following multi-level pointer chains. Each page is self-contained
+and cross-links to the relevant [API reference](../api/index.md).
+
+New here? Read the [Quick Start](../quickstart.md) first, then come back for
+the in-depth version.
+
+## What's covered
+
+- **Core workflow** — open a process, read/write values, and find addresses by
+ value or byte pattern. This is the classic Cheat Engine loop.
+- **Inspecting the process** — enumerate memory regions, loaded modules and
+ threads.
+- **Pointers** — walk pointer chains you know, and reverse-scan to discover the
+ chains that survive a restart.
+- **Advanced** — reserve and release memory inside the target.
+
+For diagnostics, see [Logging](logging.md) in the Reference section.
+
+```{toctree}
+:caption: Core workflow
+:maxdepth: 1
+
+opening-process
+read-write
+searching
+pattern-scan
+```
+
+```{toctree}
+:caption: Inspecting the process
+:maxdepth: 1
+
+memory-regions
+modules-threads
+```
+
+```{toctree}
+:caption: Pointers
+:maxdepth: 1
+
+pointers
+pointer-scan
+```
+
+```{toctree}
+:caption: Advanced
+:maxdepth: 1
+
+allocate-free
+```
diff --git a/docs/guide/modules-threads.md b/docs/guide/modules-threads.md
index 530041b..106cf58 100644
--- a/docs/guide/modules-threads.md
+++ b/docs/guide/modules-threads.md
@@ -51,7 +51,7 @@ with OpenProcess(process_name="game.exe") as process:
Address where the module is loaded **for this run**. Combine it with a
static offset (``base_address + offset``) to reach a known location
despite ASLR — the natural feed into
- :py:meth:`AbstractProcess.resolve_pointer_chain`.
+ :py:meth:`resolve_pointer_chain`.
.. py:attribute:: size
:no-index:
diff --git a/docs/guide/pointer-scan.md b/docs/guide/pointer-scan.md
index baa40f7..dc33643 100644
--- a/docs/guide/pointer-scan.md
+++ b/docs/guide/pointer-scan.md
@@ -45,7 +45,7 @@ It carries everything you need to reconstruct the chain in another run.
Recommended for shallow exploration.
:param memory_regions: optional snapshot from
:py:meth:`snapshot_memory_regions`.
- :param callable progress_callback: ``callback(fraction)`` invoked as the
+ :param progress_callback: a callable ``callback(fraction)`` invoked as the
pointer map is built (the long phase), ``fraction`` in ``[0, 1]``.
:returns: a generator of :py:class:`PointerPath`.
```
diff --git a/docs/index.md b/docs/index.md
index 52d0070..f3eb380 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -33,7 +33,7 @@ If you've never done memory editing before, start with the
## Why use it?
-
+
@@ -53,7 +53,7 @@ platform-specific wheels.
-### 🧰 Batteries included
+### 🧰 Complete toolkit
Value scans, AOB scans, pointer chains, pointer scans, a GUI app — all the
Cheat Engine workflows in one package.
@@ -78,16 +78,7 @@ quickstart
:caption: User Guide
:maxdepth: 2
-guide/opening-process
-guide/read-write
-guide/searching
-guide/pattern-scan
-guide/memory-regions
-guide/modules-threads
-guide/pointers
-guide/pointer-scan
-guide/allocate-free
-guide/logging
+guide/index
```
```{toctree}
@@ -101,15 +92,7 @@ app
:caption: API Reference
:maxdepth: 2
-api/openprocess
-api/enums
-api/memory-region
-api/remote-pointer
-api/pointer-path
-api/module-info
-api/thread-info
-api/errors
-api/utilities
+api/index
```
```{toctree}
@@ -118,6 +101,7 @@ api/utilities
platform-notes
troubleshooting
+guide/logging
glossary
```