From 3c848abeffa3c9701b89b304a8a2813d3144be10 Mon Sep 17 00:00:00 2001 From: hl-valdemar Date: Fri, 9 Oct 2026 21:07:19 +0200 Subject: [PATCH] feat: add full descriptions in a scrollable popup --- Cargo.toml | 2 +- src/main.rs | 180 +++++++++++++++++++++++++++++++++++++++++++++++-- src/youtube.rs | 54 ++++++++++++++- 3 files changed, 228 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9c3a4cd..4123f10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "A terminal YouTube browser that streams videos to your chosen pla [dependencies] clap = { version = "4.6.7", features = ["derive"] } -ratatui = { version = "0.30.2", default-features = false, features = ["crossterm"] } +ratatui = { version = "0.30.2", default-features = false, features = ["crossterm", "unstable-rendered-line-info"] } serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" diff --git a/src/main.rs b/src/main.rs index 91ddfa3..3892908 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,9 @@ //! Without a CLI query, start in insert mode; otherwise search and start in normal mode. //! Insert: Enter submits a changed query and returns to normal; Esc returns without searching. //! Normal: j/k selects, Enter streams, and i returns to insert mode to edit the query. +//! Normal-mode d opens the full description; Up/Down scrolls lines and PgUp/PgDn scrolls pages. +//! The centered popup uses up to 70% width and 60% height, capped at 96 by 20 cells. +//! Esc closes the popup; j/k loads the selected video's description and i returns to editing. //! The player must read media from standard input when passed `-`. //! Audio and video are streamed through a pipe, never saved to a video file. //! See `--help` for controls; replacing playback or quitting cancels its processes. @@ -16,9 +19,10 @@ use clap::Parser; use ratatui::{ DefaultTerminal, Frame, crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}, - layout::{Constraint, Layout}, + layout::{Constraint, Layout, Rect}, style::{Color, Style, Stylize}, - widgets::{Block, Paragraph, Row, Table, TableState, Wrap}, + text::Line, + widgets::{Block, Clear, Paragraph, Row, Table, TableState, Wrap}, }; use youtube::{Job, Playback, Video}; @@ -26,7 +30,7 @@ use youtube::{Job, Playback, Video}; #[command( version, about = "Search YouTube and stream videos to your chosen player", - after_help = "Requires yt-dlp, FFmpeg, and a player on PATH.\nThe player receives audio/video on standard input, with '-' as its last argument.\nWithout a CLI query, start in INSERT; a CLI query is searched automatically in NORMAL.\nINSERT: type to edit; Enter submits if changed and returns to NORMAL; Esc returns without submitting.\nNORMAL: j/k or arrows select; Enter streams; i edits the query; q quits.\nCtrl-U clears in INSERT; Ctrl-C quits in either mode.\nSelecting another video replaces playback. Quitting stops playback.\nExample: tubular --player mpv --player-arg=--volume=50 \"rust programming\"" + after_help = "Requires yt-dlp, FFmpeg, and a player on PATH.\nThe player receives audio/video on standard input, with '-' as its last argument.\nWithout a CLI query, start in INSERT; a CLI query is searched automatically in NORMAL.\nINSERT: type to edit; Enter submits if changed and returns to NORMAL; Esc returns without submitting.\nNORMAL: j/k or arrows select; Enter streams; i edits the query; d toggles description; q quits.\nOpening the description fetches full video metadata, preserving paragraphs and caching it for these results.\nThe centered description window uses up to 70% width and 60% height, capped at 96 by 20 cells.\nWhile it is open, Up/Down scroll lines and PgUp/PgDn scroll pages; j/k still selects videos.\nEsc closes the description; i closes it to edit the query. Scrolling stays within the text.\nCtrl-U clears in INSERT; Ctrl-C quits in either mode.\nSelecting another video replaces playback. Quitting stops playback.\nExample: tubular --player mpv --player-arg=--volume=50 \"rust programming\"" )] struct Options { /// Player executable (must support '-' for media on standard input). @@ -54,6 +58,12 @@ struct App { submitted_query: String, videos: Vec