Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 8 additions & 2 deletions src/caelestia/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
from importlib import import_module

from caelestia.parser import parse_args
from caelestia.utils.version import print_version


def main() -> None:
parser, args = parse_args()
if args.version:
from caelestia.utils.version import print_version

print_version()
elif "cls" in args:
args.cls(args).run()
# Resolve the lazy "module:class" reference from the parser
module, _, cls = args.cls.partition(":")
command = getattr(import_module(f"caelestia.subcommands.{module}"), cls)
command(args).run()
else:
parser.print_help()
31 changes: 17 additions & 14 deletions src/caelestia/parser.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import argparse

from caelestia.subcommands import clipboard, emoji, record, resizer, scheme, screenshot, shell, toggle, wallpaper
from caelestia.utils.paths import wallpapers_dir
from caelestia.utils.scheme import get_scheme_names, scheme_variants
from caelestia.utils.wallpaper import get_wallpaper

# Subcommands are referenced as "module:class" strings and imported lazily in
# main() so that a single invocation only pays the import cost of the
# subcommand it actually runs (heavy imports like PIL/materialyoucolor would
# otherwise slow down every command)


def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]:
Expand All @@ -17,7 +20,7 @@ def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]:

# Create parser for shell opts
shell_parser = command_parser.add_parser("shell", help="start or message the shell")
shell_parser.set_defaults(cls=shell.Command)
shell_parser.set_defaults(cls="shell:Command")
shell_parser.add_argument("message", nargs="*", help="a message to send to the shell")
shell_parser.add_argument("-d", "--daemon", action="store_true", help="start the shell detached")
shell_parser.add_argument("-s", "--show", action="store_true", help="print all shell IPC commands")
Expand All @@ -27,29 +30,29 @@ def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]:

# Create parser for toggle opts
toggle_parser = command_parser.add_parser("toggle", help="toggle a special workspace")
toggle_parser.set_defaults(cls=toggle.Command)
toggle_parser.set_defaults(cls="toggle:Command")
toggle_parser.add_argument("workspace", help="the workspace to toggle")

# Create parser for scheme opts
scheme_parser = command_parser.add_parser("scheme", help="manage the colour scheme")
scheme_command_parser = scheme_parser.add_subparsers(title="subcommands")

list_parser = scheme_command_parser.add_parser("list", help="list available schemes")
list_parser.set_defaults(cls=scheme.List)
list_parser.set_defaults(cls="scheme:List")
list_parser.add_argument("-n", "--names", action="store_true", help="list scheme names")
list_parser.add_argument("-f", "--flavours", action="store_true", help="list scheme flavours")
list_parser.add_argument("-m", "--modes", action="store_true", help="list scheme modes")
list_parser.add_argument("-v", "--variants", action="store_true", help="list scheme variants")

get_parser = scheme_command_parser.add_parser("get", help="get scheme properties")
get_parser.set_defaults(cls=scheme.Get)
get_parser.set_defaults(cls="scheme:Get")
get_parser.add_argument("-n", "--name", action="store_true", help="print the current scheme name")
get_parser.add_argument("-f", "--flavour", action="store_true", help="print the current scheme flavour")
get_parser.add_argument("-m", "--mode", action="store_true", help="print the current scheme mode")
get_parser.add_argument("-v", "--variant", action="store_true", help="print the current scheme variant")

set_parser = scheme_command_parser.add_parser("set", help="set the current scheme")
set_parser.set_defaults(cls=scheme.Set)
set_parser.set_defaults(cls="scheme:Set")
set_parser.add_argument("--notify", action="store_true", help="send a notification on error")
set_parser.add_argument("-r", "--random", action="store_true", help="switch to a random scheme")
set_parser.add_argument("-n", "--name", choices=get_scheme_names(), help="the name of the scheme to switch to")
Expand All @@ -59,36 +62,36 @@ def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]:

# Create parser for screenshot opts
screenshot_parser = command_parser.add_parser("screenshot", help="take a screenshot")
screenshot_parser.set_defaults(cls=screenshot.Command)
screenshot_parser.set_defaults(cls="screenshot:Command")
screenshot_parser.add_argument("-r", "--region", nargs="?", const="slurp", help="take a screenshot of a region")
screenshot_parser.add_argument(
"-f", "--freeze", action="store_true", help="freeze the screen while selecting a region"
)

# Create parser for record opts
record_parser = command_parser.add_parser("record", help="start a screen recording")
record_parser.set_defaults(cls=record.Command)
record_parser.set_defaults(cls="record:Command")
record_parser.add_argument("-r", "--region", nargs="?", const="slurp", help="record a region")
record_parser.add_argument("-s", "--sound", action="store_true", help="record audio")
record_parser.add_argument("-p", "--pause", action="store_true", help="pause/resume the recording")
record_parser.add_argument("-c", "--clipboard", action="store_true", help="copy recording path to clipboard")

# Create parser for clipboard opts
clipboard_parser = command_parser.add_parser("clipboard", help="open clipboard history")
clipboard_parser.set_defaults(cls=clipboard.Command)
clipboard_parser.set_defaults(cls="clipboard:Command")
clipboard_parser.add_argument("-d", "--delete", action="store_true", help="delete from clipboard history")

# Create parser for emoji-picker opts
emoji_parser = command_parser.add_parser("emoji", help="emoji/glyph utilities")
emoji_parser.set_defaults(cls=emoji.Command)
emoji_parser.set_defaults(cls="emoji:Command")
emoji_parser.add_argument("-p", "--picker", action="store_true", help="open the emoji/glyph picker")
emoji_parser.add_argument("-f", "--fetch", action="store_true", help="fetch emoji/glyph data from remote")

# Create parser for wallpaper opts
wallpaper_parser = command_parser.add_parser("wallpaper", help="manage the wallpaper")
wallpaper_parser.set_defaults(cls=wallpaper.Command)
wallpaper_parser.set_defaults(cls="wallpaper:Command")
wallpaper_parser.add_argument(
"-p", "--print", nargs="?", const=get_wallpaper(), metavar="PATH", help="print the scheme for a wallpaper"
"-p", "--print", nargs="?", const=True, metavar="PATH", help="print the scheme for a wallpaper"
)
wallpaper_parser.add_argument(
"-r", "--random", nargs="?", const=wallpapers_dir, metavar="DIR", help="switch to a random wallpaper"
Expand All @@ -110,7 +113,7 @@ def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]:

# Create parser for resizer opts
resizer_parser = command_parser.add_parser("resizer", help="window resizer daemon")
resizer_parser.set_defaults(cls=resizer.Command)
resizer_parser.set_defaults(cls="resizer:Command")
resizer_parser.add_argument("-d", "--daemon", action="store_true", help="start the resizer daemon")
resizer_parser.add_argument(
"pattern",
Expand Down
8 changes: 7 additions & 1 deletion src/caelestia/subcommands/wallpaper.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ def __init__(self, args: Namespace) -> None:

def run(self) -> None:
if self.args.print:
print(json.dumps(get_colours_for_wall(self.args.print, self.args.no_smart)))
# -p with no path means the current wallpaper (resolved here instead of
# at argument parsing time to avoid the cost on unrelated commands)
wall = get_wallpaper() if self.args.print is True else self.args.print
if wall is None:
print("No wallpaper set")
return
print(json.dumps(get_colours_for_wall(wall, self.args.no_smart)))
elif self.args.file:
set_wallpaper(self.args.file, self.args.no_smart)
elif self.args.random:
Expand Down