Skip to content

Commit

Permalink
Added --plaintext option to command line tools
Browse files Browse the repository at this point in the history
Now we default to markdown when displaying
status messages; the --plaintext option reverts
to previous behavior. This switch is used in
test_console.py so existing tests will pass;
we can add tests in future without --plaintext
to test the markdown rendering.
  • Loading branch information
danschwarz committed Nov 28, 2023
1 parent 8cb294f commit 4be27f8
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[test,richtext]"
pip install -e ".[test,richtext,markdown]"
- name: Run tests
run: |
pytest
Expand Down
8 changes: 4 additions & 4 deletions tests/test_console.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def test_timeline(mock_get, monkeypatch, capsys):
'media_attachments': [],
}])

console.run_command(app, user, 'timeline', ['--once'])
console.run_command(app, user, 'timeline', ['--once', '--plaintext'])

mock_get.assert_called_once_with(app, user, '/api/v1/timelines/home', {'limit': 10})

Expand Down Expand Up @@ -175,7 +175,7 @@ def test_timeline_with_re(mock_get, monkeypatch, capsys):
'media_attachments': [],
}])

console.run_command(app, user, 'timeline', ['--once'])
console.run_command(app, user, 'timeline', ['--once', '--plaintext'])

mock_get.assert_called_once_with(app, user, '/api/v1/timelines/home', {'limit': 10})

Expand Down Expand Up @@ -237,7 +237,7 @@ def test_thread(mock_get, monkeypatch, capsys):
}),
]

console.run_command(app, user, 'thread', ['111111111111111111'])
console.run_command(app, user, 'thread', ['--plaintext', '111111111111111111'])

calls = [
mock.call(app, user, '/api/v1/statuses/111111111111111111'),
Expand Down Expand Up @@ -553,7 +553,7 @@ def test_notifications(mock_get, capsys):
},
}])

console.run_command(app, user, 'notifications', [])
console.run_command(app, user, 'notifications', ['--plaintext'])

mock_get.assert_called_once_with(app, user, '/api/v1/notifications', {'exclude_types[]': [], 'limit': 20})

Expand Down
9 changes: 5 additions & 4 deletions toot/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def timeline(app, user, args, generator=None):
items = reversed(items)

statuses = [from_dict(Status, item) for item in items]
print_timeline(statuses)

print_timeline(statuses, render_mode="plaintext" if args.plaintext else "markdown")

if args.once or not sys.stdout.isatty():
break
Expand All @@ -71,7 +72,7 @@ def timeline(app, user, args, generator=None):
def status(app, user, args):
status = api.single_status(app, user, args.status_id)
status = from_dict(Status, status)
print_status(status)
print_status(status, render_mode="plaintext" if args.plaintext else "markdown")


def thread(app, user, args):
Expand All @@ -87,7 +88,7 @@ def thread(app, user, args):
thread.append(item)

statuses = [from_dict(Status, s) for s in thread]
print_timeline(statuses)
print_timeline(statuses, render_mode="plaintext" if args.plaintext else "markdown")


def post(app, user, args):
Expand Down Expand Up @@ -572,7 +573,7 @@ def notifications(app, user, args):
notifications = reversed(notifications)

notifications = [from_dict(Notification, n) for n in notifications]
print_notifications(notifications)
print_notifications(notifications, render_mode="plaintext" if args.plaintext else "markdown")


def tui(app, user, args):
Expand Down
14 changes: 12 additions & 2 deletions toot/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,13 @@ def editor(value):
json_arg = (["--json"], {
"action": "store_true",
"default": False,
"help": "print json instead of plaintext",
"help": "print json instead of standard text",
})

plaintext_arg = (["-pt", "--plaintext"], {
"action": "store_true",
"help": "Render status messages in plaintext, not markdown",
"default": False,
})

# Arguments for selecting a timeline (see `toot.commands.get_timeline_generator`)
Expand Down Expand Up @@ -284,6 +290,7 @@ def editor(value):
"default": False,
"help": "Only show the first <count> toots, do not prompt to continue.",
}),
plaintext_arg,
]

timeline_args = common_timeline_args + timeline_and_bookmark_args
Expand Down Expand Up @@ -426,7 +433,8 @@ def editor(value):
"action": "store_true",
"default": False,
"help": "Only print mentions",
})
}),
plaintext_arg,
],
require_auth=True,
),
Expand Down Expand Up @@ -464,6 +472,7 @@ def editor(value):
(["status_id"], {
"help": "Show thread for toot.",
}),
plaintext_arg,
],
require_auth=True,
),
Expand All @@ -474,6 +483,7 @@ def editor(value):
(["status_id"], {
"help": "ID of the status to show.",
}),
plaintext_arg,
],
require_auth=True,
),
Expand Down
20 changes: 10 additions & 10 deletions toot/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def print_search_results(results):
print_out("<yellow>Nothing found</yellow>")


