Skip to content

Commit

Permalink
Merge pull request ggozad#61 from ggozad/export
Browse files Browse the repository at this point in the history
Export chat as markdown document
  • Loading branch information
ggozad authored Feb 16, 2024
2 parents f10d079 + 4877f97 commit 1ac0d25
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

0.2.1 -
------------------

- Export chat as markdown document.
[ggozad]

0.2.0 - 2024-02-14
------------------

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The following keyboard shortcuts are available:
* `ctrl+n` - create a new chat session
* `ctrl+e` - edit the chat session (change template, system prompt or format)
* `ctrl+r` - rename the current chat session
* `ctrl+s` - export the current chat session as markdown
* `ctrl+x` - delete the current chat session
* `ctrl+t` - toggle between dark/light theme
* `ctrl+q` - quit
Expand Down
56 changes: 56 additions & 0 deletions oterm/app/chat_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import re
import unicodedata
from typing import Sequence

from textual import on
from textual.app import ComposeResult
from textual.containers import Container
from textual.screen import ModalScreen
from textual.widgets import Input, Label


def slugify(value):
"""
Taken from https://github.com/django/django/blob/master/django/utils/text.py
"""
value = str(value)
value = (
unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
)
value = re.sub(r"[^\w\s-]", "", value.lower())
return re.sub(r"[-\s]+", "-", value).strip("-_")


class ChatExport(ModalScreen[str]):
chat_id: int
file_name: str = ""
BINDINGS = [
("escape", "cancel", "Cancel"),
]

def action_cancel(self) -> None:
self.dismiss()

@on(Input.Submitted)
async def on_submit(self, event: Input.Submitted) -> None:
from oterm.app.widgets.chat import Author

if not event.value:
return

messages: Sequence[tuple[Author, str]] = await self.app.store.get_messages(
self.chat_id
)
with open(event.value, "w") as file:
for message in messages:
author, text = message
file.write(f"*{author.value}*\n")
file.write(f"{text}\n")
file.write("\n---\n")

self.dismiss()

def compose(self) -> ComposeResult:
with Container(id="chat-export-container"):
yield Label("Export chat", classes="title")
yield Input(id="chat-name-input", value=self.file_name)
2 changes: 1 addition & 1 deletion oterm/app/chat_rename.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ async def on_submit(self, event: Input.Submitted) -> None:
def compose(self) -> ComposeResult:
with Container(id="chat-rename-container"):
yield Label("Rename chat", classes="title")
yield Input(id="chat-rename-input", value=self.old_name)
yield Input(id="chat-name-input", value=self.old_name)
6 changes: 3 additions & 3 deletions oterm/app/oterm.tcss
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ LoadingIndicator {
color: $secondary;
}

#chat-rename-container {
#chat-rename-container, #chat-export-container {
width: 80%;
height: 10;
background: $panel;
Expand All @@ -140,11 +140,11 @@ LoadingIndicator {
padding: 1;
}

#chat-rename-container .title {
#chat-rename-container .title, #chat-export-container .title {
color: $secondary;
}

#chat-rename-input {
#chat-name-input {
margin: 2;
}
#image-select-container {
Expand Down
8 changes: 8 additions & 0 deletions oterm/app/widgets/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
)

from oterm.app.chat_edit import ChatEdit
from oterm.app.chat_export import ChatExport, slugify
from oterm.app.chat_rename import ChatRename
from oterm.app.widgets.image import ImageAdded
from oterm.app.widgets.prompt import FlexibleInput
Expand All @@ -41,6 +42,7 @@ class ChatContainer(Widget):

BINDINGS = [
Binding("ctrl+e", "edit_chat", "edit", priority=True),
Binding("ctrl+s", "export", "export", priority=True),
("ctrl+r", "rename_chat", "rename"),
("ctrl+x", "forget_chat", "forget"),
Binding(
Expand Down Expand Up @@ -184,6 +186,12 @@ async def on_model_select(model_info: str) -> None:
if self.system:
screen.system = self.system

async def action_export(self) -> None:
screen = ChatExport()
screen.chat_id = self.db_id
screen.file_name = f"{slugify(self.chat_name)}.md"
self.app.push_screen(screen)

async def action_rename_chat(self) -> None:
async def on_chat_rename(name: str) -> None:
tabs = self.app.query_one(TabbedContent)
Expand Down

0 comments on commit 1ac0d25

Please sign in to comment.