wip: checkpoint

This commit is contained in:
Alexandre Pasmantier 2025-05-04 01:05:21 +02:00
parent 59bba56ab1
commit 1bf67b537f
13 changed files with 189 additions and 148 deletions

View File

@ -8,12 +8,12 @@ use ratatui::prelude::{Line, Style};
use ratatui::style::Color;
use ratatui::widgets::{Block, BorderType, Borders, ListDirection, Padding};
use ratatui::Terminal;
use television::channels::cable::prototypes::CableChannelPrototypes;
use television::{
action::Action,
channels::{
cable::prototypes::CableChannelPrototype,
entry::{into_ranges, Entry},
preview::PreviewType,
OnAir, TelevisionChannel,
},
config::{Config, ConfigEnv},
@ -37,7 +37,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#7e8e91",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/README.md".to_string(),
@ -49,7 +48,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#dddddd",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/re.pyi".to_string(),
@ -61,7 +59,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/io.pyi".to_string(),
@ -73,7 +70,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/gc.pyi".to_string(),
@ -85,7 +81,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/uu.pyi".to_string(),
@ -97,7 +92,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/nt.pyi".to_string(),
@ -109,7 +103,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/dis.pyi".to_string(),
@ -121,7 +114,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/imp.pyi".to_string(),
@ -133,7 +125,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/bdb.pyi".to_string(),
@ -145,7 +136,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/abc.pyi".to_string(),
@ -157,7 +147,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/cgi.pyi".to_string(),
@ -169,7 +158,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/bz2.pyi".to_string(),
@ -181,7 +169,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/grp.pyi".to_string(),
@ -193,7 +180,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/ast.pyi".to_string(),
@ -205,7 +191,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/csv.pyi".to_string(),
@ -217,7 +202,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/pdb.pyi".to_string(),
@ -229,7 +213,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/pwd.pyi".to_string(),
@ -241,7 +224,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/ssl.pyi".to_string(),
@ -253,7 +235,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/tty.pyi".to_string(),
@ -265,7 +246,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/nis.pyi".to_string(),
@ -277,7 +257,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/pty.pyi".to_string(),
@ -289,7 +268,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/cmd.pyi".to_string(),
@ -301,7 +279,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/tests/utils.py".to_string(),
@ -313,7 +290,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/pyproject.toml".to_string(),
@ -325,7 +301,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#9c4221",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/MAINTAINERS.md".to_string(),
@ -337,7 +312,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#dddddd",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/enum.pyi".to_string(),
@ -349,7 +323,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/hmac.pyi".to_string(),
@ -361,7 +334,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/uuid.pyi".to_string(),
@ -373,7 +345,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/glob.pyi".to_string(),
@ -385,7 +356,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/_ast.pyi".to_string(),
@ -397,7 +367,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/_csv.pyi".to_string(),
@ -409,7 +378,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/code.pyi".to_string(),
@ -421,7 +389,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/spwd.pyi".to_string(),
@ -433,7 +400,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/_msi.pyi".to_string(),
@ -445,7 +411,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
},
Entry {
name: "typeshed/stdlib/time.pyi".to_string(),
@ -456,7 +421,6 @@ pub fn draw_results_list(c: &mut Criterion) {
color: "#ffbc03",
}),
line_number: None,
preview_type: PreviewType::Files,
name_match_ranges: Some(into_ranges(&[0, 1, 2, 3])),
value_match_ranges: None,
},
@ -514,7 +478,14 @@ pub fn draw(c: &mut Criterion) {
channel.find("television");
// Wait for the channel to finish loading
let mut tv = Television::new(
tx, channel, config, None, false, false, false,
tx,
channel,
config,
None,
false,
false,
false,
CableChannelPrototypes::default(),
);
for _ in 0..5 {
// tick the matcher

View File

@ -4,6 +4,7 @@ use anyhow::Result;
use tokio::sync::mpsc;
use tracing::{debug, trace};
use crate::channels::cable::prototypes::CableChannelPrototypes;
use crate::channels::{entry::Entry, OnAir, TelevisionChannel};
use crate::config::{default_tick_rate, Config};
use crate::keymap::Keymap;
@ -96,6 +97,8 @@ pub struct App {
/// Render task handle
render_task: Option<tokio::task::JoinHandle<Result<()>>>,
options: AppOptions,
/// The cable channels that are available.
cable_channels: CableChannelPrototypes,
}
/// The outcome of an action.
@ -139,6 +142,7 @@ impl App {
config: Config,
input: Option<String>,
options: AppOptions,
cable_channels: CableChannelPrototypes,
) -> Self {
let (action_tx, action_rx) = mpsc::unbounded_channel();
let (render_tx, render_rx) = mpsc::unbounded_channel();
@ -156,6 +160,7 @@ impl App {
options.no_remote,
options.no_help,
options.exact,
CableChannelPrototypes(cable_channels.clone()),
);
Self {
@ -173,6 +178,7 @@ impl App {
ui_state_tx,
render_task: None,
options,
cable_channels,
}
}
@ -198,7 +204,7 @@ impl App {
// Event loop
if !headless {
debug!("Starting backend event loop");
let event_loop = EventLoop::new(self.options.tick_rate, true);
let event_loop = EventLoop::new(self.options.tick_rate);
self.event_rx = event_loop.rx;
self.event_abort_tx = event_loop.abort_tx;
}
@ -437,15 +443,18 @@ impl App {
#[cfg(test)]
mod test {
use super::*;
use crate::channels::stdin::Channel as StdinChannel;
use crate::channels::cable::Channel as CableChannel;
#[test]
fn test_maybe_select_1() {
let mut app = App::new(
TelevisionChannel::Stdin(StdinChannel::new(None)),
TelevisionChannel::Cable(CableChannel::new(
"random", "cat", false, None,
)),
Config::default(),
None,
AppOptions::default(),
CableChannelPrototypes::default(),
);
app.television
.results_picker

View File

@ -6,7 +6,9 @@ use anyhow::Result;
use tracing::{debug, error};
use crate::{
channels::cable::prototypes::{CableChannelPrototype, CableChannels},
channels::cable::prototypes::{
CableChannelPrototype, CableChannelPrototypes,
},
config::get_config_dir,
};
@ -40,7 +42,7 @@ const DEFAULT_CABLE_CHANNELS: &str =
/// ├── my_channels.toml
/// └── windows_channels.toml
/// ```
pub fn load_cable_channels() -> Result<CableChannels> {
pub fn load_cable_channels() -> Result<CableChannelPrototypes> {
let config_dir = get_config_dir();
// list all files in the config directory
@ -95,7 +97,7 @@ pub fn load_cable_channels() -> Result<CableChannels> {
{
cable_channels.insert(prototype.name.clone(), prototype);
}
Ok(CableChannels(cable_channels))
Ok(CableChannelPrototypes(cable_channels))
}
fn is_cable_file_format<P>(p: P) -> bool

View File

@ -18,7 +18,7 @@ pub struct Channel {
pub name: String,
matcher: Matcher<String>,
entries_command: String,
preview_command: Option<PreviewCommand>,
pub preview_command: Option<PreviewCommand>,
selected_entries: FxHashSet<Entry>,
crawl_handle: tokio::task::JoinHandle<()>,
}
@ -29,7 +29,7 @@ impl Default for Channel {
"files",
"find . -type f",
false,
Some(PreviewCommand::new("cat {}", ":")),
Some(PreviewCommand::new("cat {}", ":", None)),
)
}
}
@ -46,6 +46,7 @@ impl From<CableChannelPrototype> for Channel {
&prototype
.preview_delimiter
.unwrap_or(DEFAULT_DELIMITER.to_string()),
prototype.preview_offset,
)),
None => None,
},

View File

@ -106,9 +106,11 @@ impl Display for CableChannelPrototype {
/// in a way that facilitates answering questions like "what's the prototype
/// for `files`?" or "does this channel exist?".
#[derive(Debug, serde::Deserialize)]
pub struct CableChannels(pub FxHashMap<String, CableChannelPrototype>);
pub struct CableChannelPrototypes(
pub FxHashMap<String, CableChannelPrototype>,
);
impl Deref for CableChannels {
impl Deref for CableChannelPrototypes {
type Target = FxHashMap<String, CableChannelPrototype>;
fn deref(&self) -> &Self::Target {
@ -127,18 +129,18 @@ const DEFAULT_CABLE_CHANNELS_FILE: &str =
const DEFAULT_CABLE_CHANNELS_FILE: &str =
include_str!("../../cable/windows-channels.toml");
impl Default for CableChannels {
impl Default for CableChannelPrototypes {
/// Fallback to the default cable channels specification (the template file
/// included in the repo).
fn default() -> Self {
let pts = toml::from_str::<SerializedChannelPrototypes>(
let s = toml::from_str::<SerializedChannelPrototypes>(
DEFAULT_CABLE_CHANNELS_FILE,
)
.expect("Unable to parse default cable channels");
let mut channels = FxHashMap::default();
for prototype in pts.prototypes {
channels.insert(prototype.name.clone(), prototype);
let mut prototypes = FxHashMap::default();
for prototype in s.prototypes {
prototypes.insert(prototype.name.clone(), prototype);
}
CableChannels(channels)
CableChannelPrototypes(prototypes)
}
}

View File

@ -7,7 +7,7 @@ pub mod cable;
pub mod entry;
pub mod preview;
pub mod remote_control;
pub mod stdin;
// pub mod stdin;
/// The interface that all television channels must implement.
///
@ -118,7 +118,7 @@ pub enum TelevisionChannel {
/// The standard input channel.
///
/// This channel allows to search through whatever is passed through stdin.
Stdin(stdin::Channel),
// Stdin(stdin::Channel),
/// The remote control channel.
///
/// This channel allows to switch between different channels.
@ -142,7 +142,7 @@ impl TelevisionChannel {
pub fn name(&self) -> String {
match self {
TelevisionChannel::Cable(channel) => channel.name.clone(),
TelevisionChannel::Stdin(_) => String::from("Stdin"),
// TelevisionChannel::Stdin(_) => String::from("Stdin"),
TelevisionChannel::RemoteControl(_) => String::from("Remote"),
}
}

View File

@ -1,8 +1,8 @@
use std::fmt::Display;
use lazy_regex::{regex, Lazy, Regex};
use super::entry::Entry;
use crate::channels::cable::prototypes::CableChannelPrototype;
use lazy_regex::{regex, Lazy, Regex};
static CMD_RE: &Lazy<Regex> = regex!(r"\{(\d+)\}");
@ -10,13 +10,19 @@ static CMD_RE: &Lazy<Regex> = regex!(r"\{(\d+)\}");
pub struct PreviewCommand {
pub command: String,
pub delimiter: String,
pub offset_expr: Option<String>,
}
impl PreviewCommand {
pub fn new(command: &str, delimiter: &str) -> Self {
pub fn new(
command: &str,
delimiter: &str,
offset_expr: Option<String>,
) -> Self {
Self {
command: command.to_string(),
delimiter: delimiter.to_string(),
offset_expr,
}
}
@ -29,6 +35,7 @@ impl PreviewCommand {
/// let command = PreviewCommand {
/// command: "something {} {2} {0}".to_string(),
/// delimiter: ":".to_string(),
/// offset_expr: None,
/// };
/// let entry = Entry::new("a:given:entry:to:preview".to_string());
///
@ -55,6 +62,29 @@ impl PreviewCommand {
}
}
impl TryFrom<&CableChannelPrototype> for PreviewCommand {
type Error = anyhow::Error;
fn try_from(value: &CableChannelPrototype) -> Result<Self, Self::Error> {
let command = value
.preview_command
.as_ref()
.expect("Preview command is not set.");
let delimiter = value
.preview_delimiter
.as_ref()
.expect("Preview delimiter is not set");
let offset_expr = value.preview_offset.clone();
// FIXME: handle offset here (side note: we don't want to reparse the offset
// expression for each entry, so maybe just parse it once and try to store it
// as some sort of function we can call later on
Ok(PreviewCommand::new(command, delimiter, offset_expr))
}
}
impl Display for PreviewCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
@ -71,6 +101,7 @@ mod tests {
let command = PreviewCommand {
command: "something {} {2} {0}".to_string(),
delimiter: ":".to_string(),
offset_expr: None,
};
let entry = Entry::new("an:entry:to:preview".to_string());
let formatted_command = command.format_with(&entry);
@ -86,6 +117,7 @@ mod tests {
let command = PreviewCommand {
command: "something".to_string(),
delimiter: ":".to_string(),
offset_expr: None,
};
let entry = Entry::new("an:entry:to:preview".to_string());
let formatted_command = command.format_with(&entry);
@ -98,6 +130,7 @@ mod tests {
let command = PreviewCommand {
command: "something {}".to_string(),
delimiter: ":".to_string(),
offset_expr: None,
};
let entry = Entry::new("an:entry:to:preview".to_string());
let formatted_command = command.format_with(&entry);
@ -110,6 +143,7 @@ mod tests {
let command = PreviewCommand {
command: "something {0} -t {2}".to_string(),
delimiter: ":".to_string(),
offset_expr: None,
};
let entry = Entry::new("an:entry:to:preview".to_string());
let formatted_command = command.format_with(&entry);

View File

@ -1,6 +1,6 @@
use std::collections::HashSet;
use crate::channels::cable::prototypes::CableChannels;
use crate::channels::cable::prototypes::CableChannelPrototypes;
use crate::channels::entry::Entry;
use crate::channels::{OnAir, TelevisionChannel};
use crate::matcher::{config::Config, Matcher};
@ -12,19 +12,19 @@ use super::cable;
pub struct RemoteControl {
matcher: Matcher<String>,
cable_channels: Option<CableChannels>,
cable_channels: Option<CableChannelPrototypes>,
selected_entries: FxHashSet<Entry>,
}
const NUM_THREADS: usize = 1;
impl RemoteControl {
pub fn new(cable_channels: Option<CableChannels>) -> Self {
pub fn new(cable_channels: Option<CableChannelPrototypes>) -> Self {
let matcher = Matcher::new(Config::default().n_threads(NUM_THREADS));
let injector = matcher.injector();
for c in cable_channels
.as_ref()
.unwrap_or(&CableChannels::default())
.unwrap_or(&CableChannelPrototypes::default())
.keys()
{
let () = injector.push(c.clone(), |e, cols| {

View File

@ -13,7 +13,7 @@ use crate::matcher::{config::Config, injector::Injector, Matcher};
pub struct Channel {
matcher: Matcher<String>,
preview_command: Option<PreviewCommand>,
pub preview_command: Option<PreviewCommand>,
selected_entries: FxHashSet<Entry>,
instream_handle: std::thread::JoinHandle<()>,
}

View File

@ -5,7 +5,7 @@ use anyhow::{anyhow, Result};
use tracing::debug;
use crate::channels::cable::prototypes::{
CableChannelPrototype, CableChannels,
CableChannelPrototype, CableChannelPrototypes,
};
use crate::channels::preview::PreviewCommand;
use crate::cli::args::{Cli, Command};
@ -76,6 +76,8 @@ impl From<Cli> for PostProcessedCli {
let preview_command = cli.preview.map(|preview| PreviewCommand {
command: preview,
delimiter: cli.delimiter.clone(),
// TODO: add the --preview-offset option to the CLI
offset_expr: None,
});
let channel: CableChannelPrototype;
@ -170,7 +172,7 @@ fn parse_keybindings_literal(
pub fn parse_channel(
channel: &str,
cable_channels: &CableChannels,
cable_channels: &CableChannelPrototypes,
) -> Result<CableChannelPrototype> {
// try to parse the channel as a cable channel
match cable_channels
@ -215,7 +217,7 @@ pub fn guess_channel_from_prompt(
prompt: &str,
command_mapping: &FxHashMap<String, String>,
fallback_channel: &str,
cable_channels: &CableChannels,
cable_channels: &CableChannelPrototypes,
) -> Result<CableChannelPrototype> {
debug!("Guessing channel from prompt: {}", prompt);
// git checkout -qf
@ -317,7 +319,8 @@ mod tests {
post_processed_cli.preview_command,
Some(PreviewCommand {
command: "bat -n --color=always {}".to_string(),
delimiter: ":".to_string()
delimiter: ":".to_string(),
offset_expr: None,
})
);
assert_eq!(post_processed_cli.tick_rate, None);
@ -377,7 +380,7 @@ mod tests {
/// Returns a tuple containing a command mapping and a fallback channel.
fn guess_channel_from_prompt_setup<'a>(
) -> (FxHashMap<String, String>, &'a str, CableChannels) {
) -> (FxHashMap<String, String>, &'a str, CableChannelPrototypes) {
let mut command_mapping = FxHashMap::default();
command_mapping.insert("vim".to_string(), "files".to_string());
command_mapping.insert("export".to_string(), "env".to_string());

View File

@ -115,9 +115,7 @@ impl Display for Key {
#[allow(clippy::module_name_repetitions)]
pub struct EventLoop {
pub rx: mpsc::UnboundedReceiver<Event<Key>>,
//tx: mpsc::UnboundedSender<Event<Key>>,
pub abort_tx: mpsc::UnboundedSender<()>,
//tick_rate: std::time::Duration,
}
struct PollFuture {
@ -162,8 +160,7 @@ fn flush_existing_events() {
}
impl EventLoop {
// FIXME: this init parameter doesn't seem to be used anymore
pub fn new(tick_rate: f64, init: bool) -> Self {
pub fn new(tick_rate: f64) -> Self {
let (tx, rx) = mpsc::unbounded_channel();
let tick_interval = Duration::from_secs_f64(1.0 / tick_rate);
@ -171,8 +168,6 @@ impl EventLoop {
flush_existing_events();
if init {
//let mut reader = crossterm::event::EventStream::new();
tokio::spawn(async move {
loop {
let delay = tokio::time::sleep(tick_interval);
@ -219,7 +214,6 @@ impl EventLoop {
}
}
});
}
Self {
//tx,

View File

@ -7,7 +7,9 @@ use anyhow::Result;
use clap::Parser;
use crossterm::terminal::enable_raw_mode;
use television::cable;
use television::channels::cable::prototypes::CableChannels;
use television::channels::cable::prototypes::{
CableChannelPrototype, CableChannelPrototypes,
};
use television::utils::clipboard::CLIPBOARD;
use tracing::{debug, error, info};
@ -81,7 +83,8 @@ async fn main() -> Result<()> {
args.no_help,
config.application.tick_rate,
);
let mut app = App::new(channel, config, args.input, options);
let mut app =
App::new(channel, config, args.input, options, cable_channels);
stdout().flush()?;
debug!("Running application...");
let output = app.run(stdout().is_terminal(), false).await?;
@ -157,8 +160,8 @@ pub fn determine_channel(
args: PostProcessedCli,
config: &Config,
readable_stdin: bool,
cable_channels: &CableChannels,
) -> Result<TelevisionChannel> {
cable_channels: &CableChannelPrototypes,
) -> Result<CableChannelPrototype> {
if readable_stdin {
debug!("Using stdin channel");
Ok(TelevisionChannel::Stdin(StdinChannel::new(
@ -197,9 +200,9 @@ mod tests {
config: &Config,
readable_stdin: bool,
expected_channel: &TelevisionChannel,
cable_channels: Option<CableChannels>,
cable_channels: Option<CableChannelPrototypes>,
) {
let channels: CableChannels = cable_channels
let channels: CableChannelPrototypes = cable_channels
.unwrap_or_else(|| load_cable_channels().unwrap_or_default());
let channel =
determine_channel(args.clone(), config, readable_stdin, &channels)

View File

@ -1,21 +1,29 @@
use crate::action::Action;
use crate::cable::load_cable_channels;
use crate::channels::entry::{Entry, ENTRY_PLACEHOLDER};
use crate::channels::{
remote_control::RemoteControl, OnAir, TelevisionChannel,
use crate::{
action::Action,
cable::load_cable_channels,
channels::{
cable::{prototypes::CableChannelPrototypes, Channel as CableChannel},
entry::{Entry, ENTRY_PLACEHOLDER},
remote_control::RemoteControl,
// stdin::Channel as StdinChannel,
OnAir,
TelevisionChannel,
},
config::{Config, Theme},
draw::{ChannelState, Ctx, TvState},
input::convert_action_to_input_request,
picker::Picker,
preview::{previewer::Previewer, Preview, PreviewState},
render::UiState,
screen::{
colors::Colorscheme,
layout::InputPosition,
spinner::{Spinner, SpinnerState},
},
utils::{
clipboard::CLIPBOARD, metadata::AppMetadata, strings::EMPTY_STRING,
},
};
use crate::config::{Config, Theme};
use crate::draw::{ChannelState, Ctx, TvState};
use crate::input::convert_action_to_input_request;
use crate::picker::Picker;
use crate::preview::{previewer::Previewer, Preview, PreviewState};
use crate::render::UiState;
use crate::screen::colors::Colorscheme;
use crate::screen::layout::InputPosition;
use crate::screen::spinner::{Spinner, SpinnerState};
use crate::utils::clipboard::CLIPBOARD;
use crate::utils::metadata::AppMetadata;
use crate::utils::strings::EMPTY_STRING;
use anyhow::Result;
use rustc_hash::{FxBuildHasher, FxHashSet};
use serde::{Deserialize, Serialize};
@ -45,7 +53,7 @@ pub struct Television {
pub matching_mode: MatchingMode,
pub results_picker: Picker,
pub rc_picker: Picker,
pub previewer: Previewer,
pub previewer: Option<Previewer>,
pub preview_state: PreviewState,
pub spinner: Spinner,
pub spinner_state: SpinnerState,
@ -66,14 +74,24 @@ impl Television {
no_remote: bool,
no_help: bool,
exact: bool,
cable_channels: CableChannelPrototypes,
) -> Self {
let mut results_picker = Picker::new(input.clone());
if config.ui.input_bar_position == InputPosition::Bottom {
results_picker = results_picker.inverted();
}
// FIXME: fix this
let previewer = Previewer::new();
let cable_channels = load_cable_channels().unwrap_or_default();
let previewer = match &channel {
// TelevisionChannel::Stdin(StdinChannel {
// preview_command: command,
// ..
// }) |
TelevisionChannel::Cable(CableChannel {
preview_command: command,
..
}) => command.clone().map(Previewer::new),
_ => None,
};
let app_metadata = AppMetadata::new(
env!("CARGO_PKG_VERSION").to_string(),
@ -369,10 +387,14 @@ impl Television {
&mut self,
selected_entry: &Entry,
) -> Result<()> {
if self.config.ui.show_preview_panel && self.channel.supports_preview()
if self.config.ui.show_preview_panel
&& self.channel.supports_preview()
&& self.previewer.is_some()
{
// preview content
if let Some(preview) = self.previewer.preview(selected_entry) {
if let Some(preview) =
self.previewer.as_mut().unwrap().preview(selected_entry)
{
// only update if the preview content has changed
if self.preview_state.preview.title != preview.title {
self.preview_state.update(