Skip to content

Commit

Permalink
Better browswer
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaGusev committed Jul 27, 2024
1 parent a89fe84 commit bfa5a15
Showing 1 changed file with 63 additions and 34 deletions.
97 changes: 63 additions & 34 deletions scripts/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@
import sys
import shutil

from textual import on
from textual.app import App, ComposeResult
from textual.widgets import Footer, MarkdownViewer, Static, Input, Button
from textual.containers import Horizontal


class IndexInput(Static):
def compose(self) -> ComposeResult:
with Horizontal():
yield Input(placeholder="Enter index", id="index_input")
yield Button("Go", variant="primary", id="go_button")
from textual import on, events
from textual.app import App, ComposeResult, Binding
from textual.widgets import Footer, MarkdownViewer, Static, Input
from textual.validation import Number
from textual.containers import Container


class RecordInfo(Static):
def update_info(self, current: int, total: int):
self.update(f"Record {current + 1} of {total}")


class FullScreenLoadingIndicator(Static):
def render(self) -> str:
return "Loading..."


def to_markdown(record):
result = ""
messages = record["messages"]
Expand All @@ -36,16 +35,21 @@ class Browser(App):
("b", "back", "Back"),
("f", "forward", "Forward"),
("s", "save", "Save"),
Binding("g", "go", "Go", show=False, priority=True),
]

def compose(self) -> ComposeResult:
self.path = sys.argv[1]
self.current_idx = 0
with open(sys.argv[1]) as r:
self.records = [json.loads(line) for line in r]
yield MarkdownViewer()
yield Container(
MarkdownViewer(),
FullScreenLoadingIndicator(),
id="main-content"
)
yield RecordInfo()
yield IndexInput()
yield Input(placeholder="Enter index", validators=[Number()], restrict="[0-9]*", valid_empty=True)
yield Footer()

@property
Expand All @@ -61,22 +65,53 @@ def record_info(self) -> RecordInfo:
return self.query_one(RecordInfo)

@property
def index_input(self) -> IndexInput:
return self.query_one(IndexInput)
def input(self) -> Input:
return self.query_one(Input)

@property
def loading_indicator(self) -> FullScreenLoadingIndicator:
return self.query_one(FullScreenLoadingIndicator)

async def show_record(self):
if len(self.records) == 0:
await self.markdown_viewer.document.update("No records left")
self.record_info.update_info(-1, 0)
return

assert self.current_idx < len(self.records)

self.markdown_viewer.display = False
self.loading_indicator.display = True

await self.markdown_viewer.document.update(to_markdown(self.records[self.current_idx]))
self.markdown_viewer.scroll_home(animate=False)
self.record_info.update_info(self.current_idx, len(self.records))

def show_markdown():
self.markdown_viewer.focus()
self.markdown_viewer.display = True
self.loading_indicator.display = False

self.markdown_viewer.scroll_home(animate=False, on_complete=show_markdown)

async def on_mount(self) -> None:
self.loading_indicator.display = False
await self.show_record()

@on(Input.Submitted)
async def goto(self, event: Input.Submitted) -> None:
if not event.validation_result.is_valid:
self.notify("Invalid index. Please enter a number between 1 and {}.".format(len(self.records)))
return

input_value = self.input.value
index = int(input_value) - 1
if 0 <= index < len(self.records):
self.current_idx = index
await self.show_record()
else:
self.notify("Invalid index. Please enter a number between 1 and {}.".format(len(self.records)))
self.input.clear()

async def action_back(self) -> None:
self.current_idx -= 1
if self.current_idx < 0:
Expand All @@ -90,35 +125,29 @@ async def action_forward(self) -> None:
await self.show_record()

async def action_delete(self) -> None:
assert self.current_idx < len(self.records)
current_item = self.records[self.current_idx]
deleted_item = self.records.pop(self.current_idx)
assert current_item == deleted_item
assert 0 <= self.current_idx < len(self.records)
self.records.pop(self.current_idx)
self.current_idx += 1
if self.current_idx >= len(self.records):
self.current_idx = 0
await self.show_record()

async def action_go(self) -> None:
if self.input.has_focus:
validation_result = self.input.validate(self.input.value)
self.post_message(self.input.Submitted(self.input, self.input.value, validation_result))

def on_key(self, event: events.Key) -> None:
if event.key in "1234567890" and not self.input.has_focus:
self.input.focus()
self.input.value = event.key

def action_save(self) -> None:
with open(self.path + "_tmp", "w") as w:
for record in self.records:
w.write(json.dumps(record, ensure_ascii=False) + "\n")
shutil.move(self.path + "_tmp", self.path)

@on(Button.Pressed, "#go_button")
async def handle_go_button(self, event: Button.Pressed) -> None:
await self.go_to_index()

async def go_to_index(self) -> None:
input_value = self.query_one("#index_input").value
index = int(input_value) - 1
if 0 <= index < len(self.records):
self.current_idx = index
await self.show_record()
else:
self.notify("Invalid index. Please enter a number between 1 and {}.".format(self.total_records))
self.query_one("#index_input").value = ""


if __name__ == "__main__":
Browser().run()

0 comments on commit bfa5a15

Please sign in to comment.