summaryrefslogtreecommitdiff
path: root/helix-term/src/commands.rs
diff options
context:
space:
mode:
authorBlaž Hrastnik2020-12-18 10:24:50 +0000
committerGitHub2020-12-18 10:24:50 +0000
commit3f0dbfcac878131167953b6f57c923a5bc889e80 (patch)
tree41b876f9bb067e5f199fe53ecb78eeb57d09719b /helix-term/src/commands.rs
parentb12a6dc8303bbc1b4b08a9abb4668741d154adbd (diff)
parent25aa45e76c9bec62f36a59768298e1f2ea2678bf (diff)
Merge pull request #7 from helix-editor/interactive-split-select
File picker/interactive split prompt
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r--helix-term/src/commands.rs81
1 files changed, 77 insertions, 4 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index b345d2e8..5f8f63f1 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -10,7 +10,7 @@ use helix_core::{
use once_cell::sync::Lazy;
use crate::compositor::Compositor;
-use crate::ui::Prompt;
+use crate::ui::{self, Prompt, PromptEvent};
use helix_view::{
document::Mode,
@@ -248,6 +248,60 @@ pub fn extend_line_down(cx: &mut Context) {
cx.view.doc.set_selection(selection);
}
+pub fn split_selection(cx: &mut Context) {
+ // TODO: this needs to store initial selection state, revert on esc, confirm on enter
+ // needs to also call the callback function per input change, not just final time.
+ // could cheat and put it into completion_fn
+ //
+ // kakoune does it like this:
+ // # save state to register
+ // {
+ // # restore state from register
+ // # if event == abort, return early
+ // # add to history if enabled
+ // # update state
+ // }
+
+ let snapshot = cx.view.doc.state.clone();
+
+ let prompt = Prompt::new(
+ "split:".to_string(),
+ |input: &str| Vec::new(), // this is fine because Vec::new() doesn't allocate
+ move |editor: &mut Editor, input: &str, event: PromptEvent| {
+ match event {
+ PromptEvent::Abort => {
+ // revert state
+ let view = editor.view_mut().unwrap();
+ view.doc.state = snapshot.clone();
+ }
+ PromptEvent::Validate => {
+ //
+ }
+ PromptEvent::Update => {
+ match Regex::new(input) {
+ Ok(regex) => {
+ let view = editor.view_mut().unwrap();
+
+ // revert state to what it was before the last update
+ view.doc.state = snapshot.clone();
+
+ let text = &view.doc.text().slice(..);
+ let selection =
+ selection::split_on_matches(text, view.doc.selection(), &regex);
+ view.doc.set_selection(selection);
+ }
+ Err(_) => (), // TODO: mark command line as error
+ }
+ }
+ }
+ },
+ );
+
+ cx.callback = Some(Box::new(move |compositor: &mut Compositor| {
+ compositor.push(Box::new(prompt));
+ }));
+}
+
pub fn split_selection_on_newline(cx: &mut Context) {
let text = &cx.view.doc.text().slice(..);
// only compile the regex once
@@ -381,14 +435,33 @@ pub fn command_mode(cx: &mut Context) {
.filter(|command| command.contains(_input))
.collect()
}, // completion
- |editor: &mut Editor, input: &str| match input {
- "q" => editor.should_close = true,
- _ => (),
+ |editor: &mut Editor, input: &str, event: PromptEvent| {
+ if event != PromptEvent::Validate {
+ return;
+ }
+
+ let parts = input.split_ascii_whitespace().collect::<Vec<&str>>();
+
+ match parts.as_slice() {
+ &["q"] => editor.should_close = true,
+ &["o", path] => {
+ // TODO: make view()/view_mut() always contain a view.
+ let size = editor.view().unwrap().size;
+ editor.open(path.into(), size);
+ }
+ _ => (),
+ }
},
);
compositor.push(Box::new(prompt));
}));
}
+pub fn file_picker(cx: &mut Context) {
+ cx.callback = Some(Box::new(|compositor: &mut Compositor| {
+ let picker = ui::file_picker("./");
+ compositor.push(Box::new(picker));
+ }));
+}
// calculate line numbers for each selection range
fn selection_lines(state: &State) -> Vec<usize> {