Skip to content

Commit 214202f

Browse files
authored
🔀 Merge pull request #152 from davep/key-bindings
Add support for rebinding commands to different keys
2 parents 13197f6 + 829343a commit 214202f

File tree

4 files changed

+112
-12
lines changed

4 files changed

+112
-12
lines changed

ChangeLog.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
# Braindrop ChangeLog
22

3+
## Unreleased
4+
5+
**Released: WiP**
6+
7+
- Added support for rebinding the keys for application commands.
8+
([#152](https://github.com/davep/braindrop/pull/152))
9+
- Added `--bindings` as a command line switch.
10+
([#152](https://github.com/davep/braindrop/pull/152))
11+
- Added `--help` as a command line switch.
12+
([#152](https://github.com/davep/braindrop/pull/152))
13+
- Added `--license` as a command line switch.
14+
([#152](https://github.com/davep/braindrop/pull/152))
15+
- Added `--version` as a command line switch.
16+
([#152](https://github.com/davep/braindrop/pull/152))
17+
318
## v0.7.3
419

520
**Released: 2025-04-27**

src/braindrop/__main__.py

Lines changed: 92 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,106 @@
11
"""Main entry point for the application."""
22

3+
##############################################################################
4+
# Python imports.
5+
from argparse import ArgumentParser, Namespace
6+
from inspect import cleandoc
7+
from operator import attrgetter
8+
9+
##############################################################################
10+
# Textual enhanced imports.
11+
from textual_enhanced.commands import Command
12+
313
##############################################################################
414
# Local imports.
15+
from . import __doc__, __version__
516
from .app import Braindrop
617
from .app.data import ExitState
718

819

20+
##############################################################################
21+
def get_args() -> Namespace:
22+
"""Get the command line arguments.
23+
24+
Returns:
25+
The arguments.
26+
"""
27+
28+
# Build the parser.
29+
parser = ArgumentParser(
30+
prog="braindrop",
31+
description=__doc__,
32+
epilog=f"v{__version__}",
33+
)
34+
35+
# Add --version
36+
parser.add_argument(
37+
"-v",
38+
"--version",
39+
help="Show version information",
40+
action="version",
41+
version=f"%(prog)s v{__version__}",
42+
)
43+
44+
# Add --license
45+
parser.add_argument(
46+
"--license",
47+
"--licence",
48+
help="Show license information",
49+
action="store_true",
50+
)
51+
52+
# Add --bindings
53+
parser.add_argument(
54+
"-b",
55+
"--bindings",
56+
help="List commands that can have their bindings changed",
57+
action="store_true",
58+
)
59+
60+
# Finally, parse the command line.
61+
return parser.parse_args()
62+
63+
64+
##############################################################################
65+
def show_bindable_commands() -> None:
66+
"""Show the commands that can have bindings applied."""
67+
from rich.console import Console
68+
from rich.markup import escape
69+
70+
from .app.screens import Main
71+
72+
console = Console(highlight=False)
73+
command: type[Command]
74+
for command in sorted(Main.COMMAND_MESSAGES, key=attrgetter("__name__")):
75+
if command().has_binding:
76+
console.print(
77+
f"[bold]{escape(command.__name__)}[/] [dim italic]- {escape(command.tooltip())}[/]"
78+
)
79+
console.print(
80+
f" [dim italic]Default: {escape(command.binding().key)}[/]"
81+
)
82+
83+
984
##############################################################################
1085
def main() -> None:
1186
"""Main entry point."""
12-
match Braindrop().run():
13-
case ExitState.TOKEN_FORGOTTEN:
14-
if Braindrop.environmental_token():
15-
print(
16-
"It looks like your token is held in an environment variable. "
17-
"If you wish to have that forgotten you will need to remove it yourself."
18-
)
19-
else:
20-
print("The locally-held copy of your API token has been removed.")
21-
case ExitState.TOKEN_NEEDED:
22-
print("An API token is needed to be able to connect to raindrop.io.")
87+
args = get_args()
88+
if args.license:
89+
print(cleandoc(Braindrop.HELP_LICENSE))
90+
elif args.bindings:
91+
show_bindable_commands()
92+
else:
93+
match Braindrop().run():
94+
case ExitState.TOKEN_FORGOTTEN:
95+
if Braindrop.environmental_token():
96+
print(
97+
"It looks like your token is held in an environment variable. "
98+
"If you wish to have that forgotten you will need to remove it yourself."
99+
)
100+
else:
101+
print("The locally-held copy of your API token has been removed.")
102+
case ExitState.TOKEN_NEEDED:
103+
print("An API token is needed to be able to connect to raindrop.io.")
23104

24105

25106
##############################################################################

src/braindrop/app/braindrop.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def __init__(self) -> None:
6464
self.theme = configuration.theme
6565
except InvalidThemeError:
6666
pass
67+
self.update_keymap(configuration.bindings)
6768

6869
def watch_theme(self) -> None:
6970
"""Save the application's theme when it's changed."""

src/braindrop/app/data/config.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
##############################################################################
44
# Python imports.
55
from contextlib import contextmanager
6-
from dataclasses import asdict, dataclass
6+
from dataclasses import asdict, dataclass, field
77
from functools import lru_cache
88
from json import dumps, loads
99
from pathlib import Path
@@ -31,6 +31,9 @@ class Configuration:
3131
compact_mode: bool = False
3232
"""Use compact mode?"""
3333

34+
bindings: dict[str, str] = field(default_factory=dict)
35+
"""Command keyboard binding overrides."""
36+
3437

3538
##############################################################################
3639
def configuration_file() -> Path:

0 commit comments

Comments
 (0)