diff options
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r-- | helix-term/src/commands.rs | 94 |
1 files changed, 49 insertions, 45 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 886ee62d..90226c53 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -4150,19 +4150,19 @@ enum ShellBehavior { } fn shell_pipe(cx: &mut Context) { - shell(cx, "pipe:".into(), ShellBehavior::Replace); + shell_prompt(cx, "pipe:".into(), ShellBehavior::Replace); } fn shell_pipe_to(cx: &mut Context) { - shell(cx, "pipe-to:".into(), ShellBehavior::Ignore); + shell_prompt(cx, "pipe-to:".into(), ShellBehavior::Ignore); } fn shell_insert_output(cx: &mut Context) { - shell(cx, "insert-output:".into(), ShellBehavior::Insert); + shell_prompt(cx, "insert-output:".into(), ShellBehavior::Insert); } fn shell_append_output(cx: &mut Context) { - shell(cx, "append-output:".into(), ShellBehavior::Append); + shell_prompt(cx, "append-output:".into(), ShellBehavior::Append); } fn shell_keep_pipe(cx: &mut Context) { @@ -4256,65 +4256,69 @@ fn shell_impl( Ok((tendril, output.status.success())) } -fn shell(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBehavior) { +fn shell(cx: &mut compositor::Context, cmd: &str, behavior: &ShellBehavior) { let pipe = match behavior { ShellBehavior::Replace | ShellBehavior::Ignore => true, ShellBehavior::Insert | ShellBehavior::Append => false, }; + let config = cx.editor.config(); + let shell = &config.shell; + let (view, doc) = current!(cx.editor); + let selection = doc.selection(view.id); + + let mut changes = Vec::with_capacity(selection.len()); + let text = doc.text().slice(..); + + for range in selection.ranges() { + let fragment = range.fragment(text); + let (output, success) = match shell_impl(shell, cmd, pipe.then(|| fragment.as_bytes())) { + Ok(result) => result, + Err(err) => { + cx.editor.set_error(err.to_string()); + return; + } + }; + + if !success { + cx.editor.set_error("Command failed"); + return; + } + + let (from, to) = match behavior { + ShellBehavior::Replace => (range.from(), range.to()), + ShellBehavior::Insert => (range.from(), range.from()), + ShellBehavior::Append => (range.to(), range.to()), + _ => (range.from(), range.from()), + }; + changes.push((from, to, Some(output))); + } + + if behavior != &ShellBehavior::Ignore { + let transaction = Transaction::change(doc.text(), changes.into_iter()); + doc.apply(&transaction, view.id); + } + + // 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) { ui::prompt( cx, prompt, Some('|'), ui::completers::none, move |cx, input: &str, event: PromptEvent| { - let config = cx.editor.config(); - let shell = &config.shell; if event != PromptEvent::Validate { return; } if input.is_empty() { return; } - let (view, doc) = current!(cx.editor); - let selection = doc.selection(view.id); - - let mut changes = Vec::with_capacity(selection.len()); - let text = doc.text().slice(..); - - for range in selection.ranges() { - let fragment = range.fragment(text); - let (output, success) = - match shell_impl(shell, input, pipe.then(|| fragment.as_bytes())) { - Ok(result) => result, - Err(err) => { - cx.editor.set_error(err.to_string()); - return; - } - }; - - if !success { - cx.editor.set_error("Command failed"); - return; - } - - let (from, to) = match behavior { - ShellBehavior::Replace => (range.from(), range.to()), - ShellBehavior::Insert => (range.from(), range.from()), - ShellBehavior::Append => (range.to(), range.to()), - _ => (range.from(), range.from()), - }; - changes.push((from, to, Some(output))); - } - - if behavior != ShellBehavior::Ignore { - let transaction = Transaction::change(doc.text(), changes.into_iter()); - doc.apply(&transaction, view.id); - } - // 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); + shell(cx, input, &behavior); }, ); } |