refactor(preview): simplify channel previews code and remove intermediate PreviewKind struct (#490)

This commit is contained in:
Alexandre Pasmantier 2025-05-01 17:42:01 +02:00 committed by GitHub
parent dbff3a330b
commit b9f42e8c29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 151 additions and 162 deletions

View File

@ -8,16 +8,18 @@ use ratatui::prelude::{Line, Style};
use ratatui::style::Color; use ratatui::style::Color;
use ratatui::widgets::{Block, BorderType, Borders, ListDirection, Padding}; use ratatui::widgets::{Block, BorderType, Borders, ListDirection, Padding};
use ratatui::Terminal; use ratatui::Terminal;
use television::action::Action; use television::{
use television::channels::cable::prototypes::CableChannelPrototype; action::Action,
use television::channels::entry::into_ranges; channels::{
use television::channels::entry::{Entry, PreviewType}; cable::prototypes::CableChannelPrototype,
use television::channels::OnAir; entry::{into_ranges, Entry},
use television::channels::TelevisionChannel; preview::PreviewType,
use television::config::{Config, ConfigEnv}; OnAir, TelevisionChannel,
use television::screen::colors::ResultsColorscheme; },
use television::screen::results::build_results_list; config::{Config, ConfigEnv},
use television::television::Television; screen::{colors::ResultsColorscheme, results::build_results_list},
television::Television,
};
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
pub fn draw_results_list(c: &mut Criterion) { pub fn draw_results_list(c: &mut Criterion) {

View File

@ -4,8 +4,9 @@ use anyhow::Result;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tracing::{debug, trace}; use tracing::{debug, trace};
use crate::channels::entry::{Entry, PreviewType}; use crate::channels::{
use crate::channels::{OnAir, TelevisionChannel}; entry::Entry, preview::PreviewType, OnAir, TelevisionChannel,
};
use crate::config::{default_tick_rate, Config}; use crate::config::{default_tick_rate, Config};
use crate::keymap::Keymap; use crate::keymap::Keymap;
use crate::render::UiState; use crate::render::UiState;

View File

@ -2,18 +2,20 @@ use std::collections::HashSet;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::process::Stdio; use std::process::Stdio;
use preview::{parse_preview_kind, PreviewKind};
use prototypes::{CableChannelPrototype, DEFAULT_DELIMITER}; use prototypes::{CableChannelPrototype, DEFAULT_DELIMITER};
use rustc_hash::{FxBuildHasher, FxHashSet}; use rustc_hash::{FxBuildHasher, FxHashSet};
use tracing::debug; use tracing::debug;
use crate::channels::entry::{Entry, PreviewCommand, PreviewType}; use crate::channels::preview::parse_preview_type;
use crate::channels::OnAir; use crate::channels::{
entry::Entry,
preview::{PreviewCommand, PreviewType},
OnAir,
};
use crate::matcher::Matcher; use crate::matcher::Matcher;
use crate::matcher::{config::Config, injector::Injector}; use crate::matcher::{config::Config, injector::Injector};
use crate::utils::command::shell_command; use crate::utils::command::shell_command;
pub mod preview;
pub mod prototypes; pub mod prototypes;
#[allow(dead_code)] #[allow(dead_code)]
@ -21,7 +23,7 @@ pub struct Channel {
pub name: String, pub name: String,
matcher: Matcher<String>, matcher: Matcher<String>,
entries_command: String, entries_command: String,
preview_kind: PreviewKind, preview_type: PreviewType,
selected_entries: FxHashSet<Entry>, selected_entries: FxHashSet<Entry>,
crawl_handle: tokio::task::JoinHandle<()>, crawl_handle: tokio::task::JoinHandle<()>,
} }
@ -72,17 +74,17 @@ impl Channel {
)); ));
let preview_kind = match preview_command { let preview_kind = match preview_command {
Some(command) => { Some(command) => {
parse_preview_kind(&command).unwrap_or_else(|_| { parse_preview_type(&command).unwrap_or_else(|_| {
panic!("Invalid preview command: {command}") panic!("Invalid preview command: {command}")
}) })
} }
None => PreviewKind::None, None => PreviewType::None,
}; };
debug!("Preview kind: {:?}", preview_kind); debug!("Preview kind: {:?}", preview_kind);
Self { Self {
matcher, matcher,
entries_command: entries_command.to_string(), entries_command: entries_command.to_string(),
preview_kind, preview_type: preview_kind,
name: name.to_string(), name: name.to_string(),
selected_entries: HashSet::with_hasher(FxBuildHasher), selected_entries: HashSet::with_hasher(FxBuildHasher),
crawl_handle, crawl_handle,
@ -147,19 +149,8 @@ impl OnAir for Channel {
.into_iter() .into_iter()
.map(|item| { .map(|item| {
let path = item.matched_string; let path = item.matched_string;
Entry::new( Entry::new(path, self.preview_type.clone())
path, .with_name_match_indices(&item.match_indices)
match &self.preview_kind {
PreviewKind::Command(ref preview_command) => {
PreviewType::Command(preview_command.clone())
}
PreviewKind::Builtin(preview_type) => {
preview_type.clone()
}
PreviewKind::None => PreviewType::None,
},
)
.with_name_match_indices(&item.match_indices)
}) })
.collect() .collect()
} }
@ -167,16 +158,7 @@ impl OnAir for Channel {
fn get_result(&self, index: u32) -> Option<Entry> { fn get_result(&self, index: u32) -> Option<Entry> {
self.matcher.get_result(index).map(|item| { self.matcher.get_result(index).map(|item| {
let path = item.matched_string; let path = item.matched_string;
Entry::new( Entry::new(path, self.preview_type.clone())
path,
match &self.preview_kind {
PreviewKind::Command(ref preview_command) => {
PreviewType::Command(preview_command.clone())
}
PreviewKind::Builtin(preview_type) => preview_type.clone(),
PreviewKind::None => PreviewType::None,
},
)
}) })
} }
@ -207,6 +189,6 @@ impl OnAir for Channel {
fn shutdown(&self) {} fn shutdown(&self) {}
fn supports_preview(&self) -> bool { fn supports_preview(&self) -> bool {
self.preview_kind != PreviewKind::None self.preview_type != PreviewType::None
} }
} }

View File

@ -1,34 +0,0 @@
use anyhow::Result;
use regex::Regex;
use tracing::debug;
use crate::channels::entry::{PreviewCommand, PreviewType};
#[derive(Debug, Clone, PartialEq)]
pub enum PreviewKind {
Command(PreviewCommand),
Builtin(PreviewType),
None,
}
/// Parses the preview command to determine if it is a built-in (i.e. ":files:") or custom command.
///
/// # Example:
/// ```
/// use television::channels::entry::{PreviewCommand, PreviewType};
/// use television::channels::cable::preview::{parse_preview_kind, PreviewKind};
///
/// let command = PreviewCommand::new("cat {0}", ":");
/// let preview_kind = parse_preview_kind(&command).unwrap();
/// assert_eq!(preview_kind, PreviewKind::Command(command));
/// ```
pub fn parse_preview_kind(command: &PreviewCommand) -> Result<PreviewKind> {
debug!("Parsing preview kind for command: {:?}", command);
let re = Regex::new(r"^\:(\w+)\:$").unwrap();
if let Some(captures) = re.captures(&command.command) {
let preview_type = PreviewType::try_from(&captures[1])?;
Ok(PreviewKind::Builtin(preview_type))
} else {
Ok(PreviewKind::Command(command.clone()))
}
}

View File

@ -25,6 +25,9 @@ use crate::cable::SerializedChannelPrototypes;
/// - `preview_delimiter`: The delimiter to use to split an entry into /// - `preview_delimiter`: The delimiter to use to split an entry into
/// multiple parts that can then be referenced in the preview command (e.g. /// multiple parts that can then be referenced in the preview command (e.g.
/// `{1} + {2}`). /// `{1} + {2}`).
/// - `preview_offset`: a litteral expression that will be interpreted later on
/// in order to determine the vertical offset at which the preview should be
/// displayed.
/// ///
/// # Example /// # Example
/// The default files channel might look something like this: /// The default files channel might look something like this:
@ -43,6 +46,7 @@ pub struct CableChannelPrototype {
pub preview_command: Option<String>, pub preview_command: Option<String>,
#[serde(default = "default_delimiter")] #[serde(default = "default_delimiter")]
pub preview_delimiter: Option<String>, pub preview_delimiter: Option<String>,
pub preview_offset: Option<String>,
} }
impl CableChannelPrototype { impl CableChannelPrototype {
@ -52,6 +56,7 @@ impl CableChannelPrototype {
interactive: bool, interactive: bool,
preview_command: Option<String>, preview_command: Option<String>,
preview_delimiter: Option<String>, preview_delimiter: Option<String>,
preview_offset: Option<String>,
) -> Self { ) -> Self {
Self { Self {
name: name.to_string(), name: name.to_string(),
@ -59,6 +64,7 @@ impl CableChannelPrototype {
interactive, interactive,
preview_command, preview_command,
preview_delimiter, preview_delimiter,
preview_offset,
} }
} }
} }
@ -76,10 +82,13 @@ impl Default for CableChannelPrototype {
interactive: false, interactive: false,
preview_command: Some(DEFAULT_PREVIEW_COMMAND.to_string()), preview_command: Some(DEFAULT_PREVIEW_COMMAND.to_string()),
preview_delimiter: Some(DEFAULT_DELIMITER.to_string()), preview_delimiter: Some(DEFAULT_DELIMITER.to_string()),
preview_offset: None,
} }
} }
} }
/// The default delimiter to use for the preview command to use to split
/// entries into multiple referenceable parts.
#[allow(clippy::unnecessary_wraps)] #[allow(clippy::unnecessary_wraps)]
fn default_delimiter() -> Option<String> { fn default_delimiter() -> Option<String> {
Some(DEFAULT_DELIMITER.to_string()) Some(DEFAULT_DELIMITER.to_string())
@ -107,9 +116,13 @@ impl Deref for CableChannels {
} }
} }
/// A default cable channels specification that is compiled into the
/// application.
#[cfg(unix)] #[cfg(unix)]
const DEFAULT_CABLE_CHANNELS_FILE: &str = const DEFAULT_CABLE_CHANNELS_FILE: &str =
include_str!("../../../cable/unix-channels.toml"); include_str!("../../../cable/unix-channels.toml");
/// A default cable channels specification that is compiled into the
/// application.
#[cfg(not(unix))] #[cfg(not(unix))]
const DEFAULT_CABLE_CHANNELS_FILE: &str = const DEFAULT_CABLE_CHANNELS_FILE: &str =
include_str!("../../cable/windows-channels.toml"); include_str!("../../cable/windows-channels.toml");

