diff --git a/Cargo.lock b/Cargo.lock index 6ba0658..4fc2aca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3038,6 +3038,7 @@ dependencies = [ "ignore", "lazy_static", "regex", + "rustc-hash", "serde", "strum", "television-derive", @@ -3076,6 +3077,7 @@ dependencies = [ "parking_lot", "ratatui", "regex", + "rustc-hash", "simdutf8", "smallvec", "syntect", @@ -3092,6 +3094,7 @@ version = "0.0.18" dependencies = [ "color-eyre", "ratatui", + "rustc-hash", "serde", "syntect", "television-channels", @@ -3109,6 +3112,7 @@ dependencies = [ "gag", "ignore", "lazy_static", + "rustc-hash", "syntect", "tracing", "unicode-width 0.2.0", diff --git a/benches/results_list_benchmark.rs b/benches/results_list_benchmark.rs index ec80260..c963089 100644 --- a/benches/results_list_benchmark.rs +++ b/benches/results_list_benchmark.rs @@ -4,13 +4,14 @@ use ratatui::layout::Alignment; use ratatui::prelude::{Line, Style}; use ratatui::style::Color; use ratatui::widgets::{Block, BorderType, Borders, ListDirection, Padding}; +use rustc_hash::FxHashMap; use television_channels::entry::merge_ranges; use television_channels::entry::{Entry, PreviewType}; use television_screen::colors::ResultsColorscheme; use television_screen::results::build_results_list; pub fn results_list_benchmark(c: &mut Criterion) { - let mut icon_color_cache = std::collections::HashMap::default(); + let mut icon_color_cache = FxHashMap::default(); // FIXME: there's probably a way to have this as a benchmark asset // possible as a JSON file and to load it for the benchmark using Serde // I don't know how exactly right now just having it here instead @@ -634,6 +635,7 @@ pub fn results_list_benchmark(c: &mut Criterion) { result_name_fg: Color::Indexed(222), result_preview_fg: Color::Indexed(222), result_line_number_fg: Color::Indexed(222), + result_selected_fg: Color::Indexed(222), result_selected_bg: Color::Indexed(222), match_foreground_color: Color::Indexed(222), }; @@ -651,6 +653,7 @@ pub fn results_list_benchmark(c: &mut Criterion) { .style(Style::default()) .padding(Padding::right(1)), &entries, + None, ListDirection::BottomToTop, false, &mut icon_color_cache, diff --git a/crates/television-channels/Cargo.toml b/crates/television-channels/Cargo.toml index 381e18a..1f910a2 100644 --- a/crates/television-channels/Cargo.toml +++ b/crates/television-channels/Cargo.toml @@ -25,6 +25,7 @@ color-eyre = { workspace = true } serde = { workspace = true } lazy_static = { workspace = true } toml = { workspace = true } +rustc-hash = { workspace = true } devicons = "0.6.11" ignore = "0.4.23" diff --git a/crates/television-channels/src/cable.rs b/crates/television-channels/src/cable.rs index 5a01024..3a17a47 100644 --- a/crates/television-channels/src/cable.rs +++ b/crates/television-channels/src/cable.rs @@ -1,5 +1,5 @@ +use rustc_hash::FxHashMap; use std::{ - collections::HashMap, fmt::{self, Display, Formatter}, ops::Deref, }; @@ -27,10 +27,10 @@ impl Display for CableChannelPrototype { } #[derive(Debug, serde::Deserialize, Default)] -pub struct CableChannels(pub HashMap); +pub struct CableChannels(pub FxHashMap); impl Deref for CableChannels { - type Target = HashMap; + type Target = FxHashMap; fn deref(&self) -> &Self::Target { &self.0 diff --git a/crates/television-channels/src/channels.rs b/crates/television-channels/src/channels.rs index c89f342..6071d9b 100644 --- a/crates/television-channels/src/channels.rs +++ b/crates/television-channels/src/channels.rs @@ -1,7 +1,6 @@ -use std::collections::HashSet; - use crate::entry::Entry; use color_eyre::Result; +use rustc_hash::FxHashSet; use television_derive::{Broadcast, ToCliChannel, ToUnitChannel}; mod alias; @@ -68,7 +67,7 @@ pub trait OnAir: Send { fn get_result(&self, index: u32) -> Option; /// Get the currently selected entries. - fn selected_entries(&self) -> &HashSet; + fn selected_entries(&self) -> &FxHashSet; /// Toggles selection for the entry under the cursor. fn toggle_selection(&mut self, entry: &Entry); diff --git a/crates/television-channels/src/channels/alias.rs b/crates/television-channels/src/channels/alias.rs index a50e8eb..b845fd6 100644 --- a/crates/television-channels/src/channels/alias.rs +++ b/crates/television-channels/src/channels/alias.rs @@ -4,6 +4,8 @@ use crate::channels::OnAir; use crate::entry::Entry; use crate::entry::PreviewType; use devicons::FileIcon; +use rustc_hash::FxBuildHasher; +use rustc_hash::FxHashSet; use television_fuzzy::matcher::{config::Config, injector::Injector, Matcher}; use television_utils::indices::sep_name_and_value_indices; use tracing::debug; @@ -23,7 +25,7 @@ impl Alias { pub struct Channel { matcher: Matcher, file_icon: FileIcon, - selected_entries: HashSet, + selected_entries: FxHashSet, } const NUM_THREADS: usize = 1; @@ -55,7 +57,7 @@ impl Channel { Self { matcher, file_icon: FileIcon::from(FILE_ICON_STR), - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -119,7 +121,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/cable.rs b/crates/television-channels/src/channels/cable.rs index c373f61..0c6564f 100644 --- a/crates/television-channels/src/channels/cable.rs +++ b/crates/television-channels/src/channels/cable.rs @@ -1,7 +1,9 @@ +use std::collections::HashSet; + use color_eyre::Result; use lazy_static::lazy_static; use regex::Regex; -use std::collections::HashSet; +use rustc_hash::{FxBuildHasher, FxHashSet}; use tracing::debug; use crate::cable::{CableChannelPrototype, DEFAULT_DELIMITER}; @@ -26,7 +28,7 @@ pub struct Channel { matcher: Matcher, entries_command: String, preview_kind: PreviewKind, - selected_entries: HashSet, + selected_entries: FxHashSet, } impl Default for Channel { @@ -94,7 +96,7 @@ impl Channel { entries_command: entries_command.to_string(), preview_kind, name: name.to_string(), - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -164,7 +166,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/dirs.rs b/crates/television-channels/src/channels/dirs.rs index d01e47a..bc1f34e 100644 --- a/crates/television-channels/src/channels/dirs.rs +++ b/crates/television-channels/src/channels/dirs.rs @@ -1,6 +1,7 @@ use crate::channels::{OnAir, TelevisionChannel}; use crate::entry::{Entry, PreviewCommand, PreviewType}; use devicons::FileIcon; +use rustc_hash::{FxBuildHasher, FxHashSet}; use std::collections::HashSet; use std::path::PathBuf; use television_fuzzy::matcher::{config::Config, injector::Injector, Matcher}; @@ -11,7 +12,7 @@ pub struct Channel { crawl_handle: tokio::task::JoinHandle<()>, // PERF: cache results (to make deleting characters smoother) with // a shallow stack of sub-patterns as keys (e.g. "a", "ab", "abc") - selected_entries: HashSet, + selected_entries: FxHashSet, } impl Channel { @@ -22,7 +23,7 @@ impl Channel { Channel { matcher, crawl_handle, - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -114,7 +115,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/env.rs b/crates/television-channels/src/channels/env.rs index 2b8031a..aee2f6b 100644 --- a/crates/television-channels/src/channels/env.rs +++ b/crates/television-channels/src/channels/env.rs @@ -1,6 +1,7 @@ use std::collections::HashSet; use devicons::FileIcon; +use rustc_hash::{FxBuildHasher, FxHashSet}; use super::OnAir; use crate::entry::{Entry, PreviewType}; @@ -17,7 +18,7 @@ struct EnvVar { pub struct Channel { matcher: Matcher, file_icon: FileIcon, - selected_entries: HashSet, + selected_entries: FxHashSet, } const NUM_THREADS: usize = 1; @@ -35,7 +36,7 @@ impl Channel { Channel { matcher, file_icon: FileIcon::from(FILE_ICON_STR), - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -99,7 +100,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/files.rs b/crates/television-channels/src/channels/files.rs index 5d866f1..cdc9cff 100644 --- a/crates/television-channels/src/channels/files.rs +++ b/crates/television-channels/src/channels/files.rs @@ -1,6 +1,7 @@ use crate::channels::{OnAir, TelevisionChannel}; use crate::entry::{Entry, PreviewType}; use devicons::FileIcon; +use rustc_hash::{FxBuildHasher, FxHashSet}; use std::collections::HashSet; use std::path::PathBuf; use television_fuzzy::matcher::{config::Config, injector::Injector, Matcher}; @@ -11,7 +12,7 @@ pub struct Channel { crawl_handle: tokio::task::JoinHandle<()>, // PERF: cache results (to make deleting characters smoother) with // a shallow stack of sub-patterns as keys (e.g. "a", "ab", "abc") - selected_entries: HashSet, + selected_entries: FxHashSet, } impl Channel { @@ -22,7 +23,7 @@ impl Channel { Channel { matcher, crawl_handle, - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -72,7 +73,7 @@ impl From<&mut TelevisionChannel> for Channel { entries .iter() .map(|entry| PathBuf::from(&entry.name)) - .collect::>() + .collect::>() .into_iter() .collect(), ) @@ -83,7 +84,7 @@ impl From<&mut TelevisionChannel> for Channel { entries .iter() .map(|entry| PathBuf::from(&entry.name)) - .collect::>() + .collect::>() .into_iter() .collect(), ) @@ -120,7 +121,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/git_repos.rs b/crates/television-channels/src/channels/git_repos.rs index c49cdb0..c0ca345 100644 --- a/crates/television-channels/src/channels/git_repos.rs +++ b/crates/television-channels/src/channels/git_repos.rs @@ -2,6 +2,7 @@ use devicons::FileIcon; use directories::BaseDirs; use ignore::overrides::OverrideBuilder; use lazy_static::lazy_static; +use rustc_hash::{FxBuildHasher, FxHashSet}; use std::collections::HashSet; use std::path::PathBuf; use tokio::task::JoinHandle; @@ -16,7 +17,7 @@ pub struct Channel { matcher: Matcher, icon: FileIcon, crawl_handle: JoinHandle<()>, - selected_entries: HashSet, + selected_entries: FxHashSet, } impl Channel { @@ -31,7 +32,7 @@ impl Channel { matcher, icon: FileIcon::from("git"), crawl_handle, - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -84,7 +85,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/remote_control.rs b/crates/television-channels/src/channels/remote_control.rs index f474f7b..6a3e95f 100644 --- a/crates/television-channels/src/channels/remote_control.rs +++ b/crates/television-channels/src/channels/remote_control.rs @@ -7,6 +7,7 @@ use crate::entry::{Entry, PreviewType}; use clap::ValueEnum; use color_eyre::Result; use devicons::FileIcon; +use rustc_hash::{FxBuildHasher, FxHashSet}; use television_fuzzy::matcher::{config::Config, Matcher}; use super::cable; @@ -14,7 +15,7 @@ use super::cable; pub struct RemoteControl { matcher: Matcher, cable_channels: Option, - selected_entries: HashSet, + selected_entries: FxHashSet, } #[derive(Clone)] @@ -61,7 +62,7 @@ impl RemoteControl { RemoteControl { matcher, cable_channels, - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } @@ -143,7 +144,7 @@ impl OnAir for RemoteControl { .collect() } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/stdin.rs b/crates/television-channels/src/channels/stdin.rs index 9cef99c..2ea4262 100644 --- a/crates/television-channels/src/channels/stdin.rs +++ b/crates/television-channels/src/channels/stdin.rs @@ -4,6 +4,7 @@ use std::{ thread::spawn, }; +use rustc_hash::{FxBuildHasher, FxHashSet}; use tracing::debug; use super::OnAir; @@ -13,7 +14,7 @@ use television_fuzzy::matcher::{config::Config, injector::Injector, Matcher}; pub struct Channel { matcher: Matcher, preview_type: PreviewType, - selected_entries: HashSet, + selected_entries: FxHashSet, } impl Channel { @@ -26,7 +27,7 @@ impl Channel { Self { matcher, preview_type: preview_type.unwrap_or_default(), - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -93,7 +94,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-channels/src/channels/text.rs b/crates/television-channels/src/channels/text.rs index 84f7879..d58fa30 100644 --- a/crates/television-channels/src/channels/text.rs +++ b/crates/television-channels/src/channels/text.rs @@ -2,6 +2,7 @@ use super::{OnAir, TelevisionChannel}; use crate::entry::{Entry, PreviewType}; use devicons::FileIcon; use ignore::WalkState; +use rustc_hash::{FxBuildHasher, FxHashSet}; use std::{ collections::HashSet, fs::File, @@ -37,7 +38,7 @@ impl CandidateLine { pub struct Channel { matcher: Matcher, crawl_handle: tokio::task::JoinHandle<()>, - selected_entries: HashSet, + selected_entries: FxHashSet, } impl Channel { @@ -51,7 +52,7 @@ impl Channel { Channel { matcher, crawl_handle, - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } @@ -76,7 +77,7 @@ impl Channel { Channel { matcher, crawl_handle, - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } @@ -101,7 +102,7 @@ impl Channel { Channel { matcher, crawl_handle: load_handle, - selected_entries: HashSet::new(), + selected_entries: HashSet::with_hasher(FxBuildHasher), } } } @@ -216,7 +217,7 @@ impl OnAir for Channel { }) } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { &self.selected_entries } diff --git a/crates/television-derive/src/lib.rs b/crates/television-derive/src/lib.rs index 0526cc5..0cd8f86 100644 --- a/crates/television-derive/src/lib.rs +++ b/crates/television-derive/src/lib.rs @@ -213,7 +213,7 @@ fn impl_tv_channel(ast: &syn::DeriveInput) -> TokenStream { } } - fn selected_entries(&self) -> &HashSet { + fn selected_entries(&self) -> &FxHashSet { match self { #( #enum_name::#variant_names(ref channel) => { diff --git a/crates/television-previewers/Cargo.toml b/crates/television-previewers/Cargo.toml index d97aed4..b5ae3cc 100644 --- a/crates/television-previewers/Cargo.toml +++ b/crates/television-previewers/Cargo.toml @@ -21,6 +21,7 @@ tracing = { workspace = true } tokio = { workspace = true } color-eyre = { workspace = true } lazy_static = { workspace = true } +rustc-hash = { workspace = true } parking_lot = "0.12.3" devicons = "0.6.11" diff --git a/crates/television-previewers/src/previewers/cache.rs b/crates/television-previewers/src/previewers/cache.rs index a5ad742..718f835 100644 --- a/crates/television-previewers/src/previewers/cache.rs +++ b/crates/television-previewers/src/previewers/cache.rs @@ -1,4 +1,5 @@ -use std::{collections::HashMap, sync::Arc}; +use rustc_hash::FxHashMap; +use std::sync::Arc; use crate::previewers::Preview; use television_utils::cache::RingSet; @@ -15,7 +16,7 @@ const DEFAULT_PREVIEW_CACHE_SIZE: usize = 100; /// The cache is implemented as an LRU cache with a fixed size. #[derive(Debug)] pub struct PreviewCache { - entries: HashMap>, + entries: FxHashMap>, ring_set: RingSet, } @@ -23,7 +24,7 @@ impl PreviewCache { /// Create a new preview cache with the given capacity. pub fn new(capacity: usize) -> Self { PreviewCache { - entries: HashMap::new(), + entries: FxHashMap::default(), ring_set: RingSet::with_capacity(capacity), } } diff --git a/crates/television-previewers/src/previewers/command.rs b/crates/television-previewers/src/previewers/command.rs index 6437714..6487f39 100644 --- a/crates/television-previewers/src/previewers/command.rs +++ b/crates/television-previewers/src/previewers/command.rs @@ -4,7 +4,7 @@ use crate::previewers::{Preview, PreviewContent}; use lazy_static::lazy_static; use parking_lot::Mutex; use regex::Regex; -use std::collections::HashSet; +use rustc_hash::FxHashSet; use std::sync::atomic::{AtomicU8, Ordering}; use std::sync::Arc; use television_channels::entry::{Entry, PreviewCommand}; @@ -18,7 +18,7 @@ pub struct CommandPreviewer { config: CommandPreviewerConfig, concurrent_preview_tasks: Arc, last_previewed: Arc>>, - in_flight_previews: Arc>>, + in_flight_previews: Arc>>, } #[allow(dead_code)] @@ -57,7 +57,7 @@ impl CommandPreviewer { last_previewed: Arc::new(Mutex::new(Arc::new( Preview::default().stale(), ))), - in_flight_previews: Arc::new(Mutex::new(HashSet::new())), + in_flight_previews: Arc::new(Mutex::new(FxHashSet::default())), } } diff --git a/crates/television-previewers/src/previewers/env.rs b/crates/television-previewers/src/previewers/env.rs index 768fd0d..0774b73 100644 --- a/crates/television-previewers/src/previewers/env.rs +++ b/crates/television-previewers/src/previewers/env.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::sync::Arc; use crate::previewers::{Preview, PreviewContent}; @@ -6,7 +6,7 @@ use television_channels::entry; #[derive(Debug, Default)] pub struct EnvVarPreviewer { - cache: HashMap>, + cache: FxHashMap>, _config: EnvVarPreviewerConfig, } @@ -16,7 +16,7 @@ pub struct EnvVarPreviewerConfig {} impl EnvVarPreviewer { pub fn new(config: Option) -> Self { EnvVarPreviewer { - cache: HashMap::new(), + cache: FxHashMap::default(), _config: config.unwrap_or_default(), } } diff --git a/crates/television-previewers/src/previewers/files.rs b/crates/television-previewers/src/previewers/files.rs index 935c763..f560368 100644 --- a/crates/television-previewers/src/previewers/files.rs +++ b/crates/television-previewers/src/previewers/files.rs @@ -1,5 +1,6 @@ use color_eyre::Result; use parking_lot::Mutex; +use rustc_hash::{FxBuildHasher, FxHashSet}; use std::collections::HashSet; use std::fs::File; use std::io::{BufRead, BufReader, Seek}; @@ -28,7 +29,7 @@ pub struct FilePreviewer { pub syntax_theme: Arc, concurrent_preview_tasks: Arc, last_previewed: Arc>>, - in_flight_previews: Arc>>, + in_flight_previews: Arc>>, } #[derive(Debug, Clone, Default)] @@ -74,7 +75,9 @@ impl FilePreviewer { last_previewed: Arc::new(Mutex::new(Arc::new( Preview::default().stale(), ))), - in_flight_previews: Arc::new(Mutex::new(HashSet::new())), + in_flight_previews: Arc::new(Mutex::new(HashSet::with_hasher( + FxBuildHasher, + ))), } } @@ -137,7 +140,7 @@ pub fn try_preview( syntax_theme: &Arc, concurrent_tasks: &Arc, last_previewed: &Arc>>, - in_flight_previews: &Arc>>, + in_flight_previews: &Arc>>, ) { debug!("Computing preview for {:?}", entry.name); let path = PathBuf::from(&entry.name); diff --git a/crates/television-screen/Cargo.toml b/crates/television-screen/Cargo.toml index df9e9be..79f1744 100644 --- a/crates/television-screen/Cargo.toml +++ b/crates/television-screen/Cargo.toml @@ -21,6 +21,7 @@ ratatui = { workspace = true } serde = { workspace = true } color-eyre = { workspace = true } syntect = { workspace = true } +rustc-hash = { workspace = true } [lints] workspace = true diff --git a/crates/television-screen/src/cache.rs b/crates/television-screen/src/cache.rs index adfa0d6..526f7bf 100644 --- a/crates/television-screen/src/cache.rs +++ b/crates/television-screen/src/cache.rs @@ -1,4 +1,5 @@ -use std::{collections::HashMap, sync::Arc}; +use rustc_hash::FxHashMap; +use std::sync::Arc; use ratatui::widgets::Paragraph; use television_utils::cache::RingSet; @@ -7,14 +8,14 @@ const DEFAULT_RENDERED_PREVIEW_CACHE_SIZE: usize = 25; #[derive(Debug)] pub struct RenderedPreviewCache<'a> { - previews: HashMap>>, + previews: FxHashMap>>, ring_set: RingSet, } impl<'a> RenderedPreviewCache<'a> { pub fn new(capacity: usize) -> Self { RenderedPreviewCache { - previews: HashMap::new(), + previews: FxHashMap::default(), ring_set: RingSet::with_capacity(capacity), } } diff --git a/crates/television-screen/src/keybindings.rs b/crates/television-screen/src/keybindings.rs index f555ed2..5e29cb6 100644 --- a/crates/television-screen/src/keybindings.rs +++ b/crates/television-screen/src/keybindings.rs @@ -1,4 +1,5 @@ -use std::{collections::HashMap, fmt::Display}; +use rustc_hash::FxHashMap; +use std::fmt::Display; use crate::{colors::Colorscheme, mode::Mode}; use ratatui::{ @@ -10,11 +11,11 @@ use ratatui::{ #[derive(Debug, Clone)] pub struct DisplayableKeybindings { - bindings: HashMap>, + bindings: FxHashMap>, } impl DisplayableKeybindings { - pub fn new(bindings: HashMap>) -> Self { + pub fn new(bindings: FxHashMap>) -> Self { Self { bindings } } } @@ -52,7 +53,7 @@ impl Display for DisplayableAction { } pub fn build_keybindings_table<'a>( - keybindings: &'a HashMap, + keybindings: &'a FxHashMap, mode: Mode, colorscheme: &'a Colorscheme, ) -> Table<'a> { diff --git a/crates/television-screen/src/remote_control.rs b/crates/television-screen/src/remote_control.rs index c16d6c1..387d8e6 100644 --- a/crates/television-screen/src/remote_control.rs +++ b/crates/television-screen/src/remote_control.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use crate::colors::{Colorscheme, GeneralColorscheme}; use crate::logo::build_remote_logo_paragraph; @@ -25,7 +25,7 @@ pub fn draw_remote_control( use_nerd_font_icons: bool, picker_state: &mut ListState, input_state: &mut Input, - icon_color_cache: &mut HashMap, + icon_color_cache: &mut FxHashMap, mode: &Mode, colorscheme: &Colorscheme, ) -> Result<()> { @@ -65,7 +65,7 @@ fn draw_rc_channels( entries: &[Entry], use_nerd_font_icons: bool, picker_state: &mut ListState, - icon_color_cache: &mut HashMap, + icon_color_cache: &mut FxHashMap, colorscheme: &Colorscheme, ) { let rc_block = Block::default() diff --git a/crates/television-screen/src/results.rs b/crates/television-screen/src/results.rs index 9d8ecb9..6c52416 100644 --- a/crates/television-screen/src/results.rs +++ b/crates/television-screen/src/results.rs @@ -8,7 +8,7 @@ use ratatui::widgets::{ Block, BorderType, Borders, List, ListDirection, ListState, Padding, }; use ratatui::Frame; -use std::collections::{HashMap, HashSet}; +use rustc_hash::{FxHashMap, FxHashSet}; use std::str::FromStr; use television_channels::entry::Entry; use television_utils::strings::{ @@ -23,10 +23,10 @@ const DESLECTED_SYMBOL: &str = " "; pub fn build_results_list<'a, 'b>( results_block: Block<'b>, entries: &'a [Entry], - selected_entries: Option<&HashSet>, + selected_entries: Option<&FxHashSet>, list_direction: ListDirection, use_icons: bool, - icon_color_cache: &mut HashMap, + icon_color_cache: &mut FxHashMap, colorscheme: &ResultsColorscheme, ) -> List<'a> where @@ -156,11 +156,11 @@ pub fn draw_results_list( f: &mut Frame, rect: Rect, entries: &[Entry], - selected_entries: &HashSet, + selected_entries: &FxHashSet, relative_picker_state: &mut ListState, input_bar_position: InputPosition, use_nerd_font_icons: bool, - icon_color_cache: &mut HashMap, + icon_color_cache: &mut FxHashMap, colorscheme: &Colorscheme, help_keybinding: &str, preview_keybinding: &str, diff --git a/crates/television-utils/Cargo.toml b/crates/television-utils/Cargo.toml index 79c9279..e3599d4 100644 --- a/crates/television-utils/Cargo.toml +++ b/crates/television-utils/Cargo.toml @@ -19,6 +19,7 @@ color-eyre = { workspace = true } directories = { workspace = true } syntect = { workspace = true } unicode-width = { workspace = true } +rustc-hash = { workspace = true } ignore = "0.4.23" bat = { version = "0.24.0", default-features = false, features = [ diff --git a/crates/television-utils/src/cache.rs b/crates/television-utils/src/cache.rs index 0809799..710a92e 100644 --- a/crates/television-utils/src/cache.rs +++ b/crates/television-utils/src/cache.rs @@ -1,3 +1,4 @@ +use rustc_hash::{FxBuildHasher, FxHashSet}; use std::collections::{HashSet, VecDeque}; use tracing::debug; @@ -43,7 +44,7 @@ use tracing::debug; #[derive(Debug)] pub struct RingSet { ring_buffer: VecDeque, - known_keys: HashSet, + known_keys: FxHashSet, capacity: usize, } @@ -55,7 +56,10 @@ where pub fn with_capacity(capacity: usize) -> Self { RingSet { ring_buffer: VecDeque::with_capacity(capacity), - known_keys: HashSet::with_capacity(capacity), + known_keys: HashSet::with_capacity_and_hasher( + capacity, + FxBuildHasher, + ), capacity, } } diff --git a/crates/television-utils/src/files.rs b/crates/television-utils/src/files.rs index c9a4ff7..cf51987 100644 --- a/crates/television-utils/src/files.rs +++ b/crates/television-utils/src/files.rs @@ -1,8 +1,9 @@ +use rustc_hash::FxHashSet; use std::fmt::Debug; use std::fs::File; use std::io::Read; use std::path::Path; -use std::{collections::HashSet, path::PathBuf}; +use std::path::PathBuf; use ignore::{overrides::Override, types::TypesBuilder, WalkBuilder}; use lazy_static::lazy_static; @@ -99,7 +100,7 @@ where } lazy_static! { - static ref KNOWN_TEXT_FILE_EXTENSIONS: HashSet<&'static str> = [ + static ref KNOWN_TEXT_FILE_EXTENSIONS: FxHashSet<&'static str> = [ "ada", "adb", "ads", @@ -428,5 +429,7 @@ lazy_static! { "zsh", "zshrc", ] - .into(); + .iter() + .copied() + .collect(); } diff --git a/crates/television/app.rs b/crates/television/app.rs index 17d233c..78b7c69 100644 --- a/crates/television/app.rs +++ b/crates/television/app.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use rustc_hash::FxHashSet; use std::sync::Arc; use color_eyre::Result; @@ -45,16 +45,16 @@ pub struct App { /// The outcome of an action. #[derive(Debug)] pub enum ActionOutcome { - Entries(HashSet), + Entries(FxHashSet), Input(String), - Passthrough(HashSet, String), + Passthrough(FxHashSet, String), None, } /// The result of the application. #[derive(Debug)] pub struct AppOutput { - pub selected_entries: Option>, + pub selected_entries: Option>, pub passthrough: Option, } diff --git a/crates/television/cable.rs b/crates/television/cable.rs index 480540d..4cf5424 100644 --- a/crates/television/cable.rs +++ b/crates/television/cable.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use color_eyre::Result; use television_channels::cable::{CableChannelPrototype, CableChannels}; @@ -71,7 +71,7 @@ pub fn load_cable_channels() -> Result { debug!("Loaded cable channels: {:?}", user_defined_prototypes); - let mut cable_channels = HashMap::new(); + let mut cable_channels = FxHashMap::default(); for prototype in user_defined_prototypes { cable_channels.insert(prototype.name.clone(), prototype); } diff --git a/crates/television/cli.rs b/crates/television/cli.rs index 9e443e3..0377220 100644 --- a/crates/television/cli.rs +++ b/crates/television/cli.rs @@ -1,4 +1,5 @@ -use std::{collections::HashMap, path::Path}; +use rustc_hash::FxHashMap; +use std::path::Path; use clap::{Parser, Subcommand, ValueEnum}; use color_eyre::{eyre::eyre, Result}; @@ -231,7 +232,7 @@ pub fn list_channels() { /// - it should be able to handle commands within delimiters (quotes, brackets, etc.) pub fn guess_channel_from_prompt( prompt: &str, - command_mapping: &HashMap, + command_mapping: &FxHashMap, ) -> Result { debug!("Guessing channel from prompt: {}", prompt); // git checkout -qf diff --git a/crates/television/config/keybindings.rs b/crates/television/config/keybindings.rs index e42eca7..4298efc 100644 --- a/crates/television/config/keybindings.rs +++ b/crates/television/config/keybindings.rs @@ -1,8 +1,8 @@ use crate::action::Action; use crate::event::{convert_raw_event_to_key, Key}; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use rustc_hash::FxHashMap; use serde::{Deserialize, Deserializer}; -use std::collections::HashMap; use std::fmt::Display; use std::ops::{Deref, DerefMut}; use television_screen::mode::Mode; @@ -56,10 +56,10 @@ impl<'de> Deserialize<'de> for KeyBindings { where D: Deserializer<'de>, { - let parsed_map = - HashMap::>::deserialize( - deserializer, - )?; + let parsed_map = FxHashMap::< + Mode, + FxHashMap, + >::deserialize(deserializer)?; let keybindings = parsed_map .into_iter() diff --git a/crates/television/config/previewers.rs b/crates/television/config/previewers.rs index 51866ff..2c75686 100644 --- a/crates/television/config/previewers.rs +++ b/crates/television/config/previewers.rs @@ -1,6 +1,7 @@ +use std::collections::HashMap; + use config::ValueKind; use serde::Deserialize; -use std::collections::HashMap; use television_previewers::previewers; use television_previewers::previewers::PreviewerConfig; diff --git a/crates/television/config/shell_integration.rs b/crates/television/config/shell_integration.rs index 1fbf302..cd757cb 100644 --- a/crates/television/config/shell_integration.rs +++ b/crates/television/config/shell_integration.rs @@ -1,9 +1,11 @@ -use serde::Deserialize; use std::collections::HashMap; +use rustc_hash::FxHashMap; +use serde::Deserialize; + #[derive(Clone, Debug, Deserialize, Default)] pub struct ShellIntegrationConfig { - pub commands: HashMap, + pub commands: FxHashMap, } impl From for config::ValueKind { diff --git a/crates/television/config/styles.rs b/crates/television/config/styles.rs index 5cbe001..d7f65e4 100644 --- a/crates/television/config/styles.rs +++ b/crates/television/config/styles.rs @@ -1,16 +1,14 @@ use ratatui::prelude::{Color, Modifier, Style}; +use rustc_hash::FxHashMap; use serde::{Deserialize, Deserializer}; -use std::{ - collections::HashMap, - ops::{Deref, DerefMut}, -}; +use std::ops::{Deref, DerefMut}; use television_screen::mode::Mode; #[derive(Clone, Debug, Default)] -pub struct Styles(pub HashMap>); +pub struct Styles(pub FxHashMap>); impl Deref for Styles { - type Target = HashMap>; + type Target = FxHashMap>; fn deref(&self) -> &Self::Target { &self.0 } @@ -28,7 +26,7 @@ impl<'de> Deserialize<'de> for Styles { D: Deserializer<'de>, { let parsed_map = - HashMap::>::deserialize( + FxHashMap::>::deserialize( deserializer, )?; diff --git a/crates/television/config/themes/builtin.rs b/crates/television/config/themes/builtin.rs index afca7f0..305066a 100644 --- a/crates/television/config/themes/builtin.rs +++ b/crates/television/config/themes/builtin.rs @@ -1,10 +1,10 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use lazy_static::lazy_static; lazy_static! { - pub static ref BUILTIN_THEMES: HashMap<&'static str, &'static str> = { - let mut m = HashMap::new(); + pub static ref BUILTIN_THEMES: FxHashMap<&'static str, &'static str> = { + let mut m = FxHashMap::default(); m.insert("default", include_str!("../../../../themes/default.toml")); m.insert( "television", diff --git a/crates/television/config/ui.rs b/crates/television/config/ui.rs index 7d3650c..5ebea97 100644 --- a/crates/television/config/ui.rs +++ b/crates/television/config/ui.rs @@ -1,6 +1,7 @@ +use std::collections::HashMap; + use config::ValueKind; use serde::Deserialize; -use std::collections::HashMap; use television_screen::layout::{InputPosition, PreviewTitlePosition}; diff --git a/crates/television/keymap.rs b/crates/television/keymap.rs index fa9e248..dc443ef 100644 --- a/crates/television/keymap.rs +++ b/crates/television/keymap.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap; use std::ops::Deref; use color_eyre::Result; @@ -9,10 +9,10 @@ use crate::config::{Binding, KeyBindings}; use crate::event::Key; #[derive(Default, Debug)] -pub struct Keymap(pub HashMap>); +pub struct Keymap(pub FxHashMap>); impl Deref for Keymap { - type Target = HashMap>; + type Target = FxHashMap>; fn deref(&self) -> &Self::Target { &self.0 } @@ -20,9 +20,9 @@ impl Deref for Keymap { impl From<&KeyBindings> for Keymap { fn from(keybindings: &KeyBindings) -> Self { - let mut keymap = HashMap::new(); + let mut keymap = FxHashMap::default(); for (mode, bindings) in keybindings.iter() { - let mut mode_keymap = HashMap::new(); + let mut mode_keymap = FxHashMap::default(); for (action, binding) in bindings { match binding { Binding::SingleKey(key) => { diff --git a/crates/television/television.rs b/crates/television/television.rs index f161df8..55bde9a 100644 --- a/crates/television/television.rs +++ b/crates/television/television.rs @@ -6,7 +6,8 @@ use crate::{cable::load_cable_channels, keymap::Keymap}; use color_eyre::Result; use copypasta::{ClipboardContext, ClipboardProvider}; use ratatui::{layout::Rect, style::Color, Frame}; -use std::collections::{HashMap, HashSet}; +use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; +use std::collections::HashSet; use std::sync::{Arc, Mutex}; use television_channels::channels::{ remote_control::{load_builtin_channels, RemoteControl}, @@ -46,7 +47,7 @@ pub struct Television { pub preview_scroll: Option, pub preview_pane_height: u16, current_preview_total_lines: u16, - pub icon_color_cache: HashMap, + pub icon_color_cache: FxHashMap, pub rendered_preview_cache: Arc>>, pub(crate) spinner: Spinner, pub(crate) spinner_state: SpinnerState, @@ -102,7 +103,7 @@ impl Television { preview_scroll: None, preview_pane_height: 0, current_preview_total_lines: 0, - icon_color_cache: HashMap::new(), + icon_color_cache: FxHashMap::default(), rendered_preview_cache: Arc::new(Mutex::new( RenderedPreviewCache::default(), )), @@ -169,12 +170,12 @@ impl Television { pub fn get_selected_entries( &mut self, mode: Option, - ) -> Option> { + ) -> Option> { if self.channel.selected_entries().is_empty() || matches!(mode, Some(Mode::RemoteControl)) { return self.get_selected_entry(mode).map(|e| { - let mut set = HashSet::new(); + let mut set = HashSet::with_hasher(FxBuildHasher); set.insert(e); set }); @@ -615,10 +616,10 @@ impl Television { } impl KeyBindings { - pub fn to_displayable(&self) -> HashMap { + pub fn to_displayable(&self) -> FxHashMap { // channel mode keybindings - let channel_bindings: HashMap> = - HashMap::from_iter(vec![ + let channel_bindings: FxHashMap> = + FxHashMap::from_iter(vec![ ( DisplayableAction::ResultsNavigation, serialized_keys_for_actions( @@ -676,58 +677,56 @@ impl KeyBindings { ]); // remote control mode keybindings - let remote_control_bindings: HashMap> = - HashMap::from_iter(vec![ - ( - DisplayableAction::ResultsNavigation, - serialized_keys_for_actions( - self, - &[Action::SelectPrevEntry, Action::SelectNextEntry], - ), + let remote_control_bindings: FxHashMap< + DisplayableAction, + Vec, + > = FxHashMap::from_iter(vec![ + ( + DisplayableAction::ResultsNavigation, + serialized_keys_for_actions( + self, + &[Action::SelectPrevEntry, Action::SelectNextEntry], ), - ( - DisplayableAction::SelectEntry, - serialized_keys_for_actions( - self, - &[Action::ConfirmSelection], - ), + ), + ( + DisplayableAction::SelectEntry, + serialized_keys_for_actions(self, &[Action::ConfirmSelection]), + ), + ( + DisplayableAction::ToggleRemoteControl, + serialized_keys_for_actions( + self, + &[Action::ToggleRemoteControl], ), - ( - DisplayableAction::ToggleRemoteControl, - serialized_keys_for_actions( - self, - &[Action::ToggleRemoteControl], - ), - ), - ]); + ), + ]); // send to channel mode keybindings - let send_to_channel_bindings: HashMap> = - HashMap::from_iter(vec![ - ( - DisplayableAction::ResultsNavigation, - serialized_keys_for_actions( - self, - &[Action::SelectPrevEntry, Action::SelectNextEntry], - ), + let send_to_channel_bindings: FxHashMap< + DisplayableAction, + Vec, + > = FxHashMap::from_iter(vec![ + ( + DisplayableAction::ResultsNavigation, + serialized_keys_for_actions( + self, + &[Action::SelectPrevEntry, Action::SelectNextEntry], ), - ( - DisplayableAction::SelectEntry, - serialized_keys_for_actions( - self, - &[Action::ConfirmSelection], - ), + ), + ( + DisplayableAction::SelectEntry, + serialized_keys_for_actions(self, &[Action::ConfirmSelection]), + ), + ( + DisplayableAction::Cancel, + serialized_keys_for_actions( + self, + &[Action::ToggleSendToChannel], ), - ( - DisplayableAction::Cancel, - serialized_keys_for_actions( - self, - &[Action::ToggleSendToChannel], - ), - ), - ]); + ), + ]); - HashMap::from_iter(vec![ + FxHashMap::from_iter(vec![ (Mode::Channel, DisplayableKeybindings::new(channel_bindings)), ( Mode::RemoteControl,