mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-08 04:25:23 +00:00
some work on the configuration file
This commit is contained in:
parent
6d48c87526
commit
4302b6189a
@ -1,3 +1,18 @@
|
|||||||
|
# Television configuration file
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Ui settings
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
[ui]
|
||||||
|
# Whether to use nerd font icons in the UI
|
||||||
|
use_nerd_font_icons = false
|
||||||
|
# How much space to allocate for the UI (in percentage of the screen)
|
||||||
|
ui_scale = 80
|
||||||
|
|
||||||
|
# Keybindings
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Channel mode keybindings
|
||||||
[keybindings.Channel]
|
[keybindings.Channel]
|
||||||
esc = "Quit"
|
esc = "Quit"
|
||||||
down = "SelectNextEntry"
|
down = "SelectNextEntry"
|
||||||
@ -11,6 +26,7 @@ ctrl-y = "CopyEntryToClipboard"
|
|||||||
ctrl-r = "ToggleRemoteControl"
|
ctrl-r = "ToggleRemoteControl"
|
||||||
ctrl-s = "ToggleSendToChannel"
|
ctrl-s = "ToggleSendToChannel"
|
||||||
|
|
||||||
|
# Remote control mode keybindings
|
||||||
[keybindings.RemoteControl]
|
[keybindings.RemoteControl]
|
||||||
esc = "Quit"
|
esc = "Quit"
|
||||||
down = "SelectNextEntry"
|
down = "SelectNextEntry"
|
||||||
@ -20,6 +36,7 @@ ctrl-p = "SelectPrevEntry"
|
|||||||
enter = "SelectEntry"
|
enter = "SelectEntry"
|
||||||
ctrl-r = "ToggleRemoteControl"
|
ctrl-r = "ToggleRemoteControl"
|
||||||
|
|
||||||
|
# Send to channel mode keybindings
|
||||||
[keybindings.SendToChannel]
|
[keybindings.SendToChannel]
|
||||||
esc = "Quit"
|
esc = "Quit"
|
||||||
down = "SelectNextEntry"
|
down = "SelectNextEntry"
|
||||||
|
29
.github/workflows/ci.yml
vendored
29
.github/workflows/ci.yml
vendored
@ -49,27 +49,12 @@ jobs:
|
|||||||
run: cargo clippy --all-targets --all-features --workspace -- -D warnings
|
run: cargo clippy --all-targets --all-features --workspace -- -D warnings
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
name: Docs
|
name: Documentation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
RUSTDOCFLAGS: -Dwarnings
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: dtolnay/rust-toolchain@nightly
|
||||||
- name: Install Rust toolchain
|
- uses: dtolnay/install@cargo-docs-rs
|
||||||
uses: dtolnay/rust-toolchain@nightly
|
- run: cargo docs-rs
|
||||||
- name: Configure cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
- name: Setup pages
|
|
||||||
id: pages
|
|
||||||
uses: actions/configure-pages@v4
|
|
||||||
- name: Clean docs folder
|
|
||||||
run: cargo clean --doc
|
|
||||||
- name: Build docs
|
|
||||||
run: cargo doc --no-deps
|
|
||||||
- name: Add redirect
|
|
||||||
run: echo '<meta http-equiv="refresh" content="0;url=tv/index.html">' > target/doc/index.html
|
|
||||||
- name: Remove lock file
|
|
||||||
run: rm target/doc/.lock
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-pages-artifact@v3
|
|
||||||
with:
|
|
||||||
path: target/doc
|
|
||||||
|
4
TODO.md
4
TODO.md
@ -6,8 +6,8 @@
|
|||||||
# tasks
|
# tasks
|
||||||
|
|
||||||
- [x] preview navigation
|
- [x] preview navigation
|
||||||
- [x] add a way to open the selected file in the default editor (or maybe that
|
- [ ] add a way to open the selected file in the default editor (or maybe that
|
||||||
should be achieved using pipes?) --> use xargs for that
|
should be achieved using pipes?) --> xargs
|
||||||
- [x] maybe filter out image types etc. for now
|
- [x] maybe filter out image types etc. for now
|
||||||
- [x] return selected entry on exit
|
- [x] return selected entry on exit
|
||||||
- [x] piping output to another command
|
- [x] piping output to another command
|
||||||
|
@ -7,7 +7,7 @@ use directories::ProjectDirs;
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use ratatui::style::{Color, Modifier, Style};
|
use ratatui::style::{Color, Modifier, Style};
|
||||||
use serde::{de::Deserializer, Deserialize};
|
use serde::{de::Deserializer, Deserialize};
|
||||||
use tracing::{error, info};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::Action,
|
action::Action,
|
||||||
@ -26,6 +26,23 @@ pub struct AppConfig {
|
|||||||
pub config_dir: PathBuf,
|
pub config_dir: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_UI_SCALE: u16 = 90;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
pub struct UiConfig {
|
||||||
|
pub use_nerd_font_icons: bool,
|
||||||
|
pub ui_scale: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for UiConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
use_nerd_font_icons: false,
|
||||||
|
ui_scale: DEFAULT_UI_SCALE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Clone, Debug, Default, Deserialize)]
|
#[derive(Clone, Debug, Default, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
@ -36,6 +53,7 @@ pub struct Config {
|
|||||||
pub keybindings: KeyBindings,
|
pub keybindings: KeyBindings,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub styles: Styles,
|
pub styles: Styles,
|
||||||
|
pub ui: UiConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -51,34 +69,32 @@ lazy_static! {
|
|||||||
.map(PathBuf::from);
|
.map(PathBuf::from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CONFIG_FILE_NAME: &str = "config.toml";
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new() -> Result<Self, config::ConfigError> {
|
pub fn new() -> Result<Self, config::ConfigError> {
|
||||||
let default_config: Config = toml::from_str(CONFIG).unwrap();
|
let default_config: Config =
|
||||||
|
toml::from_str(CONFIG).expect("default config");
|
||||||
|
|
||||||
let data_dir = get_data_dir();
|
let data_dir = get_data_dir();
|
||||||
let config_dir = get_config_dir();
|
let config_dir = get_config_dir();
|
||||||
let mut builder = config::Config::builder()
|
let mut builder = config::Config::builder()
|
||||||
.set_default("data_dir", data_dir.to_str().unwrap())?
|
.set_default("data_dir", data_dir.to_str().unwrap())?
|
||||||
.set_default("config_dir", config_dir.to_str().unwrap())?;
|
.set_default("config_dir", config_dir.to_str().unwrap())?;
|
||||||
|
|
||||||
let config_files = [
|
// Load the default_config values as base defaults
|
||||||
("config.json5", config::FileFormat::Json5),
|
builder = builder.add_source(config::File::from_str(
|
||||||
("config.json", config::FileFormat::Json),
|
CONFIG,
|
||||||
("config.yaml", config::FileFormat::Yaml),
|
config::FileFormat::Toml,
|
||||||
("config.toml", config::FileFormat::Toml),
|
));
|
||||||
("config.ini", config::FileFormat::Ini),
|
|
||||||
];
|
let source = config::File::from(config_dir.join(CONFIG_FILE_NAME))
|
||||||
let mut found_config = false;
|
.format(config::FileFormat::Toml)
|
||||||
for (file, format) in &config_files {
|
|
||||||
let source = config::File::from(config_dir.join(file))
|
|
||||||
.format(*format)
|
|
||||||
.required(false);
|
.required(false);
|
||||||
builder = builder.add_source(source);
|
builder = builder.add_source(source);
|
||||||
if config_dir.join(file).exists() {
|
|
||||||
found_config = true;
|
if !config_dir.join(CONFIG_FILE_NAME).is_file() {
|
||||||
}
|
warn!("No config file found at {:?}", config_dir);
|
||||||
}
|
|
||||||
if !found_config {
|
|
||||||
error!("No configuration file found. Application may not behave as expected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cfg: Self = builder.build()?.try_deserialize()?;
|
let mut cfg: Self = builder.build()?.try_deserialize()?;
|
||||||
|
@ -370,7 +370,7 @@ impl Television {
|
|||||||
/// * `Result<()>` - An Ok result or an error.
|
/// * `Result<()>` - An Ok result or an error.
|
||||||
pub fn draw(&mut self, f: &mut Frame, area: Rect) -> Result<()> {
|
pub fn draw(&mut self, f: &mut Frame, area: Rect) -> Result<()> {
|
||||||
let layout = Layout::build(
|
let layout = Layout::build(
|
||||||
&Dimensions::default(),
|
&Dimensions::from(self.config.ui.ui_scale),
|
||||||
area,
|
area,
|
||||||
!matches!(self.mode, Mode::Channel),
|
!matches!(self.mode, Mode::Channel),
|
||||||
);
|
);
|
||||||
|
@ -12,6 +12,12 @@ impl Dimensions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<u16> for Dimensions {
|
||||||
|
fn from(x: u16) -> Self {
|
||||||
|
Self::new(x, x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Dimensions {
|
impl Default for Dimensions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(UI_WIDTH_PERCENT, UI_HEIGHT_PERCENT)
|
Self::new(UI_WIDTH_PERCENT, UI_HEIGHT_PERCENT)
|
||||||
|
@ -31,12 +31,12 @@ impl Television {
|
|||||||
preview: &Arc<Preview>,
|
preview: &Arc<Preview>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut preview_title_spans = Vec::new();
|
let mut preview_title_spans = Vec::new();
|
||||||
if let Some(icon) = &selected_entry.icon {
|
if selected_entry.icon.is_some() && self.config.ui.use_nerd_font_icons
|
||||||
|
{
|
||||||
|
let icon = selected_entry.icon.as_ref().unwrap();
|
||||||
preview_title_spans.push(Span::styled(
|
preview_title_spans.push(Span::styled(
|
||||||
{
|
{
|
||||||
// FIXME: this should be done using padding on the parent block
|
let mut icon_str = String::from(icon.icon);
|
||||||
let mut icon_str = String::from(" ");
|
|
||||||
icon_str.push(icon.icon);
|
|
||||||
icon_str.push(' ');
|
icon_str.push(' ');
|
||||||
icon_str
|
icon_str
|
||||||
},
|
},
|
||||||
@ -53,6 +53,7 @@ impl Television {
|
|||||||
let preview_title = Paragraph::new(Line::from(preview_title_spans))
|
let preview_title = Paragraph::new(Line::from(preview_title_spans))
|
||||||
.block(
|
.block(
|
||||||
Block::default()
|
Block::default()
|
||||||
|
.padding(Padding::horizontal(1))
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.border_type(BorderType::Rounded)
|
.border_type(BorderType::Rounded)
|
||||||
.border_style(Style::default().fg(BORDER_COLOR)),
|
.border_style(Style::default().fg(BORDER_COLOR)),
|
||||||
|
@ -64,6 +64,7 @@ impl Television {
|
|||||||
ResultsListColors::default()
|
ResultsListColors::default()
|
||||||
.result_name_fg(mode_color(self.mode)),
|
.result_name_fg(mode_color(self.mode)),
|
||||||
),
|
),
|
||||||
|
self.config.ui.use_nerd_font_icons,
|
||||||
);
|
);
|
||||||
|
|
||||||
f.render_stateful_widget(
|
f.render_stateful_widget(
|
||||||
|
@ -65,6 +65,7 @@ pub fn build_results_list<'a, 'b>(
|
|||||||
entries: &'a [Entry],
|
entries: &'a [Entry],
|
||||||
list_direction: ListDirection,
|
list_direction: ListDirection,
|
||||||
results_list_colors: Option<ResultsListColors>,
|
results_list_colors: Option<ResultsListColors>,
|
||||||
|
use_icons: bool,
|
||||||
) -> List<'a>
|
) -> List<'a>
|
||||||
where
|
where
|
||||||
'b: 'a,
|
'b: 'a,
|
||||||
@ -73,7 +74,8 @@ where
|
|||||||
List::new(entries.iter().map(|entry| {
|
List::new(entries.iter().map(|entry| {
|
||||||
let mut spans = Vec::new();
|
let mut spans = Vec::new();
|
||||||
// optional icon
|
// optional icon
|
||||||
if let Some(icon) = &entry.icon {
|
if entry.icon.is_some() && use_icons {
|
||||||
|
let icon = entry.icon.as_ref().unwrap();
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
icon.to_string(),
|
icon.to_string(),
|
||||||
Style::default().fg(Color::from_str(icon.color).unwrap()),
|
Style::default().fg(Color::from_str(icon.color).unwrap()),
|
||||||
@ -200,6 +202,7 @@ impl Television {
|
|||||||
&entries,
|
&entries,
|
||||||
ListDirection::BottomToTop,
|
ListDirection::BottomToTop,
|
||||||
None,
|
None,
|
||||||
|
self.config.ui.use_nerd_font_icons,
|
||||||
);
|
);
|
||||||
|
|
||||||
f.render_stateful_widget(
|
f.render_stateful_widget(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user