refactor: simplify configuration and build code + leaner crate (#308)

This commit is contained in:
Alex Pasmantier 2025-01-25 13:26:07 +01:00 committed by GitHub
parent c7109044f0
commit 1e8c8dbc96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 113 additions and 2001 deletions

1520
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,24 +5,22 @@ edition = "2021"
description = "The revolution will be televised." description = "The revolution will be televised."
license = "MIT" license = "MIT"
authors = ["Alexandre Pasmantier <alex.pasmant@gmail.com>"] authors = ["Alexandre Pasmantier <alex.pasmant@gmail.com>"]
build = "build.rs"
repository = "https://github.com/alexpasmantier/television" repository = "https://github.com/alexpasmantier/television"
homepage = "https://github.com/alexpasmantier/television" homepage = "https://github.com/alexpasmantier/television"
keywords = ["search", "fuzzy", "preview", "tui", "terminal"] keywords = ["search", "fuzzy", "preview", "tui", "terminal"]
categories = [ categories = [
"command-line-utilities", "command-line-utilities",
"command-line-interface", "command-line-interface",
"concurrency", "concurrency",
"development-tools", "development-tools",
] ]
include = [ include = [
"LICENSE", "LICENSE",
"README.md", "README.md",
"themes/**/*.toml", "themes/**/*.toml",
"television/**", "television/**",
"build.rs", ".config/config.toml",
".config/config.toml", "cable",
"cable",
] ]
rust-version = "1.81" rust-version = "1.81"
@ -43,15 +41,14 @@ rustc-hash = "2.1"
syntect = { version = "5.2", default-features = false } syntect = { version = "5.2", default-features = false }
unicode-width = "0.2" unicode-width = "0.2"
clap = { version = "4.5", default-features = false, features = [ clap = { version = "4.5", default-features = false, features = [
"std", "std",
"derive", "derive",
"cargo", "cargo",
"string", "string",
] } ] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
ratatui = { version = "0.29", features = ["serde", "macros"] } ratatui = { version = "0.29", features = ["serde", "macros"] }
better-panic = "0.3" better-panic = "0.3"
config = "0.14"
signal-hook = "0.3" signal-hook = "0.3"
human-panic = "2.0" human-panic = "2.0"
copypasta = "0.10" copypasta = "0.10"
@ -88,9 +85,6 @@ name = "tv"
name = "results_list_benchmark" name = "results_list_benchmark"
harness = false harness = false
[build-dependencies]
vergen-gix = { version = "1.0", features = ["build", "cargo", "rustc"] }
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
crossterm = { version = "0.28.1", features = ["serde", "use-dev-tty"] } crossterm = { version = "0.28.1", features = ["serde", "use-dev-tty"] }

View File

@ -1,14 +0,0 @@
use std::error::Error;
use vergen_gix::{BuildBuilder, CargoBuilder, Emitter, RustcBuilder};
fn main() -> Result<(), Box<dyn Error>> {
let build = BuildBuilder::default().build_date(true).build()?;
let cargo = CargoBuilder::default().target_triple(true).build()?;
let rustc = RustcBuilder::default().semver(true).build()?;
Ok(Emitter::default()
.add_instructions(&build)?
.add_instructions(&cargo)?
.add_instructions(&rustc)?
.emit()?)
}

View File

@ -292,16 +292,7 @@ fn delimiter_parser(s: &str) -> Result<String, String> {
}) })
} }
const VERSION_MESSAGE: &str = concat!( const VERSION_MESSAGE: &str = env!("CARGO_PKG_VERSION");
env!("CARGO_PKG_VERSION"),
"\ntarget triple: ",
env!("VERGEN_CARGO_TARGET_TRIPLE"),
"\nbuild: ",
env!("VERGEN_RUSTC_SEMVER"),
" (",
env!("VERGEN_BUILD_DATE"),
")"
);
pub fn version() -> String { pub fn version() -> String {
let author = clap::crate_authors!(); let author = clap::crate_authors!();

View File

@ -29,10 +29,10 @@ impl Display for Binding {
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct KeyBindings(pub config::Map<Mode, config::Map<Action, Binding>>); pub struct KeyBindings(pub FxHashMap<Mode, FxHashMap<Action, Binding>>);
impl Deref for KeyBindings { impl Deref for KeyBindings {
type Target = config::Map<Mode, config::Map<Action, Binding>>; type Target = FxHashMap<Mode, FxHashMap<Action, Binding>>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
} }
@ -44,6 +44,31 @@ impl DerefMut for KeyBindings {
} }
} }
pub fn merge_keybindings(
mut keybindings: KeyBindings,
new_keybindings: &KeyBindings,
) -> KeyBindings {
for (mode, bindings) in new_keybindings.iter() {
for (action, binding) in bindings {
match keybindings.get_mut(mode) {
Some(mode_bindings) => {
mode_bindings.insert(action.clone(), binding.clone());
}
None => {
keybindings.insert(
*mode,
[(action.clone(), binding.clone())]
.iter()
.cloned()
.collect(),
);
}
}
}
}
keybindings
}
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum SerializedBinding { pub enum SerializedBinding {
@ -61,37 +86,38 @@ impl<'de> Deserialize<'de> for KeyBindings {
FxHashMap<Action, SerializedBinding>, FxHashMap<Action, SerializedBinding>,
>::deserialize(deserializer)?; >::deserialize(deserializer)?;
let keybindings = parsed_map let keybindings: FxHashMap<Mode, FxHashMap<Action, Binding>> =
.into_iter() parsed_map
.map(|(mode, inner_map)| { .into_iter()
let converted_inner_map = inner_map .map(|(mode, inner_map)| {
.into_iter() let converted_inner_map = inner_map
.map(|(cmd, binding)| { .into_iter()
( .map(|(cmd, binding)| {
cmd, (
match binding { cmd,
SerializedBinding::SingleKey(key_str) => { match binding {
Binding::SingleKey( SerializedBinding::SingleKey(key_str) => {
parse_key(&key_str).unwrap(), Binding::SingleKey(
) parse_key(&key_str).unwrap(),
} )
SerializedBinding::MultipleKeys(keys_str) => { }
Binding::MultipleKeys( SerializedBinding::MultipleKeys(
keys_str,
) => Binding::MultipleKeys(
keys_str keys_str
.iter() .iter()
.map(|key_str| { .map(|key_str| {
parse_key(key_str).unwrap() parse_key(key_str).unwrap()
}) })
.collect(), .collect(),
) ),
} },
}, )
) })
}) .collect();
.collect(); (mode, converted_inner_map)
(mode, converted_inner_map) })
}) .collect();
.collect();
Ok(KeyBindings(keybindings)) Ok(KeyBindings(keybindings))
} }

View File

@ -1,14 +1,14 @@
#![allow(clippy::module_name_repetitions)] #![allow(clippy::module_name_repetitions)]
use std::{env, path::PathBuf}; use std::{env, path::PathBuf};
use color_eyre::Result; use color_eyre::{eyre::Context, Result};
use directories::ProjectDirs; use directories::ProjectDirs;
use keybindings::merge_keybindings;
pub use keybindings::{parse_key, Binding, KeyBindings}; pub use keybindings::{parse_key, Binding, KeyBindings};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use previewers::PreviewersConfig; use previewers::PreviewersConfig;
use serde::Deserialize; use serde::Deserialize;
use shell_integration::ShellIntegrationConfig; use shell_integration::ShellIntegrationConfig;
use styles::Styles;
pub use themes::Theme; pub use themes::Theme;
use tracing::{debug, warn}; use tracing::{debug, warn};
use ui::UiConfig; use ui::UiConfig;
@ -16,18 +16,18 @@ use ui::UiConfig;
mod keybindings; mod keybindings;
mod previewers; mod previewers;
mod shell_integration; mod shell_integration;
mod styles;
mod themes; mod themes;
mod ui; mod ui;
const CONFIG: &str = include_str!("../.config/config.toml"); const DEFAULT_CONFIG: &str = include_str!("../../.config/config.toml");
#[allow(dead_code, clippy::module_name_repetitions)] #[allow(dead_code, clippy::module_name_repetitions)]
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub struct AppConfig { pub struct AppConfig {
#[serde(default)] #[serde(default = "get_data_dir")]
pub data_dir: PathBuf, pub data_dir: PathBuf,
#[serde(default)] #[serde(default = "get_config_dir")]
pub config_dir: PathBuf, pub config_dir: PathBuf,
#[serde(default = "default_frame_rate")] #[serde(default = "default_frame_rate")]
pub frame_rate: f64, pub frame_rate: f64,
@ -36,19 +36,23 @@ pub struct AppConfig {
} }
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Config { pub struct Config {
/// General application configuration
#[allow(clippy::struct_field_names)] #[allow(clippy::struct_field_names)]
#[serde(default, flatten)] #[serde(default, flatten)]
pub config: AppConfig, pub config: AppConfig,
/// Keybindings configuration
#[serde(default)] #[serde(default)]
pub keybindings: KeyBindings, pub keybindings: KeyBindings,
#[serde(default)] /// UI configuration
pub styles: Styles,
#[serde(default)] #[serde(default)]
pub ui: UiConfig, pub ui: UiConfig,
/// Previewers configuration
#[serde(default)] #[serde(default)]
pub previewers: PreviewersConfig, pub previewers: PreviewersConfig,
/// Shell integration configuration
#[serde(default)] #[serde(default)]
pub shell_integration: ShellIntegrationConfig, pub shell_integration: ShellIntegrationConfig,
} }
@ -77,68 +81,40 @@ impl Config {
#[allow(clippy::missing_panics_doc, clippy::missing_errors_doc)] #[allow(clippy::missing_panics_doc, clippy::missing_errors_doc)]
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
// Load the default_config values as base defaults // Load the default_config values as base defaults
let default_config: Config = let default_config: Config = toml::from_str(DEFAULT_CONFIG)
toml::from_str(CONFIG).expect("default config should be valid"); .wrap_err("Error parsing default config")?;
// initialize the config builder // initialize the config builder
let data_dir = get_data_dir(); let data_dir = get_data_dir();
let config_dir = get_config_dir(); let config_dir = get_config_dir();
std::fs::create_dir_all(&config_dir) std::fs::create_dir_all(&config_dir)
.expect("Failed creating configuration directory"); .expect("Failed creating configuration directory");
std::fs::create_dir_all(&data_dir) std::fs::create_dir_all(&data_dir)
.expect("Failed creating data directory"); .expect("Failed creating data directory");
let mut builder = config::Config::builder()
.set_default("data_dir", data_dir.to_str().unwrap())?
.set_default("config_dir", config_dir.to_str().unwrap())?
.set_default("frame_rate", default_config.config.frame_rate)?
.set_default("tick_rate", default_config.config.tick_rate)?
.set_default("ui", default_config.ui.clone())?
.set_default("previewers", default_config.previewers.clone())?
.set_default("theme", default_config.ui.theme.clone())?
.set_default(
"shell_integration",
default_config.shell_integration.clone(),
)?;
// Load the user's config file
let source = config::File::from(config_dir.join(CONFIG_FILE_NAME))
.format(config::FileFormat::Toml)
.required(false);
builder = builder.add_source(source);
if config_dir.join(CONFIG_FILE_NAME).is_file() { if config_dir.join(CONFIG_FILE_NAME).is_file() {
debug!("Found config file at {:?}", config_dir); debug!("Found config file at {:?}", config_dir);
let mut cfg: Self = builder.build()?.try_deserialize().unwrap();
//.with_context(|| {
// format!(
// "Error parsing config file at {:?}",
// config_dir.join(CONFIG_FILE_NAME)
// )
//})?;
for (mode, default_bindings) in default_config.keybindings.iter() { let path = config_dir.join(CONFIG_FILE_NAME);
let user_bindings = cfg.keybindings.entry(*mode).or_default(); let contents = std::fs::read_to_string(&path)?;
for (command, key) in default_bindings {
user_bindings
.entry(command.clone())
.or_insert_with(|| key.clone());
}
}
for (mode, default_styles) in default_config.styles.iter() { let cfg: Config = toml::from_str(&contents)
let user_styles = cfg.styles.entry(*mode).or_default(); .wrap_err(format!("error parsing config: {path:?}"))?;
for (style_key, style) in default_styles {
user_styles.entry(style_key.clone()).or_insert(*style); // merge keybindings with default keybindings
} let keybindings = merge_keybindings(
} default_config.keybindings,
&cfg.keybindings,
);
let cfg = Config { keybindings, ..cfg };
debug!("Config: {:?}", cfg); debug!("Config: {:?}", cfg);
Ok(cfg) Ok(cfg)
} else { } else {
warn!("No config file found at {:?}, creating default configuration file at that location.", config_dir); warn!("No config file found at {:?}, creating default configuration file at that location.", config_dir);
// create the default configuration file in the user's config directory // create the default configuration file in the user's config directory
std::fs::write(config_dir.join(CONFIG_FILE_NAME), CONFIG)?; std::fs::write(config_dir.join(CONFIG_FILE_NAME), DEFAULT_CONFIG)?;
Ok(default_config) Ok(default_config)
} }
} }

View File

@ -1,7 +1,4 @@
use std::collections::HashMap;
use crate::preview::{previewers, PreviewerConfig}; use crate::preview::{previewers, PreviewerConfig};
use config::ValueKind;
use serde::Deserialize; use serde::Deserialize;
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
@ -20,26 +17,11 @@ impl From<PreviewersConfig> for PreviewerConfig {
} }
} }
impl From<PreviewersConfig> for ValueKind {
fn from(val: PreviewersConfig) -> Self {
let mut m = HashMap::new();
m.insert(String::from("basic"), val.basic.into());
m.insert(String::from("file"), val.file.into());
m.insert(String::from("env_var"), val.env_var.into());
ValueKind::Table(m)
}
}
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
pub struct BasicPreviewerConfig {} pub struct BasicPreviewerConfig {}
impl From<BasicPreviewerConfig> for ValueKind {
fn from(_val: BasicPreviewerConfig) -> Self {
ValueKind::Table(HashMap::new())
}
}
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(default)]
pub struct FilePreviewerConfig { pub struct FilePreviewerConfig {
//pub max_file_size: u64, //pub max_file_size: u64,
pub theme: String, pub theme: String,
@ -54,19 +36,5 @@ impl Default for FilePreviewerConfig {
} }
} }
impl From<FilePreviewerConfig> for ValueKind {
fn from(val: FilePreviewerConfig) -> Self {
let mut m = HashMap::new();
m.insert(String::from("theme"), ValueKind::String(val.theme).into());
ValueKind::Table(m)
}
}
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
pub struct EnvVarPreviewerConfig {} pub struct EnvVarPreviewerConfig {}
impl From<EnvVarPreviewerConfig> for ValueKind {
fn from(_val: EnvVarPreviewerConfig) -> Self {
ValueKind::Table(HashMap::new())
}
}

