Skip to content

Commit

Permalink
feat: use a table for apy list
Browse files Browse the repository at this point in the history
refer: #88
  • Loading branch information
lervag committed Jun 7, 2024
1 parent 8cbf8c1 commit 73d58b7
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 14 deletions.
9 changes: 8 additions & 1 deletion completion/_apy
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,14 @@ _apy() {
list)
opts=( \
'::Query' \
'(-v --verbose)'{-v,--verbose}'[Be verbose]' \
'(-w --wrap)'{-w,--wrap}'[Wrap the question and answer on multiple lines]' \
'(-a --show-answer)'{-a,--show-answer}'[Display answer]' \
'(-m --show-model)'{-m,--show-model}'[Display model]' \
'(-c --show-cid)'{-c,--show-cid}'[Display card ids]' \
'(-d --show-due)'{-d,--show-due}'[Display card due time in days]' \
'(-t --show-type)'{-t,--show-type}'[Display card type]' \
'(-e --show-ease)'{-e,--show-ease}'[Display card ease]' \
'(-l --show-lapses)'{-l,--show-lapses}'[Display card number of lapses]' \
$opts_help \
);;
review)
Expand Down
61 changes: 56 additions & 5 deletions src/apyanki/anki.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from click import Abort
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.table import Table
from rich.text import Text

from apyanki import cards
from apyanki.config import cfg
Expand Down Expand Up @@ -386,15 +387,65 @@ def list_notes(self, query: str) -> None:
for note in self.find_notes(query):
cards.print_question(note.n.cards()[0])

def list_cards(self, query: str, verbose: bool = False) -> None:
def list_cards(
self, query: str, opts_display: dict[str, bool], no_wrap: bool = False
) -> None:
"""List cards that match a query"""
width = console.width - 1
if opts_display.get("show_cid", False):
width -= 15
if opts_display.get("show_due", False):
width -= 6
if opts_display.get("show_type", False):
width -= 7
if opts_display.get("show_ease", False):
width -= 7
if opts_display.get("show_lapses", False):
width -= 5
if opts_display.get("show_model", False):
width -= 12
if opts_display.get("show_answer", False):
width //= 2
width -= 1

table = Table(box=None, header_style="bold white")
table.add_column("question", no_wrap=no_wrap, max_width=width)
if opts_display.get("show_answer", False):
table.add_column("answer", no_wrap=no_wrap, max_width=width)
if opts_display.get("show_cid", False):
table.add_column("cid", min_width=13)
if opts_display.get("show_due", False):
table.add_column("due", min_width=4)
if opts_display.get("show_type", False):
table.add_column("type", min_width=5)
if opts_display.get("show_ease", False):
table.add_column("ease", min_width=5)
if opts_display.get("show_lapses", False):
table.add_column("lapses", min_width=3)
if opts_display.get("show_model", False):
table.add_column("model", min_width=10)

for cid in self.find_cards(query):
card = self.col.get_card(cid)
cards.print_question(card)
row: list[str | Text] = [cards.card_field_to_text(card.question())]
if opts_display.get("show_answer", False):
row += [cards.card_field_to_text(card.answer())]
if opts_display.get("show_cid", False):
row += [str(card.id)]
if opts_display.get("show_due", False):
row += [str(card.due)]
if opts_display.get("show_type", False):
card_type = ["new", "learning", "review", "relearning"][int(card.type)]
row += [card_type]
if opts_display.get("show_ease", False):
row += [str(card.factor / 10)]
if opts_display.get("show_lapses", False):
row += [str(card.lapses)]
if opts_display.get("show_model", False):
row += [card.note_type()["name"]]
table.add_row(*row)

if verbose:
cards.print_answer(card)
cards.print_stats(card)
console.print(table)

def add_notes_with_editor(
self,
Expand Down
10 changes: 6 additions & 4 deletions src/apyanki/cards.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@
from anki.cards import Card


def card_field_to_text(field: str) -> Text:
return Text.from_markup(prepare_field_for_cli_oneline(field))


def print_question(card: Card) -> None:
"""Print the card question"""
question = Text("Q: ")
question.stylize("yellow", 0, 2)
question.append_text(
Text.from_markup(prepare_field_for_cli_oneline(card.question()))
)
question.append_text(card_field_to_text(card.question()))
console.print(question.fit(console.width))


def print_answer(card: Card) -> None:
"""Print the card answer"""
answer = Text("A: ")
answer.stylize("yellow", 0, 2)
answer.append_text(Text.from_markup(prepare_field_for_cli_oneline(card.answer())))
answer.append_text(card_field_to_text(card.answer()))
console.print(answer.fit(console.width))


Expand Down
37 changes: 34 additions & 3 deletions src/apyanki/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,27 @@ def rename(old_name: str, new_name: str) -> None:

@main.command("list")
@click.argument("query", required=False, nargs=-1)
@click.option("-v", "--verbose", is_flag=True, help="Be verbose, show more info")
def list_cards(query: str, verbose: bool) -> None:
@click.option(
"-w", "--wrap", is_flag=True, help="Wrap the question and answer on multiple lines"
)
@click.option("-a", "--show-answer", is_flag=True, help="Display answer")
@click.option("-m", "--show-model", is_flag=True, help="Display model")
@click.option("-c", "--show-cid", is_flag=True, help="Display card ids")
@click.option("-d", "--show-due", is_flag=True, help="Display card due time in days")
@click.option("-t", "--show-type", is_flag=True, help="Display card type")
@click.option("-e", "--show-ease", is_flag=True, help="Display card ease")
@click.option("-l", "--show-lapses", is_flag=True, help="Display card number of lapses")
def list_cards(
query: str,
wrap: bool,
show_answer: bool,
show_model: bool,
show_due: bool,
show_type: bool,
show_ease: bool,
show_lapses: bool,
show_cid: bool,
) -> None:
"""List cards that match QUERY.
The default QUERY is "tag:marked OR -flag:0". This default can be
Expand All @@ -339,7 +358,19 @@ def list_cards(query: str, verbose: bool) -> None:
query = cfg["query"]

with Anki(**cfg) as a:
a.list_cards(query, verbose)
a.list_cards(
query,
{
"show_answer": show_answer,
"show_model": show_model,
"show_cid": show_cid,
"show_due": show_due,
"show_type": show_type,
"show_ease": show_ease,
"show_lapses": show_lapses,
},
no_wrap=not wrap,
)


@main.command()
Expand Down
2 changes: 1 addition & 1 deletion src/apyanki/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def prepare_field_for_cli_oneline(field: str) -> str:
text = prepare_field_for_cli(field)

text = text.replace("\n", " ")
text = re.sub(r"\s\s\s+", " ", text)
text = re.sub(r"\s\s+", " ", text)
return text


Expand Down

0 comments on commit 73d58b7

Please sign in to comment.