Skip to content

Commit

Permalink
feat: auto-update the themes file when the selected theme is unknown,…
Browse files Browse the repository at this point in the history
… added new theme solarized-dark-higher-contrast
  • Loading branch information
Mcdostone committed Jan 25, 2025
1 parent 313e232 commit c9919c3
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 61 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- run: git fetch --tags origin
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
Expand All @@ -86,6 +84,8 @@ jobs:
git add CHANGELOG.md
git commit -m "chore: Update changelog"
git push origin "changelog/v${{ needs.version.outputs.version }}" --force
- name: Check out repository
uses: actions/checkout@v4
- name: Create pull request for changelog
run: |
git pull
Expand Down
25 changes: 23 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 1 addition & 43 deletions crates/command/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
//! The command line argument Parser struct
use crate::command::{Command, MainCommand, UtilityCommands};
use crate::theme::init_themes_file;
use app::configuration::{ClusterConfig, GlobalConfig, SchemaRegistryConfig, YozefuConfig};
use app::search::filter::FILTERS_DIR;
use app::APPLICATION_NAME;
use clap::command;
use lib::Error;
use log::warn;
use reqwest::Url;
use std::fmt::Debug;
use std::fs;
use std::{fmt::Display, path::PathBuf, str::FromStr};
use tui::error::TuiError;
use tui::Theme;

pub use clap::Parser;
use indexmap::IndexMap;
Expand Down Expand Up @@ -153,47 +152,6 @@ fn init_config_file() -> Result<PathBuf, Error> {
Ok(path)
}

/// Initializes a default configuration file if it does not exist.
/// The default cluster is `localhost`.
async fn init_themes_file() -> Result<PathBuf, Error> {
let path = GlobalConfig::path()?;
let config = GlobalConfig::read(&path)?;
let path = config.themes_file();
if fs::metadata(&path).is_ok() {
return Ok(path);
}

let default_theme = Theme::light();
let mut default_themes = IndexMap::new();
default_themes.insert(default_theme.name.clone(), default_theme);

let content = match reqwest::get(
"https://raw.githubusercontent.com/MAIF/yozefu/refs/heads/main/crates/command/themes.json",
)
.await
{
Ok(response) => match response.status().is_success() {
true => response.text().await.unwrap(),
false => {
warn!("HTTP {} when downloading theme file", response.status());
serde_json::to_string_pretty(&default_themes).unwrap()
}
},
Err(e) => {
warn!("Error while downloading theme file: {}", e);
serde_json::to_string_pretty(&default_themes).unwrap()
}
};

let e: IndexMap<String, Theme> = match serde_json::from_str(&content) {
Ok(themes) => themes,
Err(_) => default_themes,
};

fs::write(&path, &serde_json::to_string_pretty(&e)?)?;
Ok(path)
}

#[test]
pub fn test_conflicts() {
use clap::CommandFactory;
Expand Down
7 changes: 5 additions & 2 deletions crates/command/src/command/configure/get_command.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Command to fetch a property of the configuration file.
use std::{collections::HashMap, fs};

use crate::command::Command as CliCommand;
use crate::{command::Command as CliCommand, theme::update_themes};
use app::configuration::GlobalConfig;
use clap::Args;
use lib::Error;
Expand Down Expand Up @@ -57,7 +57,10 @@ impl CliCommand for ConfigureGetCommand {
println!("{:?}", file)
}
"directory" | "dir" => println!("{:?}", file.parent().unwrap()),
"themes" => println!("{}", serde_json::to_string_pretty(&config.themes())?),
"themes" => {
let _ = update_themes().await;
println!("{}", serde_json::to_string_pretty(&config.themes())?)
}
"theme-file" | "themes-file" | "themes_file" | "theme_file" => {
println!("{:?}", config.themes_file())
}
Expand Down
21 changes: 14 additions & 7 deletions crates/command/src/command/main_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::headless::formatter::{
};
use crate::headless::Headless;
use crate::log::{init_logging_file, init_logging_stderr};
use crate::theme::update_themes;
use crate::APPLICATION_NAME;

fn parse_cluster<T>(s: &str) -> Result<T, Error>
Expand Down Expand Up @@ -184,16 +185,24 @@ where
Ok(themes)
}

