Merge pull request #334 from danschwarz/osc52

Add cop[y] status feature - copies status text to clipboard
This commit is contained in:
Ivan Habunek 2023-03-07 11:01:50 +01:00 committed by GitHub
commit 9d51546be3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 1 deletions

View File

@ -14,7 +14,7 @@ from .overlays import ExceptionStackTrace, GotoMenu, Help, StatusSource, StatusL
from .overlays import StatusDeleteConfirmation, Account
from .poll import Poll
from .timeline import Timeline
from .utils import parse_content_links, show_media
from .utils import parse_content_links, show_media, copy_to_clipboard
logger = logging.getLogger(__name__)
@ -111,6 +111,7 @@ class TUI(urwid.Frame):
self.overlay = None
self.exception = None
self.can_translate = False
self.screen = urwid.raw_display.Screen()
super().__init__(self.body, header=self.header, footer=self.footer)
@ -210,6 +211,9 @@ class TUI(urwid.Frame):
def _clear(*args):
self.clear_screen()
def _copy(timeline, status):
self.copy_status(status)
urwid.connect_signal(timeline, "account", _account)
urwid.connect_signal(timeline, "bookmark", self.async_toggle_bookmark)
urwid.connect_signal(timeline, "compose", _compose)
@ -226,6 +230,7 @@ class TUI(urwid.Frame):
urwid.connect_signal(timeline, "zoom", _zoom)
urwid.connect_signal(timeline, "translate", self.async_translate)
urwid.connect_signal(timeline, "clear-screen", _clear)
urwid.connect_signal(timeline, "copy-status", _copy)
def build_timeline(self, name, statuses, local):
def _close(*args):
@ -657,6 +662,12 @@ class TUI(urwid.Frame):
return self.run_in_thread(_delete, done_callback=_done)
def copy_status(self, status):
# TODO: copy a better version of status content
# including URLs
copy_to_clipboard(self.screen, status.original.data["content"])
self.footer.set_message(f"Status {status.original.id} copied")
# --- Overlay handling -----------------------------------------------------
default_overlay_options = dict(

View File

@ -206,6 +206,7 @@ class Help(urwid.Padding):
yield urwid.Text(h(" [L] - Show the status links"))
yield urwid.Text(h(" [U] - Show the status data in JSON as received from the server"))
yield urwid.Text(h(" [V] - Open status in default browser"))
yield urwid.Text(h(" [Y] - Copy status to clipboard"))
yield urwid.Text(h(" [Z] - Open status in scrollable popup window"))
yield urwid.Divider()
yield urwid.Text(("bold", "Links"))

View File

@ -41,6 +41,7 @@ class Timeline(urwid.Columns):
"save", # Save current timeline
"zoom", # Open status in scrollable popup window
"clear-screen", # Clear the screen (used internally)
"copy-status", # Copy status to clipboard
]
def __init__(self, name, statuses, can_translate, followed_tags=[], focus=0, is_thread=False):
@ -120,6 +121,7 @@ class Timeline(urwid.Columns):
"So[u]rce",
"[Z]oom",
"Tra[n]slate" if self.can_translate else "",
"Cop[y]",
"[H]elp",
]
options = "\n" + " ".join(o for o in options if o)
@ -261,6 +263,10 @@ class Timeline(urwid.Columns):
self._emit("poll", status)
return
if key in ("y", "Y"):
self._emit("copy-status", status)
return
return super().keypress(size, key)
def append_status(self, status):

View File

@ -1,3 +1,5 @@
import base64
import urwid
from html.parser import HTMLParser
import math
import os
@ -144,3 +146,20 @@ def parse_content_links(content):
parser = LinkParser()
parser.feed(content)
return parser.links[:]
def copy_to_clipboard(screen: urwid.raw_display.Screen, text: str):
""" copy text to clipboard using OSC 52
This escape sequence is documented
here https://iterm2.com/documentation-escape-codes.html
It has wide support - XTerm, Windows Terminal,
Kitty, iTerm2, others. Some terminals may require a setting to be
enabled in order to use OSC 52 clipboard functions.
"""
text_bytes = text.encode("utf-8")
b64_bytes = base64.b64encode(text_bytes)
b64_text = b64_bytes.decode("utf-8")
screen.write(f"\033]52;c;{b64_text}\a")
screen.flush()