Skip to content

Commit

Permalink
Merge 89b2280 into 65fb3d0
Browse files Browse the repository at this point in the history
  • Loading branch information
dynobo committed Apr 21, 2024
2 parents 65fb3d0 + 89b2280 commit ba528b2
Show file tree
Hide file tree
Showing 32 changed files with 1,846 additions and 908 deletions.
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
# Changelog

## v0.4.4 (2024-02-14)
## v0.5.0 (upcoming)

- Breaking changes:
- Renamed the attribute `regex_process` in `toml`-files to `regex_wmclass`.
- Renamed the attribute `source` in `toml`-files to `url`.
- Removed cli-args which are now covered by settings menu.
- Fix duplicate IDs in included sections.
- Fix error if launched with `--no-section-sort`
- Add settings menu to ui.
- Focus search field on start.
- Move generic CLI commands into separate cheatsheet and include it in terminal apps.
- Cheatsheets:
- Moved some CLI commands into separate cheatsheet and include it in terminal apps.
- Added sheet for Keyhint itself.

## v0.4.3 (2024-02-13)

Expand Down
149 changes: 101 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# KeyHint

**_Utility to display keyboard shortcuts or other hints based on the active window on
Linux. (GTK 4.6+ required!)_**
Linux._**

<p align="center"><br>
<img alt="Tests passing" src="https://github.com/dynobo/keyhint/workflows/Test/badge.svg">
Expand All @@ -24,6 +24,12 @@ Linux. (GTK 4.6+ required!)_**
gobject-introspection \
libgtk-4-dev
```
- Wayland & Gnome: The
[Gnome Extension "Window-Calls"](https://extensions.gnome.org/extension/4724/window-calls/)
is required to auto-select the cheatsheet based on the current active application.
- Wayland & KDE: Not yet implemented.
[Create an issue](https://github.com/dynobo/keyhint/issues/new) if you like to have
this support for this setup.

## Installation

Expand All @@ -35,80 +41,128 @@ Linux. (GTK 4.6+ required!)_**
- Configure a **global hotkey** (e.g. `Ctrl + F1`) **via your system settings** to
launch `keyhint`.
- If KeyHint is launched via hotkey, it detects the current active application and shows
the appropriate hints.
the appropriate hints. (This feature won't work reliably when KeyHint ist started via
Menu or Launcher.)

## CLI Options

```
Application Options:
-c, --cheatsheet=SHEET-ID Show cheatsheet with this ID on startup
-d, --default-cheatsheet=SHEET-ID Cheatsheet to show in case no cheatsheet is found for active application
-f, --no-fullscreen Launch window in normal window state instead of fullscreen mode
-s, --no-section-sort Do not sort sections by size, keep order from config toml file
-o, --orientation=horizontal|vertical Orientation and scroll direction. Default: 'vertical'
-v, --verbose Verbose log output for debugging
```

## Configuration
## Cheatsheet Configuration

- The **config directory** is `~/.config/keyhint/`.
- To **customize existing** cheatsheets, copy
The content which KeyHint displays is configured using [`toml`](https://toml.io/en/)
configuration files.

KeyHint reads those files from two locations:

1. The [built-in directory](https://github.com/dynobo/keyhint/tree/main/keyhint/config)
1. The user directory, usually located in `~/.config/keyhint`

### How Keyhint selects the cheatsheet to show

- The cheatsheet to be displayed on startup are selected by comparing the value of
`regex_wmclass` with the wm_class of the active window and the value of `regex_title`
with the title of the active window.
- The potential cheatsheets are processed alphabetically by filename, the first file
that matches both wm_class and title are getting displayed.
- Both of `regex_` values are interpreted as **case in-sensitive regular expressions**.
- Check "Debug Info" in the application menu to get insights about the active window and
the selected cheatsheet file.

### Customize or add cheatsheets

- To **change built-in** cheatsheets, copy
[the corresponding .toml-file](https://github.com/dynobo/keyhint/tree/main/src/keyhint/config)
into the config directory. Make your changes in a text editor. As long as you don't
change the `id` it will overwrite the defaults.
- To **create new** cheatsheets, I suggest you also start with
- To **create new** cheatsheets, I suggest you start with
[one of the existing .toml-file](https://github.com/dynobo/keyhint/tree/main/src/keyhint/config):
- Place it in the config directory and give it a good file name.
- Change the value `id` to something unique.
- Adjust `regex_process` and `regex_title` so it will be selected based on the active
- Adjust `regex_wmclass` and `regex_title` so it will be selected based on the active
window. (See [Tips](#tips))
- Add the `shortcuts` & `label` to a `section`.
- If you think your cheatsheet might be useful for others, please consider opening a
pull request or an issue.
- You can always **reset a configuration** to the shipped version by deleting the
`.toml` files from the config folder.
- You can **include shortcuts from other cheatsheets** add
pull request or an issue!
- You can always **reset cheatsheets** to the shipped version by deleting the
corresponding `.toml` files from the config folder.
- You can **include shortcuts from other cheatsheets** by adding
`include = ["<Cheatsheet ID>"]`
- You can **hide a cheatsheet** by add `hidden = true` in the top block (same level as
`id` and `title`).

## Tips
### Examples

**Cheatsheet selection:**
#### Hide existing cheatsheets

- The cheatsheet to be displayed on startup are selected by comparing the value of
`regex_process` with the wm_class of the active window and the value of `regex_title`
with the title of the active window.
- The potential cheatsheets are processed alphabetically by filename, the first file
that matches both wm_class and title are getting displayed.
- Both of `regex_` values are interpreted as **case in-sensitive regular expressions**.
- Check "Debug Info" in the application menu to get insights about the active window and
the selected cheatsheet file.
To hide a cheatsheet, e.g. the
[built-in](https://github.com/dynobo/keyhint/blob/main/keyhint/config/tilix.toml) one
with the ID `tilix`, create a new file `~/.config/keyhint/tilix.toml` with the content:

```toml
id = "tilix"
hidden = true
```

**Available cheatsheets:**
#### Extend existing cheatsheets

To add keybindings to an existing cheatsheet, e.g. the
[built-in](https://github.com/dynobo/keyhint/blob/main/keyhint/config/firefox.toml) one
with the ID `firefox`, create a new file `~/.config/keyhint/firefox.toml` which only
contains the ID and the additional bindings:

```toml
id = "firefox"

