Pass tui options through cli options

This commit is contained in:
Ivan Habunek 2023-12-07 19:11:59 +01:00
parent ac77ea75ce
commit bbf67c6736
No known key found for this signature in database
GPG Key ID: F5F0623FF5EBCB3D
6 changed files with 81 additions and 28 deletions

View File

@ -20,6 +20,17 @@ T = t.TypeVar("T")
PRIVACY_CHOICES = ["public", "unlisted", "private"]
VISIBILITY_CHOICES = ["public", "unlisted", "private", "direct"]
TUI_COLORS = {
"1": 1,
"16": 16,
"88": 88,
"256": 256,
"16777216": 16777216,
"24bit": 16777216,
}
TUI_COLORS_CHOICES = list(TUI_COLORS.keys())
TUI_COLORS_VALUES = list(TUI_COLORS.values())
DURATION_EXAMPLES = """e.g. "1 day", "2 hours 30 minutes", "5 minutes 30
seconds" or any combination of above. Shorthand: "1d", "2h30m", "5m30s\""""

View File

@ -1,17 +1,44 @@
import click
from toot.cli.base import Context, cli, pass_context
from typing import Optional
from toot.cli.base import TUI_COLORS, Context, cli, pass_context
from toot.cli.validators import validate_tui_colors
from toot.tui.app import TUI, TuiOptions
COLOR_OPTIONS = ", ".join(TUI_COLORS.keys())
@cli.command()
@click.option(
"--relative-datetimes",
"-r", "--relative-datetimes",
is_flag=True,
help="Show relative datetimes in status list"
)
@click.option(
"-m", "--media-viewer",
help="Program to invoke with media URLs to display the media files, such as 'feh'"
)
@click.option(
"-c", "--colors",
callback=validate_tui_colors,
help=f"""Number of colors to use, one of {COLOR_OPTIONS}, defaults to 16 if
using --color, and 1 if using --no-color."""
)
@pass_context
def tui(ctx: Context, relative_datetimes: bool):
def tui(
ctx: Context,
colors: Optional[int],
media_viewer: Optional[str],
relative_datetimes: bool,
):
"""Launches the toot terminal user interface"""
options = TuiOptions(relative_datetimes, ctx.color)
TUI.create(ctx.app, ctx.user, options).run()
if colors is None:
colors = 16 if ctx.color else 1
options = TuiOptions(
colors=colors,
media_viewer=media_viewer,
relative_datetimes=relative_datetimes,
)
tui = TUI.create(ctx.app, ctx.user, options)
tui.run()

View File

@ -4,6 +4,8 @@ import re
from click import Context
from typing import Optional
from toot.cli.base import TUI_COLORS
def validate_language(ctx: Context, param: str, value: Optional[str]):
if value is None:
@ -58,3 +60,16 @@ def validate_instance(ctx: click.Context, param: str, value: Optional[str]):
value = value.rstrip("/")
return value if value.startswith("http") else f"https://{value}"
def validate_tui_colors(ctx, param, value) -> Optional[int]:
if value is None:
return None
if value in TUI_COLORS.values():
return value
if value in TUI_COLORS.keys():
return TUI_COLORS[value]
raise click.BadParameter(f"Invalid value: {value}. Expected one of: {', '.join(TUI_COLORS)}")

View File

@ -25,6 +25,10 @@ def get_width() -> int:
return min(get_terminal_width(), get_max_width())
def print_warning(text: str):
click.secho(f"Warning: {text}", fg="yellow", err=True)
def print_instance(instance: Instance):
width = get_width()
click.echo(instance_to_text(instance, width))

View File

@ -3,7 +3,7 @@ import subprocess
import urwid
from concurrent.futures import ThreadPoolExecutor
from typing import NamedTuple
from typing import NamedTuple, Optional
from toot import api, config, __version__, settings
from toot import App, User
@ -28,8 +28,9 @@ DEFAULT_MAX_TOOT_CHARS = 500
class TuiOptions(NamedTuple):
colors: int
media_viewer: Optional[str]
relative_datetimes: bool
color: bool
class Header(urwid.WidgetWrap):
@ -89,7 +90,9 @@ class TUI(urwid.Frame):
@staticmethod
def create(app: App, user: User, args: TuiOptions):
"""Factory method, sets up TUI and an event loop."""
screen = TUI.create_screen(args)
screen = urwid.raw_display.Screen()
screen.set_terminal_properties(args.colors)
tui = TUI(app, user, screen, args)
palette = PALETTE.copy()
@ -108,23 +111,11 @@ class TUI(urwid.Frame):
return tui
@staticmethod
def create_screen(args: TuiOptions):
screen = urwid.raw_display.Screen()
# Determine how many colors to use
default_colors = 16 if args.color else 1
colors = settings.get_setting("tui.colors", int, default_colors)
logger.debug(f"Setting colors to {colors}")
screen.set_terminal_properties(colors)
return screen
def __init__(self, app, user, screen, args: TuiOptions):
def __init__(self, app, user, screen, options: TuiOptions):
self.app = app
self.user = user
self.args = args
self.config = config.load_config()
self.options = options
self.loop = None # late init, set in `create`
self.screen = screen
@ -146,7 +137,6 @@ class TUI(urwid.Frame):
self.can_translate = False
self.account = None
self.followed_accounts = []
self.media_viewer = settings.get_setting("tui.media_viewer", str)
super().__init__(self.body, header=self.header, footer=self.footer)
@ -510,8 +500,15 @@ class TUI(urwid.Frame):
if not urls:
return
if self.media_viewer:
subprocess.run([self.media_viewer] + urls)
media_viewer = self.options.media_viewer
if media_viewer:
try:
subprocess.run([media_viewer] + urls)
except FileNotFoundError:
self.footer.set_error_message(f"Media viewer not found: '{media_viewer}'")
except Exception as ex:
self.exception = ex
self.footer.set_error_message("Failed invoking media viewer. Press X to see exception.")
else:
self.footer.set_error_message("Media viewer not configured")

View File

@ -79,7 +79,7 @@ class Timeline(urwid.Columns):
return urwid.ListBox(walker)
def build_list_item(self, status):
item = StatusListItem(status, self.tui.args.relative_datetimes)
item = StatusListItem(status, self.tui.options.relative_datetimes)
urwid.connect_signal(item, "click", lambda *args:
self.tui.show_context_menu(status))
return urwid.AttrMap(item, None, focus_map={
@ -95,7 +95,7 @@ class Timeline(urwid.Columns):
return None
poll = status.original.data.get("poll")
show_media = status.original.data["media_attachments"] and self.tui.media_viewer
show_media = status.original.data["media_attachments"] and self.tui.options.media_viewer
options = [
"[A]ccount" if not status.is_mine else "",
@ -107,7 +107,6 @@ class Timeline(urwid.Columns):
"[T]hread" if not self.is_thread else "",
"L[i]nks",
"[M]edia" if show_media else "",
self.tui.media_viewer,
"[R]eply",
"[P]oll" if poll and not poll["expired"] else "",
"So[u]rce",