View File

@ -1,5 +1,3 @@
use std::collections::HashMap;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::Deserialize; use serde::Deserialize;
@ -7,20 +5,3 @@ use serde::Deserialize;
pub struct ShellIntegrationConfig { pub struct ShellIntegrationConfig {
pub commands: FxHashMap<String, String>, pub commands: FxHashMap<String, String>,
} }
impl From<ShellIntegrationConfig> for config::ValueKind {
fn from(val: ShellIntegrationConfig) -> Self {
let mut m = HashMap::new();
m.insert(
String::from("commands"),
config::ValueKind::Table(
val.commands
.into_iter()
.map(|(k, v)| (k, config::ValueKind::String(v).into()))
.collect(),
)
.into(),
);
config::ValueKind::Table(m)
}
}

View File

@ -1,207 +0,0 @@
use crate::screen::mode::Mode;
use ratatui::prelude::{Color, Modifier, Style};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Deserializer};
use std::ops::{Deref, DerefMut};
#[derive(Clone, Debug, Default)]
pub struct Styles(pub FxHashMap<Mode, FxHashMap<String, Style>>);
impl Deref for Styles {
type Target = FxHashMap<Mode, FxHashMap<String, Style>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Styles {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'de> Deserialize<'de> for Styles {
fn deserialize<D>(deserializer: D) -> color_eyre::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let parsed_map =
FxHashMap::<Mode, FxHashMap<String, String>>::deserialize(
deserializer,
)?;
let styles = parsed_map
.into_iter()
.map(|(mode, inner_map)| {
let converted_inner_map = inner_map
.into_iter()
.map(|(str, style)| (str, parse_style(&style)))
.collect();
(mode, converted_inner_map)
})
.collect();
Ok(Styles(styles))
}
}
pub fn parse_style(line: &str) -> Style {
let (foreground, background) =
line.split_at(line.to_lowercase().find("on ").unwrap_or(line.len()));
let foreground = process_color_string(foreground);
let background = process_color_string(&background.replace("on ", ""));
let mut style = Style::default();
if let Some(fg) = parse_color(&foreground.0) {
style = style.fg(fg);
}
if let Some(bg) = parse_color(&background.0) {
style = style.bg(bg);
}
style = style.add_modifier(foreground.1 | background.1);
style
}
pub fn process_color_string(color_str: &str) -> (String, Modifier) {
let color = color_str
.replace("grey", "gray")
.replace("bright ", "")
.replace("bold ", "")
.replace("underline ", "")
.replace("inverse ", "");
let mut modifiers = Modifier::empty();
if color_str.contains("underline") {
modifiers |= Modifier::UNDERLINED;
}
if color_str.contains("bold") {
modifiers |= Modifier::BOLD;
}
if color_str.contains("inverse") {
modifiers |= Modifier::REVERSED;
}
(color, modifiers)
}
#[allow(clippy::cast_possible_truncation)]
pub fn parse_color(s: &str) -> Option<Color> {
let s = s.trim_start();
let s = s.trim_end();
if s.contains("bright color") {
let s = s.trim_start_matches("bright ");
let c = s
.trim_start_matches("color")
.parse::<u8>()
.unwrap_or_default();
Some(Color::Indexed(c.wrapping_shl(8)))
} else if s.contains("color") {
let c = s
.trim_start_matches("color")
.parse::<u8>()
.unwrap_or_default();
Some(Color::Indexed(c))
} else if s.contains("gray") {
let c = 232
+ s.trim_start_matches("gray")
.parse::<u8>()
.unwrap_or_default();
Some(Color::Indexed(c))
} else if s.contains("rgb") {
let red =
(s.as_bytes()[3] as char).to_digit(10).unwrap_or_default() as u8;
let green =
(s.as_bytes()[4] as char).to_digit(10).unwrap_or_default() as u8;
let blue =
(s.as_bytes()[5] as char).to_digit(10).unwrap_or_default() as u8;
let c = 16 + red * 36 + green * 6 + blue;
Some(Color::Indexed(c))
} else if s == "bold black" {
Some(Color::Indexed(8))
} else if s == "bold red" {
Some(Color::Indexed(9))
} else if s == "bold green" {
Some(Color::Indexed(10))
} else if s == "bold yellow" {
Some(Color::Indexed(11))
} else if s == "bold blue" {
Some(Color::Indexed(12))
} else if s == "bold magenta" {
Some(Color::Indexed(13))
} else if s == "bold cyan" {
Some(Color::Indexed(14))
} else if s == "bold white" {
Some(Color::Indexed(15))
} else if s == "black" {
Some(Color::Indexed(0))
} else if s == "red" {
Some(Color::Indexed(1))
} else if s == "green" {
Some(Color::Indexed(2))
} else if s == "yellow" {
Some(Color::Indexed(3))
} else if s == "blue" {
Some(Color::Indexed(4))
} else if s == "magenta" {
Some(Color::Indexed(5))
} else if s == "cyan" {
Some(Color::Indexed(6))
} else if s == "white" {
Some(Color::Indexed(7))
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_style_default() {
let style = parse_style("");
assert_eq!(style, Style::default());
}
#[test]
fn test_parse_style_foreground() {
let style = parse_style("red");
assert_eq!(style.fg, Some(Color::Indexed(1)));
}
#[test]
fn test_parse_style_background() {
let style = parse_style("on blue");
assert_eq!(style.bg, Some(Color::Indexed(4)));
}
#[test]
fn test_parse_style_modifiers() {
let style = parse_style("underline red on blue");
assert_eq!(style.fg, Some(Color::Indexed(1)));
assert_eq!(style.bg, Some(Color::Indexed(4)));
}
#[test]
fn test_process_color_string() {
let (color, modifiers) =
process_color_string("underline bold inverse gray");
assert_eq!(color, "gray");
assert!(modifiers.contains(Modifier::UNDERLINED));
assert!(modifiers.contains(Modifier::BOLD));
assert!(modifiers.contains(Modifier::REVERSED));
}
#[test]
fn test_parse_color_rgb() {
let color = parse_color("rgb123");
let expected = 16 + 36 + 2 * 6 + 3;
assert_eq!(color, Some(Color::Indexed(expected)));
}
#[test]
fn test_parse_color_unknown() {
let color = parse_color("unknown");
assert_eq!(color, None);
}
}

View File

@ -1,6 +1,3 @@
use std::collections::HashMap;
use config::ValueKind;
use serde::Deserialize; use serde::Deserialize;
use crate::screen::layout::{InputPosition, PreviewTitlePosition}; use crate::screen::layout::{InputPosition, PreviewTitlePosition};
@ -10,6 +7,7 @@ use super::themes::DEFAULT_THEME;
const DEFAULT_UI_SCALE: u16 = 100; const DEFAULT_UI_SCALE: u16 = 100;
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(default)]
pub struct UiConfig { pub struct UiConfig {
pub use_nerd_font_icons: bool, pub use_nerd_font_icons: bool,
pub ui_scale: u16, pub ui_scale: u16,
@ -34,39 +32,3 @@ impl Default for UiConfig {
} }
} }
} }
impl From<UiConfig> for ValueKind {
fn from(val: UiConfig) -> Self {
let mut m = HashMap::new();
m.insert(
String::from("use_nerd_font_icons"),
ValueKind::Boolean(val.use_nerd_font_icons).into(),
);
m.insert(
String::from("ui_scale"),
ValueKind::U64(val.ui_scale.into()).into(),
);
m.insert(
String::from("show_help_bar"),
ValueKind::Boolean(val.show_help_bar).into(),
);
m.insert(
String::from("show_preview_panel"),
ValueKind::Boolean(val.show_preview_panel).into(),
);
m.insert(
String::from("input_position"),
ValueKind::String(val.input_bar_position.to_string()).into(),
);
m.insert(
String::from("preview_title_position"),
match val.preview_title_position {
Some(pos) => ValueKind::String(pos.to_string()),
None => ValueKind::Nil,
}
.into(),
);
m.insert(String::from("theme"), ValueKind::String(val.theme).into());
ValueKind::Table(m)
}
}