View File

@ -1,10 +1,8 @@
use std::{ use std::hash::{Hash, Hasher};
fmt::Display,
hash::{Hash, Hasher},
};
use devicons::FileIcon; use devicons::FileIcon;
use strum::EnumString;
use crate::channels::preview::PreviewType;
// NOTE: having an enum for entry types would be nice since it would allow // NOTE: having an enum for entry types would be nice since it would allow
// having a nicer implementation for transitions between channels. This would // having a nicer implementation for transitions between channels. This would
@ -87,7 +85,7 @@ impl Entry {
/// ///
/// Additional fields can be set using the builder pattern. /// Additional fields can be set using the builder pattern.
/// ``` /// ```
/// use television::channels::entry::{Entry, PreviewType}; /// use television::channels::{entry::Entry, preview::PreviewType};
/// use devicons::FileIcon; /// use devicons::FileIcon;
/// ///
/// let entry = Entry::new("name".to_string(), PreviewType::EnvVar) /// let entry = Entry::new("name".to_string(), PreviewType::EnvVar)
@ -161,39 +159,6 @@ pub const ENTRY_PLACEHOLDER: Entry = Entry {
preview_type: PreviewType::EnvVar, preview_type: PreviewType::EnvVar,
}; };
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
pub struct PreviewCommand {
pub command: String,
pub delimiter: String,
}
impl PreviewCommand {
pub fn new(command: &str, delimiter: &str) -> Self {
Self {
command: command.to_string(),
delimiter: delimiter.to_string(),
}
}
}
impl Display for PreviewCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, EnumString)]
#[strum(serialize_all = "snake_case")]
pub enum PreviewType {
Basic,
EnvVar,
Files,
#[strum(disabled)]
Command(PreviewCommand),
#[default]
None,
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -5,6 +5,7 @@ use television_derive::Broadcast;
pub mod cable; pub mod cable;
pub mod entry; pub mod entry;
pub mod preview;
pub mod remote_control; pub mod remote_control;
pub mod stdin; pub mod stdin;

View File

@ -0,0 +1,63 @@
use std::fmt::Display;
use anyhow::Result;
use regex::Regex;
use strum::EnumString;
use tracing::debug;
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
pub struct PreviewCommand {
pub command: String,
pub delimiter: String,
}
impl PreviewCommand {
pub fn new(command: &str, delimiter: &str) -> Self {
Self {
command: command.to_string(),
delimiter: delimiter.to_string(),
}
}
}
impl Display for PreviewCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default, EnumString)]
#[strum(serialize_all = "snake_case")]
pub enum PreviewType {
Basic,
EnvVar,
Files,
#[strum(disabled)]
Command(PreviewCommand),
#[default]
None,
}
/// Parses the preview command to determine the preview type.
///
/// This checks if the command matches the builtin pattern `:{preview_type}:`
/// and then falls back to the command type if it doesn't.
///
/// # Example:
/// ```
/// use television::channels::preview::{parse_preview_type, PreviewCommand, PreviewType};
///
/// let command = PreviewCommand::new("cat {0}", ":");
/// let preview_type = parse_preview_type(&command).unwrap();
/// assert_eq!(preview_type, PreviewType::Command(command));
/// ```
pub fn parse_preview_type(command: &PreviewCommand) -> Result<PreviewType> {
debug!("Parsing preview kind for command: {:?}", command);
let re = Regex::new(r"^\:(\w+)\:$").unwrap();
if let Some(captures) = re.captures(&command.command) {
let preview_type = PreviewType::try_from(&captures[1])?;
Ok(preview_type)
} else {
Ok(PreviewType::Command(command.clone()))
}
}