def print_status(status: Status, width: int = 80):
def print_status(status: Status, width=80, render_mode=""):
status_id = status.id
in_reply_to_id = status.in_reply_to_id
reblogged_by = status.account if status.reblog else None
Expand All @@ -299,7 +299,7 @@ def print_status(status: Status, width: int = 80):
f"<yellow>{time}</yellow>",
)

print_html(status.content, width)
print_html(status.content, width, render_mode=render_mode)

if status.media_attachments:
print_out("\nMedia:")
Expand All @@ -320,8 +320,8 @@ def print_status(status: Status, width: int = 80):
)


def print_html(text, width=80):
markdown = "\n".join(html_to_text(text, columns=width, highlight_tags=False))
def print_html(text, width=80, render_mode=""):
markdown = "\n".join(html_to_text(text, columns=width, render_mode=render_mode, highlight_tags=False))
print_out("")
print_out(markdown)

Expand Down Expand Up @@ -352,10 +352,10 @@ def print_poll(poll: Poll):
print_out(poll_footer)


def print_timeline(items: List[Status], width=100):
def print_timeline(items: List[Status], width=100, render_mode=""):
print_out("─" * width)
for item in items:
print_status(item, width)
print_status(item, width, render_mode=render_mode)
print_out("─" * width)


Expand All @@ -367,7 +367,7 @@ def print_timeline(items: List[Status], width=100):
}


def print_notification(notification: Notification, width=100):
def print_notification(notification: Notification, width=100, render_mode=""):
account = f"{notification.account.display_name} @{notification.account.acct}"
msg = notification_msgs.get(notification.type)
if msg is None:
Expand All @@ -376,10 +376,10 @@ def print_notification(notification: Notification, width=100):
print_out("─" * width)
print_out(msg.format(account=account))
if notification.status:
print_status(notification.status, width)
print_status(notification.status, width, render_mode=render_mode)


def print_notifications(notifications: List[Notification], width=100):
def print_notifications(notifications: List[Notification], render_mode="", width=100):
for notification in notifications:
print_notification(notification)
print_notification(notification, render_mode=render_mode)
print_out("─" * width)
24 changes: 7 additions & 17 deletions toot/richtext/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from toot.tui.utils import highlight_hashtags
from toot.utils import html_to_paragraphs
from toot.wcstring import wc_wrap
from toot.exceptions import ConsoleError
from toot.richtext.plaintext import html_to_plaintext
from typing import List

try:
Expand All @@ -9,17 +8,8 @@

except ImportError:
# Fallback to render in plaintext
def html_to_text(html: str, columns=80, highlight_tags=False) -> List:
output = []
first = True
for paragraph in html_to_paragraphs(html):
if not first:
output.append("")
for line in paragraph:
for subline in wc_wrap(line, columns):
if highlight_tags:
output.append(highlight_hashtags(subline))
else:
output.append(subline)
first = False
return output
def html_to_text(html: str, columns=80, render_mode: str = "", highlight_tags=False) -> List:
if render_mode == "markdown":
raise ConsoleError("Can't render as markdown because the pypandoc library is not available.")

return html_to_plaintext(html, columns, highlight_tags)
20 changes: 13 additions & 7 deletions toot/richtext/markdown.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from toot.exceptions import ConsoleError
from pypandoc import convert_text
from toot.richtext.plaintext import html_to_plaintext
from typing import List


def html_to_text(html: str, columns=80, highlight_tags=False) -> List:
return [convert_text(
html,
format="html",
to="gfm-raw_html",
extra_args=["--wrap=auto", f"--columns={columns}"],
)]
def html_to_text(html: str, columns=80, render_mode: str = "", highlight_tags=False) -> List:
if render_mode == "plaintext":
return html_to_plaintext(html, columns, highlight_tags)
elif render_mode == "markdown" or render_mode == "":
return [convert_text(
html,
format="html",
to="gfm-raw_html",
extra_args=["--wrap=auto", f"--columns={columns}"],
)]
raise ConsoleError("Unknown render mode; specify 'plaintext' or 'markdown'")

0 comments on commit 4be27f8

Please sign in to comment.