View File

@ -1,14 +1,14 @@
use color_eyre::Result; use color_eyre::Result;
use tracing_subscriber::{fmt, prelude::*, EnvFilter}; use tracing_subscriber::{fmt, prelude::*, EnvFilter};
use crate::config; use crate::config::get_data_dir;
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref LOG_FILE: String = format!("{}.log", env!("CARGO_PKG_NAME")); pub static ref LOG_FILE: String = format!("{}.log", env!("CARGO_PKG_NAME"));
} }
pub fn init() -> Result<()> { pub fn init() -> Result<()> {
let directory = config::get_data_dir(); let directory = get_data_dir();
std::fs::create_dir_all(directory.clone())?; std::fs::create_dir_all(directory.clone())?;
let log_path = directory.join(LOG_FILE.clone()); let log_path = directory.join(LOG_FILE.clone());
let log_file = std::fs::File::create(log_path)?; let log_file = std::fs::File::create(log_path)?;

View File

@ -40,40 +40,6 @@ pub fn build_metadata_table<'a>(
)), )),
]); ]);
let target_triple_row = Row::new(vec![
Cell::from(Span::styled(
"target triple: ",
Style::default().fg(colorscheme.help.metadata_field_name_fg),
)),
Cell::from(Span::styled(
&app_metadata.build.target_triple,
Style::default().fg(colorscheme.help.metadata_field_value_fg),
)),
]);
let build_row = Row::new(vec![
Cell::from(Span::styled(
"build: ",
Style::default().fg(colorscheme.help.metadata_field_name_fg),
)),
Cell::from(Span::styled(
&app_metadata.build.rustc_version,
Style::default().fg(colorscheme.help.metadata_field_value_fg),
)),
Cell::from(Span::styled(
" (",
Style::default().fg(colorscheme.help.metadata_field_name_fg),
)),
Cell::from(Span::styled(
&app_metadata.build.build_date,
Style::default().fg(colorscheme.help.metadata_field_value_fg),
)),
Cell::from(Span::styled(
")",
Style::default().fg(colorscheme.help.metadata_field_name_fg),
)),
]);
let current_dir_row = Row::new(vec![ let current_dir_row = Row::new(vec![
Cell::from(Span::styled( Cell::from(Span::styled(
"current directory: ", "current directory: ",
@ -115,8 +81,6 @@ pub fn build_metadata_table<'a>(
Table::new( Table::new(
vec![ vec![
version_row, version_row,
target_triple_row,
build_row,
current_dir_row, current_dir_row,
current_channel_row, current_channel_row,
current_mode_row, current_mode_row,

View File

@ -21,7 +21,7 @@ use crate::screen::preview::draw_preview_content_block;
use crate::screen::remote_control::draw_remote_control; use crate::screen::remote_control::draw_remote_control;
use crate::screen::results::draw_results_list; use crate::screen::results::draw_results_list;
use crate::screen::spinner::{Spinner, SpinnerState}; use crate::screen::spinner::{Spinner, SpinnerState};
use crate::utils::metadata::{AppMetadata, BuildMetadata}; use crate::utils::metadata::AppMetadata;
use crate::utils::strings::EMPTY_STRING; use crate::utils::strings::EMPTY_STRING;
use crate::{cable::load_cable_channels, keymap::Keymap}; use crate::{cable::load_cable_channels, keymap::Keymap};
use color_eyre::Result; use color_eyre::Result;
@ -75,11 +75,6 @@ impl Television {
let app_metadata = AppMetadata::new( let app_metadata = AppMetadata::new(
env!("CARGO_PKG_VERSION").to_string(), env!("CARGO_PKG_VERSION").to_string(),
BuildMetadata::new(
env!("VERGEN_RUSTC_SEMVER").to_string(),
env!("VERGEN_BUILD_DATE").to_string(),
env!("VERGEN_CARGO_TARGET_TRIPLE").to_string(),
),
std::env::current_dir() std::env::current_dir()
.expect("Could not get current directory") .expect("Could not get current directory")
.to_string_lossy() .to_string_lossy()

View File

@ -1,38 +1,12 @@
pub struct BuildMetadata {
pub rustc_version: String,
pub build_date: String,
pub target_triple: String,
}
impl BuildMetadata {
pub fn new(
rustc_version: String,
build_date: String,
target_triple: String,
) -> Self {
Self {
rustc_version,
build_date,
target_triple,
}
}
}
pub struct AppMetadata { pub struct AppMetadata {
pub version: String, pub version: String,
pub build: BuildMetadata,
pub current_directory: String, pub current_directory: String,
} }
impl AppMetadata { impl AppMetadata {
pub fn new( pub fn new(version: String, current_directory: String) -> Self {
version: String,
build: BuildMetadata,
current_directory: String,
) -> Self {
Self { Self {
version, version,
build,
current_directory, current_directory,
} }
} }