fn load_theme(file: &Path, name: &str) -> Result<Theme, Error> {
let themes = Self::themes(file)?;
async fn load_theme(file: &Path, name: &str) -> Result<Theme, Error> {
let mut themes = Self::themes(file)?;

if !themes.contains_key(name) {
info!("Theme '{}' not found. About to update theme file.", name);
let _ = update_themes().await;
themes = Self::themes(file)?;
}

let theme = match themes.get(name) {
Some(theme) => theme,
None => {
update_themes().await?;
warn!("Theme '{}' not found. Available themes are [{}]. Make sure it is defined in '{}'",

name,
themes.keys().join(", "),
file.display());

let theme = themes.iter().next().unwrap().1;
info!("Since the theme was not found, I'm going to use the first available theme '{}'", theme.name);
theme
Expand All @@ -208,12 +217,10 @@ where
let config = self.config(yozefu_config)?;
let query = self.query(&config)?;

let _ = init_logging_file(self.debug, &config.logs_file());
let theme_name = self.theme.clone().unwrap_or(config.theme.clone());
let color_palette = Self::load_theme(&config.themes_file(), &theme_name)?;

let color_palette = Self::load_theme(&config.themes_file(), &theme_name).await?;
let state = State::new(&cluster.to_string(), color_palette, &config);

let _ = init_logging_file(self.debug, &config.logs_file());
let mut ui = Ui::new(
self.app(&query, yozefu_config)?,
query,
Expand Down
1 change: 1 addition & 0 deletions crates/command/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod cli;
mod command;
mod headless;
mod log;
mod theme;
use app::configuration::GlobalConfig;
pub use clap::Parser;
pub use cli::Cli;
Expand Down
101 changes: 101 additions & 0 deletions crates/command/src/theme.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::{fs, path::PathBuf};

use app::configuration::GlobalConfig;
use indexmap::IndexMap;
use lib::Error;
use log::{info, warn};
use tui::Theme;

const THEMES_URL: &str =
"https://raw.githubusercontent.com/MAIF/yozefu/refs/heads/main/crates/command/themes.json";

/// Initializes a default configuration file if it does not exist.
/// The default cluster is `localhost`.
pub(crate) async fn init_themes_file() -> Result<PathBuf, Error> {
let path = GlobalConfig::path()?;
let config = GlobalConfig::read(&path)?;
let path = config.themes_file();
if fs::metadata(&path).is_ok() {
return Ok(path);
}

let default_theme = Theme::light();
let mut default_themes = IndexMap::new();
default_themes.insert(default_theme.name.clone(), default_theme);

let content = match reqwest::get(
"https://raw.githubusercontent.com/MAIF/yozefu/refs/heads/main/crates/command/themes.json",
)
.await
{
Ok(response) => match response.status().is_success() {
true => response.text().await.unwrap(),
false => {
warn!("HTTP {} when downloading theme file", response.status());
serde_json::to_string_pretty(&default_themes).unwrap()
}
},
Err(e) => {
warn!("Error while downloading theme file: {}", e);
serde_json::to_string_pretty(&default_themes).unwrap()
}
};

let e: IndexMap<String, Theme> = match serde_json::from_str(&content) {
Ok(themes) => themes,
Err(_) => default_themes,
};

fs::write(&path, &serde_json::to_string_pretty(&e)?)?;
Ok(path)
}

/// Update the themes file with the latest themes from the repository.
pub(crate) async fn update_themes() -> Result<PathBuf, Error> {
let path = GlobalConfig::path()?;
let config = GlobalConfig::read(&path)?;
let path = config.themes_file();
if fs::metadata(&path).is_err() {
return init_themes_file().await;
}

let content = fs::read_to_string(&path)?;
let mut local_themes: IndexMap<String, Theme> = serde_json::from_str(&content)?;

info!("Updating themes file from {}", THEMES_URL);
let content = match reqwest::get(THEMES_URL).await {
Ok(response) => match response.status().is_success() {
true => response.text().await.unwrap(),
false => {
warn!("HTTP {} when downloading theme file", response.status());
"{}".to_string()
}
},
Err(e) => {
warn!("Error while downloading theme file: {}", e);
"{}".to_string()
}
};

let new_themes = serde_json::from_str::<IndexMap<String, Theme>>(&content)?;

for (name, theme) in new_themes {
if !local_themes.contains_key(&name) {
info!("Theme '{}' added", name);
local_themes.insert(name, theme);
}
}

fs::write(&path, &serde_json::to_string_pretty(&local_themes)?)?;
Ok(path)
}

#[test]
fn test_valid_themes() {
use std::collections::HashMap;
use tui::Theme;

let content = include_str!("../themes.json");
let themes: HashMap<String, Theme> = serde_json::from_str(content).unwrap();
assert!(themes.keys().len() >= 3)
}
25 changes: 25 additions & 0 deletions crates/command/themes.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,30 @@
"fg_active": "DarkGray",
"dialog_border": "Yellow",
"autocomplete": "#646464"
},
"solarized-dark-higher-contrast": {
"name": "solarized-dark-higher-contrast",
"fg": "Black",
"bg": "Black",
"black": "Black",
"red": "Red",
"green": "Green",
"yellow": "Yellow",
"blue": "Blue",
"magenta": "Magenta",
"cyan": "Cyan",
"white": "White",
"orange": "LightRed",
"focused_border": "Blue",
"bg_focused_selected": "White",
"fg_focused_selected": "DarkGray",
"bg_unfocused_selected": "0",
"fg_unfocused_selected": "White",
"bg_disabled": "Green",
"fg_disabled": "Black",
"bg_active": "LightGreen",
"fg_active": "Black",
"dialog_border": "Yellow",
"autocomplete": "#646464"
}
}
2 changes: 1 addition & 1 deletion crates/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ reqwest = { version = "0.12.12", features = ["json"] }


[dev-dependencies]
insta = { version = "1.42.0", features = ["filters", "glob"] }
insta = { version = "1.42.1", features = ["filters", "glob"] }
protobuf = "3.7.1"
tokio = { version = "1.43.0", features = ["rt"] }

Expand Down
6 changes: 2 additions & 4 deletions crates/tui/src/component/help_component.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Component showing the help
use crossterm::event::{KeyCode, KeyEvent};
use itertools::Itertools;
use ratatui::{
layout::Rect,
style::Stylize,
Expand Down Expand Up @@ -113,9 +112,8 @@ impl Component for HelpComponent {
Line::from(vec![
Span::from(" Theme").bold(),
Span::from(format!(
" Theme is '{}'. You can switch between [{}] in the config file or with the '--theme' flag",
state.theme.name,
state.themes.iter().filter(|f| *f != &state.theme.name).join(", ")
" Theme is '{}'. run `yozf config get themes` to list available themes.",
state.theme.name
))
]),
Line::from(vec![
Expand Down

0 comments on commit c9919c3

Please sign in to comment.