mirror of
https://github.com/ihabunek/toot.git
synced 2025-06-30 22:18:36 -04:00
Rework paging to take terminal height into account
This commit is contained in:
parent
bfcf623448
commit
ecc8033a41
@ -1,5 +1,6 @@
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
from typing import Iterable, Optional, Tuple
|
import shutil
|
||||||
|
from typing import Iterable, List, Optional, Tuple
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
import click
|
import click
|
||||||
@ -12,11 +13,12 @@ from toot.cli.validators import validate_instance, validate_positive
|
|||||||
from toot.entities import (
|
from toot.entities import (
|
||||||
Account,
|
Account,
|
||||||
Status,
|
Status,
|
||||||
|
from_dict_list,
|
||||||
from_response,
|
from_response,
|
||||||
from_response_list,
|
from_response_list,
|
||||||
from_responses_batched,
|
from_responses_batched,
|
||||||
)
|
)
|
||||||
from toot.output import get_continue, print_timeline
|
from toot.output import get_continue, get_max_width, get_terminal_height, get_terminal_width, print_timeline, status_lines
|
||||||
from toot.utils import drop_empty_values, str_bool_nullable
|
from toot.utils import drop_empty_values, str_bool_nullable
|
||||||
|
|
||||||
|
|
||||||
@ -46,17 +48,14 @@ def common_timeline_options(func):
|
|||||||
@click.option(
|
@click.option(
|
||||||
"-p",
|
"-p",
|
||||||
"--pager",
|
"--pager",
|
||||||
help="Page the results, optionally define how many results to show per page",
|
help="Page the results",
|
||||||
type=int,
|
is_flag=True,
|
||||||
callback=validate_positive,
|
|
||||||
is_flag=False,
|
|
||||||
flag_value=10,
|
|
||||||
)
|
)
|
||||||
@click.option(
|
@click.option(
|
||||||
"-c",
|
"-c",
|
||||||
"--clear",
|
"--clear/--no-clear",
|
||||||
help="Clear the screen before printing. If paged, clear before each page.",
|
help="Clear the screen before printing. If paged, clear before each page.",
|
||||||
is_flag=True,
|
default=True,
|
||||||
)
|
)
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
@ -92,7 +91,7 @@ def account(
|
|||||||
max_id: Optional[str],
|
max_id: Optional[str],
|
||||||
since_id: Optional[str],
|
since_id: Optional[str],
|
||||||
limit: Optional[int],
|
limit: Optional[int],
|
||||||
pager: Optional[int],
|
pager: bool,
|
||||||
clear: bool,
|
clear: bool,
|
||||||
json: bool,
|
json: bool,
|
||||||
):
|
):
|
||||||
@ -120,7 +119,7 @@ def home(
|
|||||||
max_id: Optional[str],
|
max_id: Optional[str],
|
||||||
since_id: Optional[str],
|
since_id: Optional[str],
|
||||||
limit: Optional[int],
|
limit: Optional[int],
|
||||||
pager: Optional[int],
|
pager: bool,
|
||||||
clear: bool,
|
clear: bool,
|
||||||
json: bool,
|
json: bool,
|
||||||
):
|
):
|
||||||
@ -148,7 +147,7 @@ def link(
|
|||||||
max_id: Optional[str],
|
max_id: Optional[str],
|
||||||
since_id: Optional[str],
|
since_id: Optional[str],
|
||||||
limit: Optional[int],
|
limit: Optional[int],
|
||||||
pager: Optional[int],
|
pager: bool,
|
||||||
clear: bool,
|
clear: bool,
|
||||||
json: bool,
|
json: bool,
|
||||||
):
|
):
|
||||||
@ -170,19 +169,19 @@ def link(
|
|||||||
_show_timeline(ctx, path, params, json, pager, clear, limit)
|
_show_timeline(ctx, path, params, json, pager, clear, limit)
|
||||||
|
|
||||||
|
|
||||||
@timelines.command()
|
@timelines.command("list")
|
||||||
@click.argument("list_name_or_id")
|
@click.argument("list_name_or_id")
|
||||||
@common_timeline_options
|
@common_timeline_options
|
||||||
@json_option
|
@json_option
|
||||||
@pass_context
|
@pass_context
|
||||||
def list(
|
def list_cmd(
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
list_name_or_id: str,
|
list_name_or_id: str,
|
||||||
min_id: Optional[str],
|
min_id: Optional[str],
|
||||||
max_id: Optional[str],
|
max_id: Optional[str],
|
||||||
since_id: Optional[str],
|
since_id: Optional[str],
|
||||||
limit: Optional[int],
|
limit: Optional[int],
|
||||||
pager: Optional[int],
|
pager: bool,
|
||||||
clear: bool,
|
clear: bool,
|
||||||
json: bool,
|
json: bool,
|
||||||
):
|
):
|
||||||
@ -230,7 +229,7 @@ def public(
|
|||||||
max_id: Optional[str],
|
max_id: Optional[str],
|
||||||
since_id: Optional[str],
|
since_id: Optional[str],
|
||||||
limit: Optional[int],
|
limit: Optional[int],
|
||||||
pager: Optional[int],
|
pager: bool,
|
||||||
clear: bool,
|
clear: bool,
|
||||||
local: Optional[bool],
|
local: Optional[bool],
|
||||||
remote: Optional[bool],
|
remote: Optional[bool],
|
||||||
@ -303,7 +302,7 @@ def tag(
|
|||||||
max_id: Optional[str],
|
max_id: Optional[str],
|
||||||
since_id: Optional[str],
|
since_id: Optional[str],
|
||||||
limit: Optional[int],
|
limit: Optional[int],
|
||||||
pager: Optional[int],
|
pager: bool,
|
||||||
clear: bool,
|
clear: bool,
|
||||||
local: Optional[bool],
|
local: Optional[bool],
|
||||||
remote: Optional[bool],
|
remote: Optional[bool],
|
||||||
@ -381,18 +380,33 @@ def _print_single(response: Response, clear: bool, limit: Optional[int]):
|
|||||||
dim=True,
|
dim=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
click.echo("No statuses found containing the given tag")
|
click.echo("No statuses found")
|
||||||
|
|
||||||
|
|
||||||
def _print_paged(responses: Iterable[Response], page_size: int, clear: bool):
|
def _print_paged(responses: Iterable[Response], page_size: int, clear: bool):
|
||||||
|
width = get_max_width()
|
||||||
|
height = get_terminal_height()
|
||||||
|
separator = "─" * width
|
||||||
|
|
||||||
|
def _page_generator():
|
||||||
|
batch_lines: List[str] = []
|
||||||
|
for response in responses:
|
||||||
|
statuses = from_dict_list(Status, response.json())
|
||||||
|
for status in statuses:
|
||||||
|
lines = [separator] + list(status_lines(status))
|
||||||
|
if len(batch_lines) + len(lines) > height - 2 and batch_lines:
|
||||||
|
yield "\n".join(batch_lines) + "\n" + separator
|
||||||
|
batch_lines = []
|
||||||
|
batch_lines.extend(lines)
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
printed_any = False
|
printed_any = False
|
||||||
for page in from_responses_batched(responses, Status, page_size):
|
for page in _page_generator():
|
||||||
if not first and not get_continue():
|
if not first and not get_continue():
|
||||||
break
|
break
|
||||||
if clear:
|
if clear:
|
||||||
click.clear()
|
click.clear()
|
||||||
print_timeline(page)
|
click.echo(page)
|
||||||
first = False
|
first = False
|
||||||
printed_any = True
|
printed_any = True
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@ def get_terminal_width() -> int:
|
|||||||
return shutil.get_terminal_size().columns
|
return shutil.get_terminal_size().columns
|
||||||
|
|
||||||
|
|
||||||
|
def get_terminal_height() -> int:
|
||||||
|
return shutil.get_terminal_size().lines
|
||||||
|
|
||||||
|
|
||||||
def get_width() -> int:
|
def get_width() -> int:
|
||||||
return min(get_terminal_width(), get_max_width())
|
return min(get_terminal_width(), get_max_width())
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user