[section]
[section."My Personal Favorites"] # New section
"Ctrl + Shift + Tab" = "Show all Tabs"
# ...
```

- Check the
[included toml-files](https://github.com/dynobo/keyhint/tree/main/src/keyhint/config)
to see which applications are available by default.
- Feel free submit additional `toml-files` for further applications.
#### Add new cheatsheet which never gets auto-selected

**Differentiate cheatsheets per website:**
To add a new cheatsheet, which never gets automatically selected and displayed by
KeyHint, but remains accessible through KeyHint's cheatsheet dropdown, create a file
`~/.config/keyhint/my-app.toml`:

- For showing different browser-cheatsheets depending on the current website, you might
want to use a browser extension like
"[Add URL To Window Title](https://addons.mozilla.org/en-US/firefox/addon/add-url-to-window-title/)"
and then configure the sections in `<cheatsheet>.toml` to look for the URL in the
window title.
```toml
id = "my-app"
url = "url-to-my-apps-keybindings"

**KeyHint's shortcuts:**
[match]
regex_wmclass = "a^" # Patter which never matches
regex_title = "a^"

- `Ctrl+F`: Start filtering
- `Ctrl+S`: Focus sheet selection dropdown (press `Enter` to open it)
- `Esc`: Exit KeyHint
- ``, ``, `l` or `k`: scroll forward
- ``, ``, `h` or `j`: scroll backward
- `PageDown`: scroll page forward
- `PageUP`: scroll page backward
[section]
[section.General]
"Ctrl + C" = "Copy"
# ...