View File

@ -1,7 +1,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use crate::channels::cable::prototypes::CableChannels; use crate::channels::cable::prototypes::CableChannels;
use crate::channels::entry::{Entry, PreviewType}; use crate::channels::{entry::Entry, preview::PreviewType};
use crate::channels::{OnAir, TelevisionChannel}; use crate::channels::{OnAir, TelevisionChannel};
use crate::matcher::{config::Config, Matcher}; use crate::matcher::{config::Config, Matcher};
use anyhow::Result; use anyhow::Result;

View File

@ -8,7 +8,7 @@ use rustc_hash::{FxBuildHasher, FxHashSet};
use tracing::debug; use tracing::debug;
use super::OnAir; use super::OnAir;
use crate::channels::entry::{Entry, PreviewType}; use crate::channels::{entry::Entry, preview::PreviewType};
use crate::matcher::{config::Config, injector::Injector, Matcher}; use crate::matcher::{config::Config, injector::Injector, Matcher};
pub struct Channel { pub struct Channel {

View File

@ -4,12 +4,11 @@ use std::path::Path;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use tracing::debug; use tracing::debug;
use crate::channels::cable::{ use crate::channels::cable::prototypes::{
preview::parse_preview_kind, preview::PreviewKind, CableChannelPrototype, CableChannels,
prototypes::CableChannels,
}; };
use crate::channels::{ use crate::channels::preview::{
cable::prototypes::CableChannelPrototype, entry::PreviewCommand, parse_preview_type, PreviewCommand, PreviewType,
}; };
use crate::cli::args::{Cli, Command}; use crate::cli::args::{Cli, Command};
use crate::config::{KeyBindings, DEFAULT_CHANNEL}; use crate::config::{KeyBindings, DEFAULT_CHANNEL};
@ -24,7 +23,7 @@ pub mod args;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PostProcessedCli { pub struct PostProcessedCli {
pub channel: CableChannelPrototype, pub channel: CableChannelPrototype,
pub preview_kind: PreviewKind, pub preview_kind: PreviewType,
pub no_preview: bool, pub no_preview: bool,
pub tick_rate: Option<f64>, pub tick_rate: Option<f64>,
pub frame_rate: Option<f64>, pub frame_rate: Option<f64>,
@ -44,7 +43,7 @@ impl Default for PostProcessedCli {
fn default() -> Self { fn default() -> Self {
Self { Self {
channel: CableChannelPrototype::default(), channel: CableChannelPrototype::default(),
preview_kind: PreviewKind::None, preview_kind: PreviewType::None,
no_preview: false, no_preview: false,
tick_rate: None, tick_rate: None,
frame_rate: None, frame_rate: None,
@ -80,8 +79,8 @@ impl From<Cli> for PostProcessedCli {
command: preview, command: preview,
delimiter: cli.delimiter.clone(), delimiter: cli.delimiter.clone(),
}) })
.map_or(PreviewKind::None, |preview_command| { .map_or(PreviewType::None, |preview_command| {
parse_preview_kind(&preview_command) parse_preview_type(&preview_command)
.map_err(|e| { .map_err(|e| {
cli_parsing_error_exit(&e.to_string()); cli_parsing_error_exit(&e.to_string());
}) })
@ -302,7 +301,7 @@ Data directory: {data_dir_path}"
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
action::Action, channels::entry::PreviewType, config::Binding, action::Action, channels::preview::PreviewType, config::Binding,
event::Key, event::Key,
}; };
@ -327,7 +326,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
post_processed_cli.preview_kind, post_processed_cli.preview_kind,
PreviewKind::Command(PreviewCommand { PreviewType::Command(PreviewCommand {
command: "bat -n --color=always {}".to_string(), command: "bat -n --color=always {}".to_string(),
delimiter: ":".to_string() delimiter: ":".to_string()
}) })
@ -373,10 +372,7 @@ mod tests {
let post_processed_cli: PostProcessedCli = cli.into(); let post_processed_cli: PostProcessedCli = cli.into();
assert_eq!( assert_eq!(post_processed_cli.preview_kind, PreviewType::Files);
post_processed_cli.preview_kind,
PreviewKind::Builtin(PreviewType::Files)
);
} }
#[test] #[test]
@ -390,10 +386,7 @@ mod tests {
let post_processed_cli: PostProcessedCli = cli.into(); let post_processed_cli: PostProcessedCli = cli.into();
assert_eq!( assert_eq!(post_processed_cli.preview_kind, PreviewType::EnvVar);
post_processed_cli.preview_kind,
PreviewKind::Builtin(PreviewType::EnvVar)
);
} }
#[test] #[test]

View File

@ -7,15 +7,13 @@ use anyhow::Result;
use clap::Parser; use clap::Parser;
use crossterm::terminal::enable_raw_mode; use crossterm::terminal::enable_raw_mode;
use television::cable; use television::cable;
use television::channels::cable::{ use television::channels::cable::prototypes::CableChannels;
preview::PreviewKind, prototypes::CableChannels,
};
use television::utils::clipboard::CLIPBOARD; use television::utils::clipboard::CLIPBOARD;
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use television::app::{App, AppOptions}; use television::app::{App, AppOptions};
use television::channels::{ use television::channels::{
entry::PreviewType, stdin::Channel as StdinChannel, TelevisionChannel, stdin::Channel as StdinChannel, TelevisionChannel,
}; };
use television::cli::{ use television::cli::{
args::{Cli, Command}, args::{Cli, Command},
@ -163,13 +161,7 @@ pub fn determine_channel(
if readable_stdin { if readable_stdin {
debug!("Using stdin channel"); debug!("Using stdin channel");
Ok(TelevisionChannel::Stdin(StdinChannel::new( Ok(TelevisionChannel::Stdin(StdinChannel::new(
match &args.preview_kind { args.preview_kind,
PreviewKind::Command(ref preview_command) => {
PreviewType::Command(preview_command.clone())
}
PreviewKind::Builtin(preview_type) => preview_type.clone(),
PreviewKind::None => PreviewType::None,
},
))) )))
} else if let Some(prompt) = args.autocomplete_prompt { } else if let Some(prompt) = args.autocomplete_prompt {
debug!("Using autocomplete prompt: {:?}", prompt); debug!("Using autocomplete prompt: {:?}", prompt);
@ -192,7 +184,9 @@ mod tests {
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use television::{ use television::{
cable::load_cable_channels, cable::load_cable_channels,
channels::cable::prototypes::CableChannelPrototype, channels::{
cable::prototypes::CableChannelPrototype, preview::PreviewType,
},
}; };
use super::*; use super::*;
@ -241,8 +235,10 @@ mod tests {
async fn test_determine_channel_autocomplete_prompt() { async fn test_determine_channel_autocomplete_prompt() {
let autocomplete_prompt = Some("cd".to_string()); let autocomplete_prompt = Some("cd".to_string());
let expected_channel = TelevisionChannel::Cable( let expected_channel = TelevisionChannel::Cable(
CableChannelPrototype::new("dirs", "ls {}", false, None, None) CableChannelPrototype::new(
.into(), "dirs", "ls {}", false, None, None, None,
)
.into(),
); );
let args = PostProcessedCli { let args = PostProcessedCli {
autocomplete_prompt, autocomplete_prompt,
@ -276,7 +272,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_determine_channel_standard_case() { async fn test_determine_channel_standard_case() {
let channel = let channel =
CableChannelPrototype::new("dirs", "", false, None, None); CableChannelPrototype::new("dirs", "", false, None, None, None);
let args = PostProcessedCli { let args = PostProcessedCli {
channel, channel,
..Default::default() ..Default::default()
@ -287,8 +283,10 @@ mod tests {
&config, &config,
false, false,
&TelevisionChannel::Cable( &TelevisionChannel::Cable(
CableChannelPrototype::new("dirs", "", false, None, None) CableChannelPrototype::new(
.into(), "dirs", "", false, None, None, None,
)
.into(),
), ),
None, None,
); );

View File

@ -1,6 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use crate::channels::entry::{Entry, PreviewType}; use crate::channels::{entry::Entry, preview::PreviewType};
use devicons::FileIcon; use devicons::FileIcon;
use ratatui::layout::Rect; use ratatui::layout::Rect;

View File

@ -1,7 +1,9 @@
use crate::channels::entry::{Entry, PreviewCommand};
use crate::preview::cache::PreviewCache;
use crate::preview::{Preview, PreviewContent}; use crate::preview::{Preview, PreviewContent};
use crate::utils::command::shell_command; use crate::utils::command::shell_command;
use crate::{
channels::{entry::Entry, preview::PreviewCommand},
preview::cache::PreviewCache,
};
use parking_lot::Mutex; use parking_lot::Mutex;
use regex::Regex; use regex::Regex;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
@ -127,7 +129,7 @@ impl CommandPreviewer {
/// ///
/// # Example /// # Example
/// ``` /// ```
/// use television::channels::entry::{PreviewCommand, PreviewType, Entry}; /// use television::channels::{preview::{PreviewCommand, PreviewType}, entry::Entry};
/// use television::preview::previewers::command::format_command; /// use television::preview::previewers::command::format_command;
/// ///
/// let command = PreviewCommand { /// let command = PreviewCommand {
@ -209,7 +211,7 @@ pub fn try_preview(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::channels::entry::{Entry, PreviewType}; use crate::channels::{entry::Entry, preview::PreviewType};
#[test] #[test]
fn test_format_command() { fn test_format_command() {

View File

@ -294,7 +294,7 @@ pub fn draw_results_list(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::channels::entry::PreviewType; use crate::channels::preview::PreviewType;
use super::*; use super::*;

View File

@ -1,6 +1,9 @@
use crate::action::Action; use crate::action::Action;
use crate::cable::load_cable_channels; use crate::cable::load_cable_channels;
use crate::channels::entry::{Entry, PreviewType, ENTRY_PLACEHOLDER}; use crate::channels::{
entry::{Entry, ENTRY_PLACEHOLDER},
preview::PreviewType,
};
use crate::channels::{ use crate::channels::{
remote_control::RemoteControl, OnAir, TelevisionChannel, remote_control::RemoteControl, OnAir, TelevisionChannel,
}; };