mirror of
https://github.com/ihabunek/toot.git
synced 2024-09-29 04:35:54 -04:00
Pass tui options through cli options
This commit is contained in:
parent
ac77ea75ce
commit
bbf67c6736
@ -20,6 +20,17 @@ T = t.TypeVar("T")
|
|||||||
PRIVACY_CHOICES = ["public", "unlisted", "private"]
|
PRIVACY_CHOICES = ["public", "unlisted", "private"]
|
||||||
VISIBILITY_CHOICES = ["public", "unlisted", "private", "direct"]
|
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
|
DURATION_EXAMPLES = """e.g. "1 day", "2 hours 30 minutes", "5 minutes 30
|
||||||
seconds" or any combination of above. Shorthand: "1d", "2h30m", "5m30s\""""
|
seconds" or any combination of above. Shorthand: "1d", "2h30m", "5m30s\""""
|
||||||
|
|
||||||
|
@ -1,17 +1,44 @@
|
|||||||
import click
|
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
|
from toot.tui.app import TUI, TuiOptions
|
||||||
|
|
||||||
|
COLOR_OPTIONS = ", ".join(TUI_COLORS.keys())
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@click.option(
|
@click.option(
|
||||||
"--relative-datetimes",
|
"-r", "--relative-datetimes",
|
||||||
is_flag=True,
|
is_flag=True,
|
||||||
help="Show relative datetimes in status list"
|
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
|
@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"""
|
"""Launches the toot terminal user interface"""
|
||||||
options = TuiOptions(relative_datetimes, ctx.color)
|
if colors is None:
|
||||||
TUI.create(ctx.app, ctx.user, options).run()
|
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()
|
||||||
|
@ -4,6 +4,8 @@ import re
|
|||||||
from click import Context
|
from click import Context
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
from toot.cli.base import TUI_COLORS
|
||||||
|
|
||||||
|
|
||||||
def validate_language(ctx: Context, param: str, value: Optional[str]):
|
def validate_language(ctx: Context, param: str, value: Optional[str]):
|
||||||
if value is None:
|
if value is None:
|
||||||
@ -58,3 +60,16 @@ def validate_instance(ctx: click.Context, param: str, value: Optional[str]):
|
|||||||
|
|
||||||
value = value.rstrip("/")
|
value = value.rstrip("/")
|
||||||
return value if value.startswith("http") else f"https://{value}"
|
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)}")
|
||||||
|
@ -25,6 +25,10 @@ def get_width() -> int:
|
|||||||
return min(get_terminal_width(), get_max_width())
|
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):
|
def print_instance(instance: Instance):
|
||||||
width = get_width()
|
width = get_width()
|
||||||
click.echo(instance_to_text(instance, width))
|
click.echo(instance_to_text(instance, width))
|
||||||
|
@ -3,7 +3,7 @@ import subprocess
|
|||||||
import urwid
|
import urwid
|
||||||
|
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from typing import NamedTuple
|
from typing import NamedTuple, Optional
|
||||||
|
|
||||||
from toot import api, config, __version__, settings
|
from toot import api, config, __version__, settings
|
||||||
from toot import App, User
|
from toot import App, User
|
||||||
@ -28,8 +28,9 @@ DEFAULT_MAX_TOOT_CHARS = 500
|
|||||||
|
|
||||||
|
|
||||||
class TuiOptions(NamedTuple):
|
class TuiOptions(NamedTuple):
|
||||||
|
colors: int
|
||||||
|
media_viewer: Optional[str]
|
||||||
relative_datetimes: bool
|
relative_datetimes: bool
|
||||||
color: bool
|
|
||||||
|
|
||||||
|
|
||||||
class Header(urwid.WidgetWrap):
|
class Header(urwid.WidgetWrap):
|
||||||
@ -89,7 +90,9 @@ class TUI(urwid.Frame):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def create(app: App, user: User, args: TuiOptions):
|
def create(app: App, user: User, args: TuiOptions):
|
||||||
"""Factory method, sets up TUI and an event loop."""
|
"""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)
|
tui = TUI(app, user, screen, args)
|
||||||
|
|
||||||
palette = PALETTE.copy()
|
palette = PALETTE.copy()
|
||||||
@ -108,23 +111,11 @@ class TUI(urwid.Frame):
|
|||||||
|
|
||||||
return tui
|
return tui
|
||||||
|
|
||||||
@staticmethod
|
def __init__(self, app, user, screen, options: TuiOptions):
|
||||||
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):
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.user = user
|
self.user = user
|
||||||
self.args = args
|
|
||||||
self.config = config.load_config()
|
self.config = config.load_config()
|
||||||
|
self.options = options
|
||||||
|
|
||||||
self.loop = None # late init, set in `create`
|
self.loop = None # late init, set in `create`
|
||||||
self.screen = screen
|
self.screen = screen
|
||||||
@ -146,7 +137,6 @@ class TUI(urwid.Frame):
|
|||||||
self.can_translate = False
|
self.can_translate = False
|
||||||
self.account = None
|
self.account = None
|
||||||
self.followed_accounts = []
|
self.followed_accounts = []
|
||||||
self.media_viewer = settings.get_setting("tui.media_viewer", str)
|
|
||||||
|
|
||||||
super().__init__(self.body, header=self.header, footer=self.footer)
|
super().__init__(self.body, header=self.header, footer=self.footer)
|
||||||
|
|
||||||
@ -510,8 +500,15 @@ class TUI(urwid.Frame):
|
|||||||
if not urls:
|
if not urls:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.media_viewer:
|
media_viewer = self.options.media_viewer
|
||||||
subprocess.run([self.media_viewer] + urls)
|
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:
|
else:
|
||||||
self.footer.set_error_message("Media viewer not configured")
|
self.footer.set_error_message("Media viewer not configured")
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class Timeline(urwid.Columns):
|
|||||||
return urwid.ListBox(walker)
|
return urwid.ListBox(walker)
|
||||||
|
|
||||||
def build_list_item(self, status):
|
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:
|
urwid.connect_signal(item, "click", lambda *args:
|
||||||
self.tui.show_context_menu(status))
|
self.tui.show_context_menu(status))
|
||||||
return urwid.AttrMap(item, None, focus_map={
|
return urwid.AttrMap(item, None, focus_map={
|
||||||
@ -95,7 +95,7 @@ class Timeline(urwid.Columns):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
poll = status.original.data.get("poll")
|
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 = [
|
options = [
|
||||||
"[A]ccount" if not status.is_mine else "",
|
"[A]ccount" if not status.is_mine else "",
|
||||||
@ -107,7 +107,6 @@ class Timeline(urwid.Columns):
|
|||||||
"[T]hread" if not self.is_thread else "",
|
"[T]hread" if not self.is_thread else "",
|
||||||
"L[i]nks",
|
"L[i]nks",
|
||||||
"[M]edia" if show_media else "",
|
"[M]edia" if show_media else "",
|
||||||
self.tui.media_viewer,
|
|
||||||
"[R]eply",
|
"[R]eply",
|
||||||
"[P]oll" if poll and not poll["expired"] else "",
|
"[P]oll" if poll and not poll["expired"] else "",
|
||||||
"So[u]rce",
|
"So[u]rce",
|
||||||
|
Loading…
Reference in New Issue
Block a user