@@ -115,10 +115,43 @@ pub fn file_picker(root: PathBuf) -> Picker<PathBuf> {
115115
116116pub mod completers {
117117 use crate::ui::prompt::Completion;
118− use std::borrow::Cow;
118+ use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
119+ use fuzzy_matcher::FuzzyMatcher;
120+ use helix_view::theme;
121+ use std::cmp::Reverse;
122+ use std::{borrow::Cow, sync::Arc};
119123
120124 pub type Completer = fn(&str) -> Vec<Completion>;
121125
126+ pub fn theme(input: &str) -> Vec<Completion> {
127+ let mut names = theme::Loader::read_names(&helix_core::runtime_dir().join("themes"));
128+ names.extend(theme::Loader::read_names(
129+ &helix_core::config_dir().join("themes"),
130+ ));
131+ names.push("default".into());
132+
133+ let mut names: Vec<_> = names
134+ .into_iter()
135+ .map(|name| ((0..), Cow::from(name)))
136+ .collect();
137+
138+ let matcher = Matcher::default();
139+
140+ let mut matches: Vec<_> = names
141+ .into_iter()
142+ .filter_map(|(range, name)| {
143+ matcher
144+ .fuzzy_match(&name, &input)
145+ .map(|score| (name, score))
146+ })
147+ .collect();
148+
149+ matches.sort_unstable_by_key(|(_file, score)| Reverse(*score));
150+ names = matches.into_iter().map(|(name, _)| ((0..), name)).collect();
151+
152+ names
153+ }
154+
122155 // TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
123156 pub fn filename(input: &str) -> Vec<Completion> {
124157 // Rust's filename handling is really annoying.
@@ -178,10 +211,6 @@ pub mod completers {
178211
179212 // if empty, return a list of dirs and files in current dir
180213 if let Some(file_name) = file_name {
181− use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
182− use fuzzy_matcher::FuzzyMatcher;
183− use std::cmp::Reverse;
184−
185214 let matcher = Matcher::default();
186215
187216 // inefficient, but we need to calculate the scores, filter out None, then sort.