top menus

This commit is contained in:
alexpasmantier 2024-10-25 23:29:07 +02:00
parent 4bec64e245
commit 9eea37a5b5
9 changed files with 327 additions and 155 deletions

View File

@ -4,9 +4,7 @@ down = "SelectNextEntry"
up = "SelectPrevEntry" up = "SelectPrevEntry"
ctrl-n = "SelectNextEntry" ctrl-n = "SelectNextEntry"
ctrl-p = "SelectPrevEntry" ctrl-p = "SelectPrevEntry"
alt-down = "ScrollPreviewHalfPageDown"
ctrl-d = "ScrollPreviewHalfPageDown" ctrl-d = "ScrollPreviewHalfPageDown"
alt-up = "ScrollPreviewHalfPageUp"
ctrl-u = "ScrollPreviewHalfPageUp" ctrl-u = "ScrollPreviewHalfPageUp"
enter = "SelectEntry" enter = "SelectEntry"
ctrl-enter = "SendToChannel" ctrl-enter = "SendToChannel"
@ -20,4 +18,3 @@ ctrl-n = "SelectNextEntry"
ctrl-p = "SelectPrevEntry" ctrl-p = "SelectPrevEntry"
enter = "SelectEntry" enter = "SelectEntry"
ctrl-s = "ToggleChannelSelection" ctrl-s = "ToggleChannelSelection"

View File

