Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# AgiNG ChangeLog

## Unreleased

**Released: WiP**

- Added the ability to copy the credits of a guide from the About dialog.
([#55](https://github.com/davep/aging/pull/55))

## v1.1.1

**Released: 2025-12-12**
Expand Down
28 changes: 28 additions & 0 deletions src/aging/aging.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
# Python imports.
from argparse import Namespace

##############################################################################
# Pyperclip imports.
from pyperclip import PyperclipException
from pyperclip import copy as copy_to_clipboard

##############################################################################
# Textual imports.
from textual import on
from textual.app import InvalidThemeError, ScreenStackError

##############################################################################
Expand All @@ -19,6 +25,7 @@
load_configuration,
update_configuration,
)
from .messages import CopyToClipboard
from .screens import Main


Expand Down Expand Up @@ -81,5 +88,26 @@ def get_default_screen(self) -> Main:
"""Get the main screen for the application."""
return Main(self._arguments)

@on(CopyToClipboard)
def _copy_text_to_clipbaord(self, message: CopyToClipboard) -> None:
"""Copy some text into the clipboard.

Args:
message: The message requesting the text be copied.
"""
# First off, use Textual's own copy to clipboard facility. Generally
# this will work in most terminals, and if it does it'll likely work
# best, getting the text through remote connections to the user's
# own environment.
self.copy_to_clipboard(message.text)
# However, as a backup, use pyerclip too. If the above did fail due
# to the terminal not supporting the operation, this might work.
try:
copy_to_clipboard(message.text)
except PyperclipException:
pass
# Give the user some feedback.
self.notify(f"Copied {message.description or ''}".strip())


### aging.py ends here
36 changes: 26 additions & 10 deletions src/aging/screens/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
# Textual enhanced imports.
from textual_enhanced.tools import add_key

##############################################################################
# Local imports.
from ..messages.clipboard import CopyToClipboard


##############################################################################
class Title(Label):
Expand Down Expand Up @@ -62,6 +66,10 @@ class About(ModalScreen[None]):
border-top: solid $border;
width: 100%;
height: auto;

#copy {
margin-left: 1;
}
}

Title, {
Expand All @@ -81,7 +89,7 @@ class About(ModalScreen[None]):
}
"""

BINDINGS = [("escape", "dismiss(None)")]
BINDINGS = [("c", "copy_credits"), ("escape", "dismiss(None)")]

def __init__(self, guide: NortonGuide) -> None:
"""Initialise the object.
Expand All @@ -93,17 +101,17 @@ def __init__(self, guide: NortonGuide) -> None:
"""The guide we're viewing."""
super().__init__()

@property
def _credits(self) -> str:
"""The credits of the guide as a single string."""
return "\n".join(make_dos_like(line) for line in self._guide.credits)

def compose(self) -> ComposeResult:
"""Compose the content of the screen."""
with Vertical() as dialog:
dialog.border_title = f"About {self._guide.path.name}"
if any(line.strip() for line in self._guide.credits):
yield (
data := Data(
"\n".join(make_dos_like(line) for line in self._guide.credits),
id="credits",
)
)
if has_credits := any(line.strip() for line in self._guide.credits):
yield (data := Data(self._credits, id="credits"))
data.border_title = "Credits"
yield Title("Made With:")
yield Data(self._guide.made_with)
Expand All @@ -116,12 +124,20 @@ def compose(self) -> ComposeResult:
f"{datetime.fromtimestamp(int(self._guide.path.stat().st_ctime))}"
)
with Horizontal(id="buttons"):
yield Button(add_key("Close", "Esc", self))
yield Button(add_key("Close", "Esc", self), id="close")
if has_credits:
yield Button(add_key("Copy Credits", "c", self), id="copy")

@on(Button.Pressed)
@on(Button.Pressed, "#close")
def _close_about(self) -> None:
"""Close the about dialog."""
self.dismiss(None)

@on(Button.Pressed, "#copy")
def action_copy_credits(self) -> None:
"""Copy the credits to the clipboard."""
if self.query("#copy"):
self.post_message(CopyToClipboard(self._credits, "the guide's credits"))


### about.py ends here
26 changes: 0 additions & 26 deletions src/aging/screens/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
# NGDB imports.
from ngdb import Long, NGDBError, NortonGuide, PlainText, Short, make_dos_like

##############################################################################
# Pyperclip imports.
from pyperclip import PyperclipException
from pyperclip import copy as copy_to_clipboard

##############################################################################
# Textual imports.
from textual import on, work
Expand Down Expand Up @@ -470,27 +465,6 @@ def action_change_guides_side_command(self) -> None:
"""Change which side the guides directory is docked to."""
self.guides_on_right = not self.guides_on_right

@on(CopyToClipboard)
def _copy_text_to_clipbaord(self, message: CopyToClipboard) -> None:
"""Copy some text into the clipboard.

Args:
message: The message requesting the text be copied.
"""
# First off, use Textual's own copy to clipboard facility. Generally
# this will work in most terminals, and if it does it'll likely work
# best, getting the text through remote connections to the user's
# own environment.
self.app.copy_to_clipboard(message.text)
# However, as a backup, use pyerclip too. If the above did fail due
# to the terminal not supporting the operation, this might.
try:
copy_to_clipboard(message.text)
except PyperclipException:
pass
# Give the user some feedback.
self.notify(f"Copied {message.description or ''}".strip())

@property
def _entry_text(self) -> str:
"""The text of the current entry."""
Expand Down