|
|
@ -23,7 +23,7 @@ pub use markdown::Markdown;
|
|
|
|
pub use menu::Menu;
|
|
|
|
pub use menu::Menu;
|
|
|
|
pub use picker::{DynamicPicker, FileLocation, Picker};
|
|
|
|
pub use picker::{DynamicPicker, FileLocation, Picker};
|
|
|
|
pub use popup::Popup;
|
|
|
|
pub use popup::Popup;
|
|
|
|
pub use prompt::{Prompt, PromptEvent};
|
|
|
|
pub use prompt::{CompletionResult, Prompt, PromptEvent};
|
|
|
|
pub use spinner::{ProgressSpinners, Spinner};
|
|
|
|
pub use spinner::{ProgressSpinners, Spinner};
|
|
|
|
pub use text::Text;
|
|
|
|
pub use text::Text;
|
|
|
|
|
|
|
|
|
|
|
@ -35,7 +35,7 @@ pub fn prompt(
|
|
|
|
cx: &mut crate::commands::Context,
|
|
|
|
cx: &mut crate::commands::Context,
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
history_register: Option<char>,
|
|
|
|
history_register: Option<char>,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> Vec<prompt::Completion> + 'static,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> CompletionResult + 'static,
|
|
|
|
callback_fn: impl FnMut(&mut crate::compositor::Context, &str, PromptEvent) + 'static,
|
|
|
|
callback_fn: impl FnMut(&mut crate::compositor::Context, &str, PromptEvent) + 'static,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
let mut prompt = Prompt::new(prompt, history_register, completion_fn, callback_fn);
|
|
|
|
let mut prompt = Prompt::new(prompt, history_register, completion_fn, callback_fn);
|
|
|
@ -49,7 +49,7 @@ pub fn prompt_with_input(
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
input: String,
|
|
|
|
input: String,
|
|
|
|
history_register: Option<char>,
|
|
|
|
history_register: Option<char>,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> Vec<prompt::Completion> + 'static,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> CompletionResult + 'static,
|
|
|
|
callback_fn: impl FnMut(&mut crate::compositor::Context, &str, PromptEvent) + 'static,
|
|
|
|
callback_fn: impl FnMut(&mut crate::compositor::Context, &str, PromptEvent) + 'static,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
let prompt = Prompt::new(prompt, history_register, completion_fn, callback_fn)
|
|
|
|
let prompt = Prompt::new(prompt, history_register, completion_fn, callback_fn)
|
|
|
@ -61,7 +61,7 @@ pub fn regex_prompt(
|
|
|
|
cx: &mut crate::commands::Context,
|
|
|
|
cx: &mut crate::commands::Context,
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
history_register: Option<char>,
|
|
|
|
history_register: Option<char>,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> Vec<prompt::Completion> + 'static,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> CompletionResult + 'static,
|
|
|
|
fun: impl Fn(&mut crate::compositor::Context, rope::Regex, PromptEvent) + 'static,
|
|
|
|
fun: impl Fn(&mut crate::compositor::Context, rope::Regex, PromptEvent) + 'static,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
raw_regex_prompt(
|
|
|
|
raw_regex_prompt(
|
|
|
@ -72,11 +72,12 @@ pub fn regex_prompt(
|
|
|
|
move |cx, regex, _, event| fun(cx, regex, event),
|
|
|
|
move |cx, regex, _, event| fun(cx, regex, event),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn raw_regex_prompt(
|
|
|
|
pub fn raw_regex_prompt(
|
|
|
|
cx: &mut crate::commands::Context,
|
|
|
|
cx: &mut crate::commands::Context,
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
prompt: std::borrow::Cow<'static, str>,
|
|
|
|
history_register: Option<char>,
|
|
|
|
history_register: Option<char>,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> Vec<prompt::Completion> + 'static,
|
|
|
|
completion_fn: impl FnMut(&Editor, &str) -> CompletionResult + 'static,
|
|
|
|
fun: impl Fn(&mut crate::compositor::Context, rope::Regex, &str, PromptEvent) + 'static,
|
|
|
|
fun: impl Fn(&mut crate::compositor::Context, rope::Regex, &str, PromptEvent) + 'static,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
let (view, doc) = current!(cx.editor);
|
|
|
|
let (view, doc) = current!(cx.editor);
|
|
|
@ -254,6 +255,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> Picker
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub mod completers {
|
|
|
|
pub mod completers {
|
|
|
|
|
|
|
|
use super::CompletionResult;
|
|
|
|
use crate::ui::prompt::Completion;
|
|
|
|
use crate::ui::prompt::Completion;
|
|
|
|
use helix_core::fuzzy::fuzzy_match;
|
|
|
|
use helix_core::fuzzy::fuzzy_match;
|
|
|
|
use helix_core::syntax::LanguageServerFeature;
|
|
|
|
use helix_core::syntax::LanguageServerFeature;
|
|
|
@ -263,13 +265,13 @@ pub mod completers {
|
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
use std::borrow::Cow;
|
|
|
|
use std::borrow::Cow;
|
|
|
|
|
|
|
|
|
|
|
|
pub type Completer = fn(&Editor, &str) -> Vec<Completion>;
|
|
|
|
pub type Completer = fn(&Editor, &str) -> CompletionResult;
|
|
|
|
|
|
|
|
|
|
|
|
pub fn none(_editor: &Editor, _input: &str) -> Vec<Completion> {
|
|
|
|
pub fn none(_editor: &Editor, _input: &str) -> CompletionResult {
|
|
|
|
Vec::new()
|
|
|
|
CompletionResult::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn buffer(editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn buffer(editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
let names = editor.documents.values().map(|doc| {
|
|
|
|
let names = editor.documents.values().map(|doc| {
|
|
|
|
doc.relative_path()
|
|
|
|
doc.relative_path()
|
|
|
|
.map(|p| p.display().to_string().into())
|
|
|
|
.map(|p| p.display().to_string().into())
|
|
|
@ -279,10 +281,11 @@ pub mod completers {
|
|
|
|
fuzzy_match(input, names, true)
|
|
|
|
fuzzy_match(input, names, true)
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(name, _)| ((0..), name))
|
|
|
|
.map(|(name, _)| ((0..), name))
|
|
|
|
.collect()
|
|
|
|
.collect::<Vec<Completion>>()
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn theme(_editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn theme(_editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
let mut names = theme::Loader::read_names(&helix_loader::config_dir().join("themes"));
|
|
|
|
let mut names = theme::Loader::read_names(&helix_loader::config_dir().join("themes"));
|
|
|
|
for rt_dir in helix_loader::runtime_dirs() {
|
|
|
|
for rt_dir in helix_loader::runtime_dirs() {
|
|
|
|
names.extend(theme::Loader::read_names(&rt_dir.join("themes")));
|
|
|
|
names.extend(theme::Loader::read_names(&rt_dir.join("themes")));
|
|
|
@ -295,7 +298,8 @@ pub mod completers {
|
|
|
|
fuzzy_match(input, names, false)
|
|
|
|
fuzzy_match(input, names, false)
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(name, _)| ((0..), name.into()))
|
|
|
|
.map(|(name, _)| ((0..), name.into()))
|
|
|
|
.collect()
|
|
|
|
.collect::<Vec<Completion>>()
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Recursive function to get all keys from this value and add them to vec
|
|
|
|
/// Recursive function to get all keys from this value and add them to vec
|
|
|
@ -314,7 +318,7 @@ pub mod completers {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn setting(_editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn setting(_editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
static KEYS: Lazy<Vec<String>> = Lazy::new(|| {
|
|
|
|
static KEYS: Lazy<Vec<String>> = Lazy::new(|| {
|
|
|
|
let mut keys = Vec::new();
|
|
|
|
let mut keys = Vec::new();
|
|
|
|
let json = serde_json::json!(Config::default());
|
|
|
|
let json = serde_json::json!(Config::default());
|
|
|
@ -325,18 +329,19 @@ pub mod completers {
|
|
|
|
fuzzy_match(input, &*KEYS, false)
|
|
|
|
fuzzy_match(input, &*KEYS, false)
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(name, _)| ((0..), name.into()))
|
|
|
|
.map(|(name, _)| ((0..), name.into()))
|
|
|
|
.collect()
|
|
|
|
.collect::<Vec<Completion>>()
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn filename(editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn filename(editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
filename_with_git_ignore(editor, input, true)
|
|
|
|
filename_with_git_ignore(editor, input, true).into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn filename_with_git_ignore(
|
|
|
|
pub fn filename_with_git_ignore(
|
|
|
|
editor: &Editor,
|
|
|
|
editor: &Editor,
|
|
|
|
input: &str,
|
|
|
|
input: &str,
|
|
|
|
git_ignore: bool,
|
|
|
|
git_ignore: bool,
|
|
|
|
) -> Vec<Completion> {
|
|
|
|
) -> CompletionResult {
|
|
|
|
filename_impl(editor, input, git_ignore, |entry| {
|
|
|
|
filename_impl(editor, input, git_ignore, |entry| {
|
|
|
|
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
|
|
|
|
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
|
|
|
|
|
|
|
|
|
|
|
@ -346,9 +351,10 @@ pub mod completers {
|
|
|
|
FileMatch::Accept
|
|
|
|
FileMatch::Accept
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn language(editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn language(editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
let text: String = "text".into();
|
|
|
|
let text: String = "text".into();
|
|
|
|
|
|
|
|
|
|
|
|
let loader = editor.syn_loader.load();
|
|
|
|
let loader = editor.syn_loader.load();
|
|
|
@ -360,32 +366,34 @@ pub mod completers {
|
|
|
|
fuzzy_match(input, language_ids, false)
|
|
|
|
fuzzy_match(input, language_ids, false)
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(name, _)| ((0..), name.to_owned().into()))
|
|
|
|
.map(|(name, _)| ((0..), name.to_owned().into()))
|
|
|
|
.collect()
|
|
|
|
.collect::<Vec<Completion>>()
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn lsp_workspace_command(editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn lsp_workspace_command(editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
let Some(options) = doc!(editor)
|
|
|
|
let Some(options) = doc!(editor)
|
|
|
|
.language_servers_with_feature(LanguageServerFeature::WorkspaceCommand)
|
|
|
|
.language_servers_with_feature(LanguageServerFeature::WorkspaceCommand)
|
|
|
|
.find_map(|ls| ls.capabilities().execute_command_provider.as_ref())
|
|
|
|
.find_map(|ls| ls.capabilities().execute_command_provider.as_ref())
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
return vec![];
|
|
|
|
return CompletionResult::default();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
fuzzy_match(input, &options.commands, false)
|
|
|
|
fuzzy_match(input, &options.commands, false)
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(name, _)| ((0..), name.to_owned().into()))
|
|
|
|
.map(|(name, _)| ((0..), name.to_owned().into()))
|
|
|
|
.collect()
|
|
|
|
.collect::<Vec<Completion>>()
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn directory(editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn directory(editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
directory_with_git_ignore(editor, input, true)
|
|
|
|
directory_with_git_ignore(editor, input, true).into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn directory_with_git_ignore(
|
|
|
|
pub fn directory_with_git_ignore(
|
|
|
|
editor: &Editor,
|
|
|
|
editor: &Editor,
|
|
|
|
input: &str,
|
|
|
|
input: &str,
|
|
|
|
git_ignore: bool,
|
|
|
|
git_ignore: bool,
|
|
|
|
) -> Vec<Completion> {
|
|
|
|
) -> CompletionResult {
|
|
|
|
filename_impl(editor, input, git_ignore, |entry| {
|
|
|
|
filename_impl(editor, input, git_ignore, |entry| {
|
|
|
|
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
|
|
|
|
let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
|
|
|
|
|
|
|
|
|
|
|
@ -395,6 +403,7 @@ pub mod completers {
|
|
|
|
FileMatch::Reject
|
|
|
|
FileMatch::Reject
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
|
|
@ -414,7 +423,7 @@ pub mod completers {
|
|
|
|
input: &str,
|
|
|
|
input: &str,
|
|
|
|
git_ignore: bool,
|
|
|
|
git_ignore: bool,
|
|
|
|
filter_fn: F,
|
|
|
|
filter_fn: F,
|
|
|
|
) -> Vec<Completion>
|
|
|
|
) -> CompletionResult
|
|
|
|
where
|
|
|
|
where
|
|
|
|
F: Fn(&ignore::DirEntry) -> FileMatch,
|
|
|
|
F: Fn(&ignore::DirEntry) -> FileMatch,
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -498,17 +507,18 @@ pub mod completers {
|
|
|
|
fuzzy_match(&file_name, files, true)
|
|
|
|
fuzzy_match(&file_name, files, true)
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(name, _)| (range.clone(), name))
|
|
|
|
.map(|(name, _)| (range.clone(), name))
|
|
|
|
.collect()
|
|
|
|
.collect::<Vec<Completion>>()
|
|
|
|
|
|
|
|
.into()
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: complete to longest common match
|
|
|
|
// TODO: complete to longest common match
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
let mut files: Vec<_> = files.map(|file| (end.clone(), file)).collect();
|
|
|
|
let mut files: Vec<_> = files.map(|file| (end.clone(), file)).collect();
|
|
|
|
files.sort_unstable_by(|(_, path1), (_, path2)| path1.cmp(path2));
|
|
|
|
files.sort_unstable_by(|(_, path1), (_, path2)| path1.cmp(path2));
|
|
|
|
files
|
|
|
|
files.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn register(editor: &Editor, input: &str) -> Vec<Completion> {
|
|
|
|
pub fn register(editor: &Editor, input: &str) -> CompletionResult {
|
|
|
|
let iter = editor
|
|
|
|
let iter = editor
|
|
|
|
.registers
|
|
|
|
.registers
|
|
|
|
.iter_preview()
|
|
|
|
.iter_preview()
|
|
|
@ -519,6 +529,7 @@ pub mod completers {
|
|
|
|
fuzzy_match(input, iter, false)
|
|
|
|
fuzzy_match(input, iter, false)
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
|
.map(|(name, _)| ((0..), name.into()))
|
|
|
|
.map(|(name, _)| ((0..), name.into()))
|
|
|
|
.collect()
|
|
|
|
.collect::<Vec<Completion>>()
|
|
|
|
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|