```

#### Different cheatsheets for different Websites

For showing different browser-cheatsheets depending on the current website, you might
want to use a browser extension like
"[Add URL To Window Title](https://addons.mozilla.org/en-US/firefox/addon/add-url-to-window-title/)"
and configure the `[match]` section to look for the url in the title. E.g.
`~/.config/keyhint/github.toml`

```toml
id = "github.com"

[match]
regex_wmclass = "Firefox"
regex_title = ".*github\\.com.*" # URL added by browser extensions to window title

[section]
[section.Repositories]
gc = "Goto code tab"
# ...
```

## Contribute

Expand All @@ -120,11 +174,10 @@ the
## Design Principles

- **Don't run as service**<br>It shouldn't consume resources in the background, even if
this leads to slower start-up time.
this leads to slightly slower start-up time.
- **No network connection**<br>Everything should run locally without any network
communication.
- **Dependencies**<br>The fewer dependencies, the better.
- **Multi-Monitors**<br>Supports setups with two or more displays

## Certification

Expand Down
3 changes: 0 additions & 3 deletions keyhint/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
from keyhint import utils

__version__ = "0.4.4"
__all__ = ["utils"]
1 change: 1 addition & 0 deletions keyhint/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Package entry for keyhint."""

from keyhint import app

if __name__ == "__main__":
Expand Down
50 changes: 9 additions & 41 deletions keyhint/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,22 @@

import logging
import sys
from collections.abc import Mapping
from typing import Any

import gi

gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")

from gi.repository import Adw, Gio, GLib, Gtk # noqa: E402
from gi.repository import Adw, Gio, GLib # noqa: E402

from keyhint.window import KeyhintWindow # noqa: E402

logging.basicConfig(
format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
format="%(asctime)s - %(levelname)-7s - %(module)s.py:%(lineno)d - %(message)s",
datefmt="%H:%M:%S",
level="WARNING",
)
logger = logging.getLogger(__name__)
logger = logging.getLogger("keyhint")


class Application(Adw.Application):
Expand All @@ -36,10 +34,12 @@ class Application(Adw.Application):

def __init__(self, *args, **kwargs) -> None: # noqa: ANN002, ANN003
"""Initialize application with command line options."""
super().__init__(
*args,
kwargs.update(
application_id="eu.dynobo.keyhint",
flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
)
super().__init__(
*args,
**kwargs,
)
self.options: dict = {}
Expand All @@ -52,38 +52,6 @@ def __init__(self, *args, **kwargs) -> None: # noqa: ANN002, ANN003
"Show cheatsheet with this ID on startup",
"SHEET-ID",
)
self.add_main_option(
"default-cheatsheet",
ord("d"),
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
"Cheatsheet to show in case no cheatsheet is found for active application",
"SHEET-ID",
)
self.add_main_option(
"no-fullscreen",
ord("f"),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
"Launch window in normal window state instead of fullscreen mode",
None,
)
self.add_main_option(
"no-section-sort",
ord("s"),
GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
"Do not sort sections by size, keep order from config toml file",
None,
)
self.add_main_option(
"orientation",
ord("o"),
GLib.OptionFlags.NONE,
GLib.OptionArg.STRING,
"Orientation and scroll direction. Default: 'vertical'",
"horizontal|vertical",
)
self.add_main_option(
"verbose",
ord("v"),
Expand All @@ -99,12 +67,12 @@ def do_activate(self, *_, **__) -> None: # noqa: ANN002, ANN003
window.set_application(self)
window.present()

def do_command_line(self, cli: Gtk, **__: Mapping[Any, Any]) -> int:
def do_command_line(self, cli: Gio.ApplicationCommandLine) -> int:
"""Store command line options in class attribute for later usage."""
self.options = cli.get_options_dict().end().unpack()

if "verbose" in self.options:
logging.getLogger().setLevel("DEBUG")
logger.setLevel("DEBUG")
logger.debug("CLI Options: %s", self.options)

self.activate()
Expand Down
Loading

0 comments on commit ba528b2

Please sign in to comment.