@ -8,12 +8,12 @@
_______________ _______________
|,----------. |\ |,----------. |\
|| |=| | || |=| |
|| || | | || | | |
|| . _o| | | || |o| |
|`-----------' |/ |`-----------' |/
~~~~~~~~~~~~~~~ `--------------'
__ __ _ _ __ __ _ _
/ /____ / /__ _ __(_)__ (_)__ ___ / /____ / /__ _ __(_)__ (_)__ ___
/ __/ -_) / -_) |/ / (_-</ / _ \/ _ \ / __/ -_) / -_) |/ / (_-</ / _ \/ _ \
\__/\__/_/\__/|___/_/___/_/\___/_//_/ \__/\__/_/\__/|___/_/___/_/\___/_//_/

View File

@ -14,12 +14,15 @@ use ratatui::{
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashMap, str::FromStr}; use std::{collections::HashMap, str::FromStr};
use strum::Display;
use tokio::sync::mpsc::UnboundedSender; use tokio::sync::mpsc::UnboundedSender;
use crate::ui::input::Input;
use crate::ui::layout::{Dimensions, Layout};
use crate::ui::preview::DEFAULT_PREVIEW_TITLE_FG; use crate::ui::preview::DEFAULT_PREVIEW_TITLE_FG;
use crate::ui::results::build_results_list; use crate::ui::results::build_results_list;
use crate::ui::{
layout::{Dimensions, Layout},
logo::build_logo_paragraph,
};
use crate::utils::strings::EMPTY_STRING; use crate::utils::strings::EMPTY_STRING;
use crate::{action::Action, config::Config}; use crate::{action::Action, config::Config};
use crate::{channels::tv_guide::TvGuide, ui::get_border_style}; use crate::{channels::tv_guide::TvGuide, ui::get_border_style};
@ -27,13 +30,16 @@ use crate::{channels::OnAir, utils::strings::shrink_with_ellipsis};
use crate::{ use crate::{
channels::TelevisionChannel, ui::input::actions::InputActionHandler, channels::TelevisionChannel, ui::input::actions::InputActionHandler,
}; };
use crate::{channels::UnitChannel, ui::input::Input};
use crate::{ use crate::{
entry::{Entry, ENTRY_PLACEHOLDER}, entry::{Entry, ENTRY_PLACEHOLDER},
ui::spinner::Spinner, ui::spinner::Spinner,
}; };
use crate::{previewers::Previewer, ui::spinner::SpinnerState}; use crate::{previewers::Previewer, ui::spinner::SpinnerState};
#[derive(PartialEq, Copy, Clone, Hash, Eq, Debug, Serialize, Deserialize)] #[derive(
PartialEq, Copy, Clone, Hash, Eq, Debug, Serialize, Deserialize, Display,
)]
pub enum Mode { pub enum Mode {
Channel, Channel,
Guide, Guide,
@ -98,6 +104,10 @@ impl Television {
} }
} }
pub fn current_channel(&self) -> UnitChannel {
UnitChannel::from(&self.channel)
}
/// FIXME: this needs rework /// FIXME: this needs rework
pub fn change_channel(&mut self, channel: TelevisionChannel) { pub fn change_channel(&mut self, channel: TelevisionChannel) {
self.reset_preview_scroll(); self.reset_preview_scroll();
@ -304,19 +314,17 @@ impl Television {
Action::ScrollPreviewUp => self.scroll_preview_up(1), Action::ScrollPreviewUp => self.scroll_preview_up(1),
Action::ScrollPreviewHalfPageDown => self.scroll_preview_down(20), Action::ScrollPreviewHalfPageDown => self.scroll_preview_down(20),
Action::ScrollPreviewHalfPageUp => self.scroll_preview_up(20), Action::ScrollPreviewHalfPageUp => self.scroll_preview_up(20),
Action::ToggleChannelSelection => { Action::ToggleChannelSelection => match self.mode {
match self.mode { Mode::Channel => {
Mode::Channel => { self.reset_screen();
self.reset_screen(); self.mode = Mode::Guide;
self.mode = Mode::Guide;
}
Mode::Guide => {
self.reset_screen();
self.mode = Mode::Channel;
}
Mode::SendToChannel => {}
} }
} Mode::Guide => {
self.reset_screen();
self.mode = Mode::Channel;
}
Mode::SendToChannel => {}
},
Action::SelectEntry => { Action::SelectEntry => {
if let Some(entry) = self.get_selected_entry() { if let Some(entry) = self.get_selected_entry() {
match self.mode { match self.mode {
@ -387,19 +395,38 @@ impl Television {
}, },
); );
let help_block = Block::default() let metadata_block = Block::default()
.borders(Borders::NONE) .borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(Color::Blue))
.padding(Padding::horizontal(1))
.style(Style::default());
let metadata_table = self.build_metadata_table().block(metadata_block);
f.render_widget(metadata_table, layout.help_bar_left);
let keymaps_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(Color::Blue))
.style(Style::default()) .style(Style::default())
.padding(Padding::uniform(1)); .padding(Padding::horizontal(1));
let help_text = self let keymaps_table = self.build_help_table()?.block(keymaps_block);
.build_help_paragraph()?
.style(Style::default().fg(Color::DarkGray).italic())
.alignment(Alignment::Center)
.wrap(Wrap { trim: true })
.block(help_block);
f.render_widget(help_text, layout.help_bar); f.render_widget(keymaps_table, layout.help_bar_middle);
let logo_block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(Color::Blue))
.style(Style::default().fg(Color::Yellow))
.padding(Padding::horizontal(1));
let logo_paragraph = build_logo_paragraph().block(logo_block);
f.render_widget(logo_paragraph, layout.help_bar_right);
self.results_area_height = u32::from(layout.results.height); self.results_area_height = u32::from(layout.results.height);
if let Some(preview_window) = layout.preview_window { if let Some(preview_window) = layout.preview_window {
@ -489,7 +516,7 @@ impl Television {
"> ", "> ",
Style::default().fg(DEFAULT_INPUT_FG).bold(), Style::default().fg(DEFAULT_INPUT_FG).bold(),
)) ))
.block(arrow_block); .block(arrow_block);
f.render_widget(arrow, inner_input_chunks[0]); f.render_widget(arrow, inner_input_chunks[0]);
let interactive_input_block = Block::default(); let interactive_input_block = Block::default();
@ -527,8 +554,8 @@ impl Television {
), ),
Style::default().fg(DEFAULT_RESULTS_COUNT_FG).italic(), Style::default().fg(DEFAULT_RESULTS_COUNT_FG).italic(),
)) ))
.block(result_count_block) .block(result_count_block)
.alignment(Alignment::Right); .alignment(Alignment::Right);
f.render_widget(result_count_paragraph, inner_input_chunks[2]); f.render_widget(result_count_paragraph, inner_input_chunks[2]);
// Make the cursor visible and ask tui-rs to put it at the // Make the cursor visible and ask tui-rs to put it at the
@ -537,8 +564,8 @@ impl Television {
// Put cursor past the end of the input text // Put cursor past the end of the input text
inner_input_chunks[1].x inner_input_chunks[1].x
+ u16::try_from( + u16::try_from(
self.input.visual_cursor().max(scroll) - scroll, self.input.visual_cursor().max(scroll) - scroll,
)?, )?,
// Move one line down, from the border to the input line // Move one line down, from the border to the input line
inner_input_chunks[1].y, inner_input_chunks[1].y,
)); ));

View File

@ -3,6 +3,8 @@ use ratatui::style::{Color, Style, Stylize};
pub mod help; pub mod help;
pub mod input; pub mod input;
pub mod layout; pub mod layout;
pub mod logo;
pub mod metadata;
pub mod preview; pub mod preview;
pub mod results; pub mod results;
pub mod spinner; pub mod spinner;

View File

@ -1,8 +1,9 @@
use color_eyre::eyre::{OptionExt, Result}; use color_eyre::eyre::{OptionExt, Result};
use ratatui::{ use ratatui::{
layout::Constraint,
style::{Color, Style}, style::{Color, Style},
text::{Line, Span}, text::{Line, Span},
widgets::Paragraph, widgets::{Cell, Row, Table},
}; };
use std::collections::HashMap; use std::collections::HashMap;
@ -12,142 +13,118 @@ use crate::{
television::{Mode, Television}, television::{Mode, Television},
}; };
const SEPARATOR: &str = " ";
const ACTION_COLOR: Color = Color::DarkGray; const ACTION_COLOR: Color = Color::DarkGray;
const KEY_COLOR: Color = Color::LightYellow; const KEY_COLOR: Color = Color::LightYellow;
impl Television { impl Television {
pub fn build_help_paragraph<'a>(&self) -> Result<Paragraph<'a>> { pub fn build_help_table<'a>(&self) -> Result<Table<'a>> {
match self.mode { match self.mode {
Mode::Channel => self.build_help_paragraph_for_channel(), Mode::Channel => self.build_help_table_for_channel(),
Mode::Guide => self.build_help_paragraph_for_channel_selection(), Mode::Guide => self.build_help_table_for_channel_selection(),
Mode::SendToChannel => self.build_help_paragraph_for_channel(), Mode::SendToChannel => self.build_help_table_for_channel(),
} }
} }
fn build_help_paragraph_for_channel<'a>(&self) -> Result<Paragraph<'a>> { fn build_help_table_for_channel<'a>(&self) -> Result<Table<'a>> {
let keymap = self.keymap_for_mode()?; let keymap = self.keymap_for_mode()?;
let mut lines = Vec::new();
// NAVIGATION and SELECTION line
let mut ns_line = Line::default();
// Results navigation // Results navigation
let prev = keys_for_action(keymap, Action::SelectPrevEntry); let prev = keys_for_action(keymap, &Action::SelectPrevEntry);
let next = keys_for_action(keymap, Action::SelectNextEntry); let next = keys_for_action(keymap, &Action::SelectNextEntry);
let results_spans = let results_row = Row::new(build_cells_for_key_groups(
build_spans_for_key_groups("↕ Results", vec![prev, next]); "↕ Results navigation",
vec![prev, next],
ns_line.extend(results_spans); ));
ns_line.push_span(Span::styled(SEPARATOR, Style::default()));
// Preview navigation // Preview navigation
let up_keys = keys_for_action(keymap, Action::ScrollPreviewHalfPageUp); let up_keys =
keys_for_action(keymap, &Action::ScrollPreviewHalfPageUp);
let down_keys = let down_keys =
keys_for_action(keymap, Action::ScrollPreviewHalfPageDown); keys_for_action(keymap, &Action::ScrollPreviewHalfPageDown);
let preview_spans = let preview_row = Row::new(build_cells_for_key_groups(
build_spans_for_key_groups("↕ Preview", vec![up_keys, down_keys]); "↕ Preview navigation",
vec![up_keys, down_keys],
ns_line.extend(preview_spans); ));
ns_line.push_span(Span::styled(SEPARATOR, Style::default()));
// Select entry // Select entry
let select_entry_keys = keys_for_action(keymap, Action::SelectEntry); let select_entry_keys = keys_for_action(keymap, &Action::SelectEntry);
let select_entry_spans = build_spans_for_key_groups( let select_entry_row = Row::new(build_cells_for_key_groups(
"Select entry", "Select entry",
vec![select_entry_keys], vec![select_entry_keys],
); ));
ns_line.extend(select_entry_spans);
ns_line.push_span(Span::styled(SEPARATOR, Style::default()));
// Send to channel // Send to channel
let send_to_channel_keys = let send_to_channel_keys =
keys_for_action(keymap, Action::SendToChannel); keys_for_action(keymap, &Action::SendToChannel);
// TODO: add send icon let send_to_channel_row = Row::new(build_cells_for_key_groups(
let send_to_channel_spans = "⇉ Send results to",
build_spans_for_key_groups("Send to", vec![send_to_channel_keys]); vec![send_to_channel_keys],
));
ns_line.extend(send_to_channel_spans);
ns_line.push_span(Span::styled(SEPARATOR, Style::default()));
// Switch channels // Switch channels
let switch_channels_keys = let switch_channels_keys =
keys_for_action(keymap, Action::ToggleChannelSelection); keys_for_action(keymap, &Action::ToggleChannelSelection);
let switch_channels_spans = build_spans_for_key_groups( let switch_channels_row = Row::new(build_cells_for_key_groups(
"Switch channels", "Switch channels",
vec![switch_channels_keys], vec![switch_channels_keys],
); ));
ns_line.extend(switch_channels_spans);
lines.push(ns_line);
// MISC line (quit, help, etc.) // MISC line (quit, help, etc.)
// let mut misc_line = Line::default(); // Quit ⏼
// let quit_keys = keys_for_action(keymap, &Action::Quit);
// // Quit let quit_row =
// let quit_keys = keys_for_action(keymap, Action::Quit); Row::new(build_cells_for_key_groups("⏼ Quit", vec![quit_keys]));
// let quit_spans = build_spans_for_key_groups("Quit", vec![quit_keys]);
//
// misc_line.extend(quit_spans);
//
// lines.push(misc_line);
Ok(Paragraph::new(lines)) let widths = vec![Constraint::Fill(1), Constraint::Fill(2)];
Ok(Table::new(
vec![
results_row,
preview_row,
select_entry_row,
send_to_channel_row,
switch_channels_row,
quit_row,
],
widths,
))
} }
fn build_help_paragraph_for_channel_selection<'a>( fn build_help_table_for_channel_selection<'a>(&self) -> Result<Table<'a>> {
&self,
) -> Result<Paragraph<'a>> {
let keymap = self.keymap_for_mode()?; let keymap = self.keymap_for_mode()?;
let mut lines = Vec::new();
// NAVIGATION + SELECTION line
let mut ns_line = Line::default();
// Results navigation // Results navigation
let prev = keys_for_action(keymap, Action::SelectPrevEntry); let prev = keys_for_action(keymap, &Action::SelectPrevEntry);
let next = keys_for_action(keymap, Action::SelectNextEntry); let next = keys_for_action(keymap, &Action::SelectNextEntry);
let results_spans = let results_row = Row::new(build_cells_for_key_groups(
build_spans_for_key_groups("↕ Results", vec![prev, next]); "↕ Results",
vec![prev, next],
ns_line.extend(results_spans); ));
ns_line.push_span(Span::styled(SEPARATOR, Style::default()));
// Select entry // Select entry
let select_entry_keys = keys_for_action(keymap, Action::SelectEntry); let select_entry_keys = keys_for_action(keymap, &Action::SelectEntry);
let select_entry_spans = build_spans_for_key_groups( let select_entry_row = Row::new(build_cells_for_key_groups(
"Select entry", "Select entry",
vec![select_entry_keys], vec![select_entry_keys],
); ));
ns_line.extend(select_entry_spans);
ns_line.push_span(Span::styled(SEPARATOR, Style::default()));
// Switch channels // Switch channels
let switch_channels_keys = let switch_channels_keys =
keys_for_action(keymap, Action::ToggleChannelSelection); keys_for_action(keymap, &Action::ToggleChannelSelection);
let switch_channels_spans = build_spans_for_key_groups( let switch_channels_row = Row::new(build_cells_for_key_groups(
"Switch channels", "Switch channels",
vec![switch_channels_keys], vec![switch_channels_keys],
); ));
ns_line.extend(switch_channels_spans);
lines.push(ns_line);
// MISC line (quit, help, etc.)
// let mut misc_line = Line::default();
// Quit // Quit
// let quit_keys = keys_for_action(keymap, Action::Quit); let quit_keys = keys_for_action(keymap, &Action::Quit);
// let quit_spans = build_spans_for_key_groups("Quit", vec![quit_keys]); let quit_row =
Row::new(build_cells_for_key_groups("Quit", vec![quit_keys]));
// misc_line.extend(quit_spans); Ok(Table::new(
vec![results_row, select_entry_row, switch_channels_row, quit_row],
// lines.push(misc_line); vec![Constraint::Fill(1), Constraint::Fill(2)],
))
Ok(Paragraph::new(lines))
} }
/// Get the keymap for the current mode. /// Get the keymap for the current mode.
@ -189,21 +166,23 @@ impl Television {
/// ///
/// assert_eq!(spans.len(), 5); /// assert_eq!(spans.len(), 5);
/// ``` /// ```
fn build_spans_for_key_groups( fn build_cells_for_key_groups(
group_name: &str, group_name: &str,
key_groups: Vec<Vec<String>>, key_groups: Vec<Vec<String>>,
) -> Vec<Span> { ) -> Vec<Cell> {
if key_groups.is_empty() || key_groups.iter().all(|keys| keys.is_empty()) { if key_groups.is_empty() || key_groups.iter().all(std::vec::Vec::is_empty)
return vec![]; {
return vec![group_name.into(), "No keybindings".into()];
} }
let non_empty_groups = key_groups.iter().filter(|keys| !keys.is_empty()); let non_empty_groups = key_groups.iter().filter(|keys| !keys.is_empty());
let mut spans = vec![ let mut cells = vec![Cell::from(Span::styled(
Span::styled( group_name.to_owned() + ": ",
group_name.to_owned() + ": ", Style::default().fg(ACTION_COLOR),
Style::default().fg(ACTION_COLOR), ))];
),
Span::styled("[", Style::default().fg(KEY_COLOR)), let mut spans = Vec::new();
]; //spans.push(Span::styled("[", Style::default().fg(KEY_COLOR)));
let key_group_spans: Vec<Span> = non_empty_groups let key_group_spans: Vec<Span> = non_empty_groups
.map(|keys| { .map(|keys| {
let key_group = keys.join(", "); let key_group = keys.join(", ");
@ -213,12 +192,14 @@ fn build_spans_for_key_groups(
key_group_spans.iter().enumerate().for_each(|(i, span)| { key_group_spans.iter().enumerate().for_each(|(i, span)| {
spans.push(span.clone()); spans.push(span.clone());
if i < key_group_spans.len() - 1 { if i < key_group_spans.len() - 1 {
spans.push(Span::styled(" | ", Style::default().fg(KEY_COLOR))); spans.push(Span::styled(" / ", Style::default().fg(KEY_COLOR)));
} }
}); });
spans.push(Span::styled("]", Style::default().fg(KEY_COLOR))); //spans.push(Span::styled("]", Style::default().fg(KEY_COLOR)));
spans cells.push(Cell::from(Line::from(spans)));
cells
} }
/// Get the keys for a given action. /// Get the keys for a given action.
@ -246,11 +227,11 @@ fn build_spans_for_key_groups(
/// ``` /// ```
fn keys_for_action( fn keys_for_action(
keymap: &HashMap<Key, Action>, keymap: &HashMap<Key, Action>,
action: Action, action: &Action,
) -> Vec<String> { ) -> Vec<String> {
keymap keymap
.iter() .iter()
.filter(|(_key, act)| **act == action) .filter(|(_key, act)| *act == action)
.map(|(key, _act)| format!("{key}")) .map(|(key, _act)| format!("{key}"))
.collect() .collect()
} }

View File

@ -19,7 +19,9 @@ impl Default for Dimensions {
} }
pub struct Layout { pub struct Layout {
pub help_bar: Rect, pub help_bar_left: Rect,
pub help_bar_middle: Rect,
pub help_bar_right: Rect,
pub results: Rect, pub results: Rect,
pub input: Rect, pub input: Rect,
pub preview_title: Option<Rect>, pub preview_title: Option<Rect>,
@ -28,14 +30,18 @@ pub struct Layout {
impl Layout { impl Layout {
pub fn new( pub fn new(
help_bar: Rect, help_bar_left: Rect,
help_bar_middle: Rect,
help_bar_right: Rect,
results: Rect, results: Rect,
input: Rect, input: Rect,
preview_title: Option<Rect>, preview_title: Option<Rect>,
preview_window: Option<Rect>, preview_window: Option<Rect>,
) -> Self { ) -> Self {
Self { Self {
help_bar, help_bar_left,
help_bar_middle,
help_bar_right,
results, results,
input, input,
preview_title, preview_title,
@ -52,9 +58,19 @@ impl Layout {
// split the main block into two vertical chunks (help bar + rest) // split the main block into two vertical chunks (help bar + rest)
let hz_chunks = layout::Layout::default() let hz_chunks = layout::Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints([Constraint::Fill(1), Constraint::Length(5)]) .constraints([Constraint::Length(9), Constraint::Fill(1)])
.split(main_block); .split(main_block);
// split the help bar into three horizontal chunks (left + center + right)
let help_bar_chunks = layout::Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Fill(1),
Constraint::Fill(1),
Constraint::Length(24),
])
.split(hz_chunks[0]);
if with_preview { if with_preview {
// split the main block into two vertical chunks // split the main block into two vertical chunks
let vt_chunks = layout::Layout::default() let vt_chunks = layout::Layout::default()
@ -63,7 +79,7 @@ impl Layout {
Constraint::Percentage(50), Constraint::Percentage(50),
Constraint::Percentage(50), Constraint::Percentage(50),
]) ])
.split(hz_chunks[0]); .split(hz_chunks[1]);
// left block: results + input field // left block: results + input field
let left_chunks = layout::Layout::default() let left_chunks = layout::Layout::default()
@ -78,7 +94,9 @@ impl Layout {
.split(vt_chunks[1]); .split(vt_chunks[1]);
Self::new( Self::new(
hz_chunks[1], help_bar_chunks[0],
help_bar_chunks[1],
help_bar_chunks[2],
left_chunks[0], left_chunks[0],
left_chunks[1], left_chunks[1],
Some(right_chunks[0]), Some(right_chunks[0]),
@ -89,9 +107,17 @@ impl Layout {
let chunks = layout::Layout::default() let chunks = layout::Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints([Constraint::Min(10), Constraint::Length(3)]) .constraints([Constraint::Min(10), Constraint::Length(3)])
.split(hz_chunks[0]); .split(hz_chunks[1]);
Self::new(hz_chunks[1], chunks[0], chunks[1], None, None) Self::new(
help_bar_chunks[0],
help_bar_chunks[1],
help_bar_chunks[2],
chunks[0],
chunks[1],
None,
None,
)
} }
} }
} }

View File

@ -0,0 +1,26 @@
use ratatui::widgets::Paragraph;
//const LOGO: &str = r" _______________
// __ __ _ _ |,----------. |\
// / /____ / /__ _ __(_)__ (_)__ ___ || |=| |
// / __/ -_) / -_) |/ / (_-</ / _ \/ _ \ || | | |
// \__/\__/_/\__/|___/_/___/_/\___/_//_/ || |o| |
// |`-----------' |/
// `--------------'";
const LOGO: &str = r" _______________
|,----------. |\
|| |=| |
|| | | |
|| |o| |
|`-----------' |/
`--------------'";
pub fn build_logo_paragraph<'a>() -> Paragraph<'a> {
let lines = LOGO
.lines()
.map(std::convert::Into::into)
.collect::<Vec<_>>();
let logo_paragraph = Paragraph::new(lines);
logo_paragraph
}

View File

@ -0,0 +1,113 @@
use ratatui::{
layout::Constraint,
style::{Color, Style},
text::Span,
widgets::{Cell, Row, Table},
};
use crate::television::Television;
// television 0.1.6
// target triple: aarch64-apple-darwin
// build: 1.82.0 (2024-10-24)
// current_channel: git_repos
// current_mode: channel
impl Television {
pub fn build_metadata_table<'a>(&self) -> Table<'a> {
let version_row = Row::new(vec![
Cell::from(Span::styled(
"version: ",
Style::default().fg(Color::DarkGray),
)),
Cell::from(Span::styled(
env!("CARGO_PKG_VERSION"),
Style::default().fg(Color::LightYellow),
)),
]);
let target_triple_row = Row::new(vec![
Cell::from(Span::styled(
"target triple: ",
Style::default().fg(Color::DarkGray),
)),
Cell::from(Span::styled(
env!("VERGEN_CARGO_TARGET_TRIPLE"),
Style::default().fg(Color::LightYellow),
)),
]);
let build_row = Row::new(vec![
Cell::from(Span::styled(
"build: ",
Style::default().fg(Color::DarkGray),
)),
Cell::from(Span::styled(
env!("VERGEN_RUSTC_SEMVER"),
Style::default().fg(Color::LightYellow),
)),
Cell::from(Span::styled(
" (",
Style::default().fg(Color::DarkGray),
)),
Cell::from(Span::styled(
env!("VERGEN_BUILD_DATE"),
Style::default().fg(Color::LightYellow),
)),
Cell::from(Span::styled(
")",
Style::default().fg(Color::DarkGray),
)),
]);
let current_dir_row = Row::new(vec![
Cell::from(Span::styled(
"current directory: ",
Style::default().fg(Color::DarkGray),
)),
Cell::from(Span::styled(
std::env::current_dir()
.expect("Could not get current directory")
.display()
.to_string(),
Style::default().fg(Color::LightYellow),
)),
]);
let current_channel_row = Row::new(vec![
Cell::from(Span::styled(
"current channel: ",
Style::default().fg(Color::DarkGray),
)),
Cell::from(Span::styled(
self.current_channel().to_string(),
Style::default().fg(Color::LightYellow),
)),
]);
let current_mode_row = Row::new(vec![
Cell::from(Span::styled(
"current mode: ",
Style::default().fg(Color::DarkGray),
)),
Cell::from(Span::styled(
self.mode.to_string(),
Style::default().fg(Color::LightYellow),
)),
]);
let widths = vec![Constraint::Fill(1), Constraint::Fill(2)];
Table::new(
vec![
version_row,
target_triple_row,
build_row,
current_dir_row,
current_channel_row,
current_mode_row,
],
widths,
)
}
}

View File

@ -224,7 +224,7 @@ fn impl_unit_channel(ast: &syn::DeriveInput) -> TokenStream {
// Generate a unit enum from the given enum // Generate a unit enum from the given enum
let unit_enum = quote! { let unit_enum = quote! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Display)]
pub enum UnitChannel { pub enum UnitChannel {
#( #(
#variant_names, #variant_names,