Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Theme system #57

Merged
merged 20 commits into from
Jul 24, 2024
Merged
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
Binary file modified .coverage
Binary file not shown.
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ Dotenv files are separate from collections, although you may wish to include the
| Config Key (Env Var) | Values (Default) | Description |
|----------------------|------------------|-------------|
| `theme` (`POSTING_THEME`) | `"posting"`, `"galaxy"`, `"monokai"`, `"solarized-light"`, `"nautilus"`, `"nebula"`, `"alpine"`, `"cobalt"`, `"twilight"`, `"hacker"` (Default: `"posting"`) | Sets the theme of the application. |
| `load_user_themes` (`POSTING_LOAD_USER_THEMES`) | `true`, `false` (Default: `true`) | If enabled, load user themes from the theme directory, allowing them to be specified in config and selected via the command palette. |
| `load_builtin_themes` (`POSTING_LOAD_BUILTIN_THEMES`) | `true`, `false` (Default: `true`) | If enabled, load builtin themes, allowing them to be specified in config and selected via the command palette. |
| `theme_directory` (`POSTING_THEME_DIRECTORY`) | (Default: `${XDG_DATA_HOME}/posting/themes`) | The directory containing user themes. |
| `layout` (`POSTING_LAYOUT`) | `"vertical"`, `"horizontal"` (Default: `"horizontal"`) | Sets the layout of the application. |
| `use_host_environment` (`POSTING_USE_HOST_ENVIRONMENT`) | `true`, `false` (Default: `false`) | Allow/deny using environment variables from the host machine in requests via `$env:` syntax. When disabled, only variables defined explicitly in `.env` files will be available for use. |
| `animation` (`POSTING_ANIMATION`) | `"none"`, `"basic"`, `"full"` (Default: `"none"`) | Controls the animation level. |
Expand All @@ -240,6 +243,7 @@ Dotenv files are separate from collections, although you may wish to include the
| `focus.on_startup` (`POSTING_FOCUS__ON_STARTUP`) | `"url"`, `"method", "collection"` (Default: `"url"`) | Automatically focus the URL bar, method, or collection browser when the app starts. |
| `focus.on_response` (`POSTING_FOCUS__ON_RESPONSE`) | `"body"`, `"tabs"` (Default: `unset`)| Automatically focus the response tabs or response body text area when a response is received. |
| `text_input.blinking_cursor` (`POSTING_TEXT_INPUT__BLINKING_CURSOR`) | `true`, `false` (Default: `true`) | If enabled, the cursor will blink in input widgets and text area widgets. |
<!-- | `use_xresources` (`POSTING_USE_XRESOURCES`) | `true`, `false` (Default: `false`) | Try to create themes called `xresources-dark` and `xresources-light` (see the section below) | -->

## SSL certificate configuration

Expand Down Expand Up @@ -278,6 +282,51 @@ ssl:
password: '***********' # optional password for key_file
```

## Theming

Place custom themes in the themes directory and Posting will load them on startup. Theme files must be suffixed with `.yaml`, but the rest of the filename is unused by Posting.

You can check where Posting will look for themes by running `posting locate themes` in your terminal.

Here's an example theme file:

```yaml
name: example # use this name in your config file
primary: '#4e78c4' # buttons, fixed table columns
secondary: '#f39c12' # method selector, some minor labels
accent: '#e74c3c' # header text, scrollbars, cursors, focus highlights
background: '#0e1726' # background colors
surface: '#17202a' # panels, etc
error: '#e74c3c' # error messages
success: '#2ecc71' # success messages
warning: '#f1c40f' # warning messages
syntax: 'dracula' # auto-switch syntax highlighting theme

# Optional metadata
author: Darren Burns
description: A dark theme with a blue primary color.
homepage: https://github.com/darrenburns/posting
```

### X resources themes

Posting supports using X resources for theming. To use this, enable the `use_xresources` option (see above).

It requires the `xrdb` executable on your `PATH` and `xrdb -query` must return the following variables:

| Xresources | Description |
|-------------|-----------|
| *color0 | primary color: used for button backgrounds and fixed table columns |
| *color8 | secondary color: used in method selector and some minor labels |
| *color1 | error color: used for error messages |
| *color2 | success color: used for success messages |
| *color3 | warning color: used for warning messages |
| *color4 | accent color: used for header text, scrollbars, cursors, focus highlights |
| *background | background color |
| *color7 | surface/panel color |

If these conditions are met, themes called `xresources-dark` and `xresources-light` will be available for use.

## Importing OpenAPI Specifications

Note: this feature is highly experimental.
Expand All @@ -290,4 +339,4 @@ You can optionally supply an output directory.

If no output directory is supplied, the default collection directory will be used.

Posting will attempt to build a file structure in the collection that aligns with the URL structure of the imported API.
Posting will attempt to build a file structure in the collection that aligns with the URL structure of the imported API.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ dev-dependencies = [
"syrupy>=4.6.1",
"pytest-xdist>=3.6.1",
"pytest-cov>=5.0.0",
"pytest-textual-snapshot>=1.0.0",
]

[tool.hatch.metadata]
Expand All @@ -69,4 +70,4 @@ markers = [
]

[tool.coverage.run]
relative_files = true
relative_files = true
6 changes: 6 additions & 0 deletions requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ idna==3.7
iniconfig==2.0.0
# via pytest
jinja2==3.1.4
# via pytest-textual-snapshot
linkify-it-py==2.0.3
# via markdown-it-py
markdown-it-py==3.0.0
Expand Down Expand Up @@ -84,23 +85,28 @@ pyperclip==1.8.2
# via posting
pytest==8.3.1
# via pytest-cov
# via pytest-textual-snapshot
# via pytest-xdist
# via syrupy
pytest-cov==5.0.0
pytest-textual-snapshot==1.0.0
pytest-xdist==3.6.1
python-dotenv==1.0.1
# via posting
# via pydantic-settings
pyyaml==6.0.1
# via posting
rich==13.7.1
# via pytest-textual-snapshot
# via textual
sniffio==1.3.1
# via anyio
# via httpx
syrupy==4.6.1
# via pytest-textual-snapshot
textual==0.73.0
# via posting
# via pytest-textual-snapshot
# via textual-autocomplete
# via textual-dev
textual-autocomplete==3.0.0a9
Expand Down
12 changes: 9 additions & 3 deletions src/posting/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
from posting.collection import Collection
from posting.config import Settings
from posting.importing.open_api import import_openapi_spec
from posting.locations import config_file, default_collection_directory
from posting.locations import (
config_file,
default_collection_directory,
theme_directory,
)


def create_config_file() -> None:
Expand Down Expand Up @@ -68,7 +72,6 @@ def default(collection: str | None = None, env: tuple[str, ...] = ()) -> None:
@cli.command()
@click.argument(
"thing_to_locate",
type=click.Choice(["config", "collection"]),
)
def locate(thing_to_locate: str) -> None:
if thing_to_locate == "config":
Expand All @@ -77,10 +80,13 @@ def locate(thing_to_locate: str) -> None:
elif thing_to_locate == "collection":
print("Default collection directory:")
print(default_collection_directory())
elif thing_to_locate == "themes":
print("Themes directory:")
print(theme_directory())
else:
# This shouldn't happen because the type annotation should enforce that
# the only valid options are "config" and "collection".
raise ValueError(f"Unknown thing to locate: {thing_to_locate}")
print(f"Unknown thing to locate: {thing_to_locate!r}")


@cli.command(name="import")
Expand Down
Loading
Loading