|
|
@ -59,7 +59,7 @@ use movement::Movement;
|
|
|
|
use crate::{
|
|
|
|
use crate::{
|
|
|
|
args,
|
|
|
|
args,
|
|
|
|
compositor::{self, Component, Compositor},
|
|
|
|
compositor::{self, Component, Compositor},
|
|
|
|
filter_picker_entry,
|
|
|
|
events, filter_picker_entry,
|
|
|
|
job::Callback,
|
|
|
|
job::Callback,
|
|
|
|
keymap::ReverseKeymap,
|
|
|
|
keymap::ReverseKeymap,
|
|
|
|
ui::{self, menu::Item, overlay::overlaid, Picker, Popup, Prompt, PromptEvent},
|
|
|
|
ui::{self, menu::Item, overlay::overlaid, Picker, Popup, Prompt, PromptEvent},
|
|
|
@ -142,6 +142,45 @@ impl<'a> Context<'a> {
|
|
|
|
pub fn count(&self) -> usize {
|
|
|
|
pub fn count(&self) -> usize {
|
|
|
|
self.count.map_or(1, |v| v.get())
|
|
|
|
self.count.map_or(1, |v| v.get())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn execute<F: FnOnce(&mut Self)>(&mut self, execute_fn: F) {
|
|
|
|
|
|
|
|
self.execute_impl(execute_fn)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn execute_command(&mut self, command: &MappableCommand) {
|
|
|
|
|
|
|
|
self.execute_impl(|cx| {
|
|
|
|
|
|
|
|
command.execute(cx);
|
|
|
|
|
|
|
|
helix_event::dispatch(events::PostCommand { command, cx });
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn execute_impl<F: FnOnce(&mut Self)>(&mut self, execute_fn: F) {
|
|
|
|
|
|
|
|
let pre_command_mode = self.editor.mode();
|
|
|
|
|
|
|
|
if pre_command_mode != Mode::Insert {
|
|
|
|
|
|
|
|
let (view, doc) = current!(self.editor);
|
|
|
|
|
|
|
|
doc.append_changes_to_history(view);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
execute_fn(self);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let post_command_mode = self.editor.mode();
|
|
|
|
|
|
|
|
if post_command_mode != pre_command_mode {
|
|
|
|
|
|
|
|
helix_event::dispatch(events::OnModeSwitch {
|
|
|
|
|
|
|
|
old_mode: pre_command_mode,
|
|
|
|
|
|
|
|
new_mode: post_command_mode,
|
|
|
|
|
|
|
|
cx: self,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !self.editor.tree.is_empty() {
|
|
|
|
|
|
|
|
let scrolloff = self.editor.config().scrolloff;
|
|
|
|
|
|
|
|
let (view, doc) = current!(self.editor);
|
|
|
|
|
|
|
|
if post_command_mode != Mode::Insert {
|
|
|
|
|
|
|
|
doc.append_changes_to_history(view);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
view.ensure_cursor_in_view(doc, scrolloff);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[inline]
|
|
|
@ -1981,7 +2020,6 @@ fn search_impl(
|
|
|
|
regex: &rope::Regex,
|
|
|
|
regex: &rope::Regex,
|
|
|
|
movement: Movement,
|
|
|
|
movement: Movement,
|
|
|
|
direction: Direction,
|
|
|
|
direction: Direction,
|
|
|
|
scrolloff: usize,
|
|
|
|
|
|
|
|
wrap_around: bool,
|
|
|
|
wrap_around: bool,
|
|
|
|
show_warnings: bool,
|
|
|
|
show_warnings: bool,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
@ -2054,7 +2092,6 @@ fn search_impl(
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
doc.set_selection(view.id, selection);
|
|
|
|
doc.set_selection(view.id, selection);
|
|
|
|
view.ensure_cursor_in_view_center(doc, scrolloff);
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -2078,7 +2115,6 @@ fn rsearch(cx: &mut Context) {
|
|
|
|
fn searcher(cx: &mut Context, direction: Direction) {
|
|
|
|
fn searcher(cx: &mut Context, direction: Direction) {
|
|
|
|
let reg = cx.register.unwrap_or('/');
|
|
|
|
let reg = cx.register.unwrap_or('/');
|
|
|
|
let config = cx.editor.config();
|
|
|
|
let config = cx.editor.config();
|
|
|
|
let scrolloff = config.scrolloff;
|
|
|
|
|
|
|
|
let wrap_around = config.search.wrap_around;
|
|
|
|
let wrap_around = config.search.wrap_around;
|
|
|
|
let movement = if cx.editor.mode() == Mode::Select {
|
|
|
|
let movement = if cx.editor.mode() == Mode::Select {
|
|
|
|
Movement::Extend
|
|
|
|
Movement::Extend
|
|
|
@ -2106,15 +2142,7 @@ fn searcher(cx: &mut Context, direction: Direction) {
|
|
|
|
} else if event != PromptEvent::Update {
|
|
|
|
} else if event != PromptEvent::Update {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
search_impl(
|
|
|
|
search_impl(cx.editor, ®ex, movement, direction, wrap_around, false);
|
|
|
|
cx.editor,
|
|
|
|
|
|
|
|
®ex,
|
|
|
|
|
|
|
|
movement,
|
|
|
|
|
|
|
|
direction,
|
|
|
|
|
|
|
|
scrolloff,
|
|
|
|
|
|
|
|
wrap_around,
|
|
|
|
|
|
|
|
false,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
},
|
|
|
|
},
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -2125,7 +2153,6 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
|
|
|
|
.register
|
|
|
|
.register
|
|
|
|
.unwrap_or(cx.editor.registers.last_search_register);
|
|
|
|
.unwrap_or(cx.editor.registers.last_search_register);
|
|
|
|
let config = cx.editor.config();
|
|
|
|
let config = cx.editor.config();
|
|
|
|
let scrolloff = config.scrolloff;
|
|
|
|
|
|
|
|
if let Some(query) = cx.editor.registers.first(register, cx.editor) {
|
|
|
|
if let Some(query) = cx.editor.registers.first(register, cx.editor) {
|
|
|
|
let search_config = &config.search;
|
|
|
|
let search_config = &config.search;
|
|
|
|
let case_insensitive = if search_config.smart_case {
|
|
|
|
let case_insensitive = if search_config.smart_case {
|
|
|
@ -2143,15 +2170,7 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
|
|
|
|
.build(&query)
|
|
|
|
.build(&query)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for _ in 0..count {
|
|
|
|
for _ in 0..count {
|
|
|
|
search_impl(
|
|
|
|
search_impl(cx.editor, ®ex, movement, direction, wrap_around, true);
|
|
|
|
cx.editor,
|
|
|
|
|
|
|
|
®ex,
|
|
|
|
|
|
|
|
movement,
|
|
|
|
|
|
|
|
direction,
|
|
|
|
|
|
|
|
scrolloff,
|
|
|
|
|
|
|
|
wrap_around,
|
|
|
|
|
|
|
|
true,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
let error = format!("Invalid regex: {}", query);
|
|
|
|
let error = format!("Invalid regex: {}", query);
|
|
|
@ -3188,22 +3207,8 @@ pub fn command_palette(cx: &mut Context) {
|
|
|
|
on_next_key_callback: None,
|
|
|
|
on_next_key_callback: None,
|
|
|
|
jobs: cx.jobs,
|
|
|
|
jobs: cx.jobs,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
let focus = view!(ctx.editor).id;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command.execute(&mut ctx);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ctx.editor.tree.contains(focus) {
|
|
|
|
|
|
|
|
let config = ctx.editor.config();
|
|
|
|
|
|
|
|
let mode = ctx.editor.mode();
|
|
|
|
|
|
|
|
let view = view_mut!(ctx.editor, focus);
|
|
|
|
|
|
|
|
let doc = doc_mut!(ctx.editor, &view.doc);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
view.ensure_cursor_in_view(doc, config.scrolloff);
|
|
|
|
ctx.execute_command(command);
|
|
|
|
|
|
|
|
|
|
|
|
if mode != Mode::Insert {
|
|
|
|
|
|
|
|
doc.append_changes_to_history(view);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
compositor.push(Box::new(overlaid(picker)));
|
|
|
|
compositor.push(Box::new(overlaid(picker)));
|
|
|
|
},
|
|
|
|
},
|
|
|
@ -4329,7 +4334,6 @@ fn replace_with_yanked_impl(editor: &mut Editor, register: char, count: usize) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
let values: Vec<_> = values.map(|value| value.to_string()).collect();
|
|
|
|
let values: Vec<_> = values.map(|value| value.to_string()).collect();
|
|
|
|
let scrolloff = editor.config().scrolloff;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let (view, doc) = current!(editor);
|
|
|
|
let (view, doc) = current!(editor);
|
|
|
|
let repeat = std::iter::repeat(
|
|
|
|
let repeat = std::iter::repeat(
|
|
|
@ -4352,8 +4356,6 @@ fn replace_with_yanked_impl(editor: &mut Editor, register: char, count: usize) {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
doc.apply(&transaction, view.id);
|
|
|
|
doc.apply(&transaction, view.id);
|
|
|
|
doc.append_changes_to_history(view);
|
|
|
|
|
|
|
|
view.ensure_cursor_in_view(doc, scrolloff);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn replace_selections_with_clipboard(cx: &mut Context) {
|
|
|
|
fn replace_selections_with_clipboard(cx: &mut Context) {
|
|
|
@ -5037,7 +5039,6 @@ fn match_brackets(cx: &mut Context) {
|
|
|
|
|
|
|
|
|
|
|
|
fn jump_forward(cx: &mut Context) {
|
|
|
|
fn jump_forward(cx: &mut Context) {
|
|
|
|
let count = cx.count();
|
|
|
|
let count = cx.count();
|
|
|
|
let config = cx.editor.config();
|
|
|
|
|
|
|
|
let view = view_mut!(cx.editor);
|
|
|
|
let view = view_mut!(cx.editor);
|
|
|
|
let doc_id = view.doc;
|
|
|
|
let doc_id = view.doc;
|
|
|
|
|
|
|
|
|
|
|
@ -5051,13 +5052,11 @@ fn jump_forward(cx: &mut Context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
doc.set_selection(view.id, selection);
|
|
|
|
doc.set_selection(view.id, selection);
|
|
|
|
view.ensure_cursor_in_view_center(doc, config.scrolloff);
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn jump_backward(cx: &mut Context) {
|
|
|
|
fn jump_backward(cx: &mut Context) {
|
|
|
|
let count = cx.count();
|
|
|
|
let count = cx.count();
|
|
|
|
let config = cx.editor.config();
|
|
|
|
|
|
|
|
let (view, doc) = current!(cx.editor);
|
|
|
|
let (view, doc) = current!(cx.editor);
|
|
|
|
let doc_id = doc.id();
|
|
|
|
let doc_id = doc.id();
|
|
|
|
|
|
|
|
|
|
|
@ -5071,7 +5070,6 @@ fn jump_backward(cx: &mut Context) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
doc.set_selection(view.id, selection);
|
|
|
|
doc.set_selection(view.id, selection);
|
|
|
|
view.ensure_cursor_in_view_center(doc, config.scrolloff);
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -5789,10 +5787,6 @@ fn shell(cx: &mut compositor::Context, cmd: &str, behavior: &ShellBehavior) {
|
|
|
|
doc.apply(&transaction, view.id);
|
|
|
|
doc.apply(&transaction, view.id);
|
|
|
|
doc.append_changes_to_history(view);
|
|
|
|
doc.append_changes_to_history(view);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// after replace cursor may be out of bounds, do this to
|
|
|
|
|
|
|
|
// make sure cursor is in view and update scroll as well
|
|
|
|
|
|
|
|
view.ensure_cursor_in_view(doc, config.scrolloff);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn shell_prompt(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBehavior) {
|
|
|
|
fn shell_prompt(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBehavior) {
|
|
|
|