diff --git a/Cargo.lock b/Cargo.lock index 5728a45..fbfce7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1031,7 +1031,6 @@ dependencies = [ "i18n-embed", "i18n-embed-fl", "ignore", - "lazy_static", "lexical-sort", "libcosmic", "log", diff --git a/Cargo.toml b/Cargo.toml index a7c72f7..ddf703b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,6 @@ license = "GPL-3.0-only" env_logger = "0.10.0" grep = "0.3.1" ignore = "0.4.21" -lazy_static = "1.4.0" lexical-sort = "0.3.1" log = "0.4.20" patch = "0.7.0" diff --git a/src/localize.rs b/src/localize.rs index f5c6fb9..1aab45a 100644 --- a/src/localize.rs +++ b/src/localize.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only +use std::sync::OnceLock; + use i18n_embed::{ fluent::{fluent_language_loader, FluentLanguageLoader}, DefaultLocalizer, LanguageLoader, Localizer, @@ -10,8 +12,22 @@ use rust_embed::RustEmbed; #[folder = "i18n/"] struct Localizations; -lazy_static::lazy_static! { - pub static ref LANGUAGE_LOADER: FluentLanguageLoader = { +pub static LANGUAGE_LOADER: OnceLock = OnceLock::new(); + +#[macro_export] +macro_rules! fl { + ($message_id:literal) => {{ + i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER.get().unwrap(), $message_id) + }}; + + ($message_id:literal, $($args:expr),*) => {{ + i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER.get().unwrap(), $message_id, $($args), *) + }}; +} + +// Get the `Localizer` to be used for localizing this library. +pub fn localizer() -> Box { + LANGUAGE_LOADER.get_or_init(|| { let loader: FluentLanguageLoader = fluent_language_loader!(); loader @@ -19,23 +35,12 @@ lazy_static::lazy_static! { .expect("Error while loading fallback language"); loader - }; -} + }); -#[macro_export] -macro_rules! fl { - ($message_id:literal) => {{ - i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id) - }}; - - ($message_id:literal, $($args:expr),*) => {{ - i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id, $($args), *) - }}; -} - -// Get the `Localizer` to be used for localizing this library. -pub fn localizer() -> Box { - Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations)) + Box::from(DefaultLocalizer::new( + LANGUAGE_LOADER.get().unwrap(), + &Localizations, + )) } pub fn localize() { diff --git a/src/main.rs b/src/main.rs index ad928d3..1cb1680 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,7 +23,7 @@ use std::{ env, fs, io, path::{Path, PathBuf}, process, - sync::Mutex, + sync::{Mutex, OnceLock}, }; use tokio::time; @@ -60,17 +60,28 @@ use self::text_box::text_box; mod text_box; //TODO: re-use iced FONT_SYSTEM -lazy_static::lazy_static! { - static ref FONT_SYSTEM: Mutex = Mutex::new(FontSystem::new()); - static ref ICON_CACHE: Mutex = Mutex::new(IconCache::new()); - static ref LINE_NUMBER_CACHE: Mutex = Mutex::new(LineNumberCache::new()); - static ref SWASH_CACHE: Mutex = Mutex::new(SwashCache::new()); - static ref SYNTAX_SYSTEM: SyntaxSystem = { +static FONT_SYSTEM: OnceLock> = OnceLock::new(); +static ICON_CACHE: OnceLock> = OnceLock::new(); +static LINE_NUMBER_CACHE: OnceLock> = OnceLock::new(); +static SWASH_CACHE: OnceLock> = OnceLock::new(); +static SYNTAX_SYSTEM: OnceLock = OnceLock::new(); + +pub fn icon_cache_get(name: &'static str, size: u16) -> icon::Icon { + let mut icon_cache = ICON_CACHE.get().unwrap().lock().unwrap(); + icon_cache.get(name, size) +} + +fn main() -> Result<(), Box> { + FONT_SYSTEM.get_or_init(|| Mutex::new(FontSystem::new())); + ICON_CACHE.get_or_init(|| Mutex::new(IconCache::new())); + LINE_NUMBER_CACHE.get_or_init(|| Mutex::new(LineNumberCache::new())); + SWASH_CACHE.get_or_init(|| Mutex::new(SwashCache::new())); + SYNTAX_SYSTEM.get_or_init(|| { let lazy_theme_set = two_face::theme::LazyThemeSet::from(two_face::theme::extra()); let mut theme_set = syntect::highlighting::ThemeSet::from(&lazy_theme_set); for (theme_name, theme_data) in &[ ("COSMIC Dark", cosmic_syntax_theme::COSMIC_DARK_TM_THEME), - ("COSMIC Light", cosmic_syntax_theme::COSMIC_LIGHT_TM_THEME) + ("COSMIC Light", cosmic_syntax_theme::COSMIC_LIGHT_TM_THEME), ] { let mut cursor = io::Cursor::new(theme_data); match syntect::highlighting::ThemeSet::load_from_reader(&mut cursor) { @@ -87,15 +98,8 @@ lazy_static::lazy_static! { syntax_set: two_face::syntax::extra_no_newlines(), theme_set, } - }; -} + }); -pub fn icon_cache_get(name: &'static str, size: u16) -> icon::Icon { - let mut icon_cache = ICON_CACHE.lock().unwrap(); - icon_cache.get(name, size) -} - -fn main() -> Result<(), Box> { #[cfg(all(unix, not(target_os = "redox")))] match fork::daemon(true, true) { Ok(fork::Fork::Child) => (), @@ -829,7 +833,7 @@ impl App { .iter() .position(|theme_name| theme_name == &self.config.syntax_theme_light); let font_selected = { - let font_system = FONT_SYSTEM.lock().unwrap(); + let font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); let current_font_name = font_system.db().family_name(&Family::Monospace); self.font_names .iter() @@ -920,7 +924,7 @@ impl Application for App { fn init(core: Core, flags: Self::Flags) -> (Self, Command) { // Update font name from config { - let mut font_system = FONT_SYSTEM.lock().unwrap(); + let mut font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); font_system .db_mut() .set_monospace_family(&flags.config.font_name); @@ -930,7 +934,7 @@ impl Application for App { let font_names = { let mut font_names = Vec::new(); - let font_system = FONT_SYSTEM.lock().unwrap(); + let font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); //TODO: do not repeat, used in Tab::new let attrs = cosmic_text::Attrs::new().family(Family::Monospace); for face in font_system.db().faces() { @@ -954,8 +958,9 @@ impl Application for App { font_sizes.push(font_size); } - let mut theme_names = Vec::with_capacity(SYNTAX_SYSTEM.theme_set.themes.len()); - for (theme_name, _theme) in SYNTAX_SYSTEM.theme_set.themes.iter() { + let mut theme_names = + Vec::with_capacity(SYNTAX_SYSTEM.get().unwrap().theme_set.themes.len()); + for (theme_name, _theme) in SYNTAX_SYSTEM.get().unwrap().theme_set.themes.iter() { theme_names.push(theme_name.to_string()); } @@ -1172,13 +1177,14 @@ impl Application for App { if font_name != &self.config.font_name { // Update font name from config { - let mut font_system = FONT_SYSTEM.lock().unwrap(); + let mut font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); font_system.db_mut().set_monospace_family(font_name); } // Reset line number cache { - let mut line_number_cache = LINE_NUMBER_CACHE.lock().unwrap(); + let mut line_number_cache = + LINE_NUMBER_CACHE.get().unwrap().lock().unwrap(); line_number_cache.clear(); } diff --git a/src/mime_icon.rs b/src/mime_icon.rs index 40fca06..9317624 100644 --- a/src/mime_icon.rs +++ b/src/mime_icon.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only use cosmic::widget::icon; -use std::{collections::HashMap, path::Path, sync::Mutex}; +use std::{collections::HashMap, path::Path, sync::Mutex, sync::OnceLock}; pub const FALLBACK_MIME_ICON: &str = "text-x-generic"; @@ -39,18 +39,18 @@ impl MimeIconCache { } } -lazy_static::lazy_static! { - static ref MIME_ICON_CACHE: Mutex = Mutex::new(MimeIconCache::new()); -} +static MIME_ICON_CACHE: OnceLock> = OnceLock::new(); pub fn mime_icon>(path: P, size: u16) -> icon::Icon { + MIME_ICON_CACHE.get_or_init(|| Mutex::new(MimeIconCache::new())); + //TODO: smarter path handling let path = path .as_ref() .to_str() .expect("failed to convert path to UTF-8") .to_owned(); - let mut mime_icon_cache = MIME_ICON_CACHE.lock().unwrap(); + let mut mime_icon_cache = MIME_ICON_CACHE.get().unwrap().lock().unwrap(); match mime_icon_cache.get(MimeIconKey { path, size }) { Some(handle) => icon::icon(handle).size(size), None => icon::from_name(FALLBACK_MIME_ICON).size(size).icon(), diff --git a/src/tab.rs b/src/tab.rs index 62f77f4..41e49cd 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -47,14 +47,18 @@ impl EditorTab { let mut buffer = Buffer::new_empty(config.metrics()); buffer.set_text( - &mut FONT_SYSTEM.lock().unwrap(), + &mut FONT_SYSTEM.get().unwrap().lock().unwrap(), "", attrs, Shaping::Advanced, ); - let editor = - SyntaxEditor::new(Arc::new(buffer), &SYNTAX_SYSTEM, config.syntax_theme()).unwrap(); + let editor = SyntaxEditor::new( + Arc::new(buffer), + SYNTAX_SYSTEM.get().unwrap(), + config.syntax_theme(), + ) + .unwrap(); let mut tab = Self { path_opt: None, @@ -71,7 +75,7 @@ impl EditorTab { pub fn set_config(&mut self, config: &Config) { let mut editor = self.editor.lock().unwrap(); - let mut font_system = FONT_SYSTEM.lock().unwrap(); + let mut font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); let mut editor = editor.borrow_with(&mut font_system); editor.set_auto_indent(config.auto_indent); editor.set_passthrough(!config.vim_bindings); @@ -89,7 +93,7 @@ impl EditorTab { pub fn open(&mut self, path: PathBuf) { let mut editor = self.editor.lock().unwrap(); - let mut font_system = FONT_SYSTEM.lock().unwrap(); + let mut font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); let mut editor = editor.borrow_with(&mut font_system); match editor.load_text(&path, self.attrs) { Ok(()) => { @@ -111,7 +115,7 @@ impl EditorTab { pub fn reload(&mut self) { let mut editor = self.editor.lock().unwrap(); - let mut font_system = FONT_SYSTEM.lock().unwrap(); + let mut font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); let mut editor = editor.borrow_with(&mut font_system); if let Some(path) = &self.path_opt { // Save scroll diff --git a/src/text_box.rs b/src/text_box.rs index a7fa577..6affe9e 100644 --- a/src/text_box.rs +++ b/src/text_box.rs @@ -246,7 +246,7 @@ where let mut editor = self.editor.lock().unwrap(); //TODO: set size? editor - .borrow_with(&mut FONT_SYSTEM.lock().unwrap()) + .borrow_with(&mut FONT_SYSTEM.get().unwrap().lock().unwrap()) .shape_as_needed(true); editor.with_buffer(|buffer| { @@ -348,7 +348,7 @@ where let image_w = image_w - scrollbar_w; // Lock font system (used throughout) - let mut font_system = FONT_SYSTEM.lock().unwrap(); + let mut font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); // Calculate line number information let (line_number_chars, editor_offset_x) = if self.line_numbers { @@ -363,7 +363,7 @@ where // Calculate line number width let mut line_number_width = 0.0; { - let mut line_number_cache = LINE_NUMBER_CACHE.lock().unwrap(); + let mut line_number_cache = LINE_NUMBER_CACHE.get().unwrap().lock().unwrap(); if let Some(layout_line) = line_number_cache .get( &mut font_system, @@ -410,7 +410,7 @@ where // Draw to pixel buffer let mut pixels_u8 = vec![0; image_w as usize * image_h as usize * 4]; { - let mut swash_cache = SWASH_CACHE.lock().unwrap(); + let mut swash_cache = SWASH_CACHE.get().unwrap().lock().unwrap(); let pixels = unsafe { std::slice::from_raw_parts_mut( @@ -454,7 +454,8 @@ where // Draw line numbers //TODO: move to cosmic-text? editor.with_buffer(|buffer| { - let mut line_number_cache = LINE_NUMBER_CACHE.lock().unwrap(); + let mut line_number_cache = + LINE_NUMBER_CACHE.get().unwrap().lock().unwrap(); let mut last_line_number = 0; for run in buffer.layout_runs() { let line_number = run.line_i.saturating_add(1); @@ -695,7 +696,7 @@ where let mut editor = self.editor.lock().unwrap(); let buffer_size = editor.with_buffer(|buffer| buffer.size()); let last_changed = editor.changed(); - let mut font_system = FONT_SYSTEM.lock().unwrap(); + let mut font_system = FONT_SYSTEM.get().unwrap().lock().unwrap(); let mut editor = editor.borrow_with(&mut font_system); let mut status = Status::Ignored;