Skip to content

Commit

Permalink
feat: execute helix command from pipe output
Browse files Browse the repository at this point in the history
  • Loading branch information
L-Trump committed Sep 30, 2024
1 parent 237cbe4 commit 3c76d75
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 7 deletions.
1 change: 1 addition & 0 deletions book/src/generated/typable-cmd.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
| `:append-output` | Run shell command, appending output after each selection. |
| `:pipe` | Pipe each selection to the shell command. |
| `:pipe-to` | Pipe each selection to the shell command, ignoring output. |
| `:pipe-execute` | Pipe each selection to the shell command, execute output as helix command. |
| `:run-shell-command`, `:sh` | Run a shell command |
| `:reset-diff-change`, `:diffget`, `:diffg` | Reset the diff change at the cursor position. |
| `:clear-register` | Clear given register. If no argument is provided, clear all registers. |
Expand Down
1 change: 1 addition & 0 deletions book/src/keymap.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Normal mode is the default mode when you launch helix. You can return to it from
| `!` | Run shell command, inserting output before each selection | `shell_insert_output` |
| `Alt-!` | Run shell command, appending output after each selection | `shell_append_output` |
| `$` | Pipe each selection into shell command, keep selections where command returned 0 | `shell_keep_pipe` |
| `Alt-$` | Pipe each selection into shell command, execute output as helix command | `shell_keep_pipe` |


### Selection manipulation
Expand Down
49 changes: 42 additions & 7 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ use crate::{
};

use crate::job::{self, Jobs};
use std::str::FromStr;
use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
Expand Down Expand Up @@ -555,6 +556,7 @@ impl MappableCommand {
dap_disable_exceptions, "Disable exception breakpoints",
shell_pipe, "Pipe selections through shell command",
shell_pipe_to, "Pipe selections into shell command ignoring output",
shell_pipe_execute, "Pipe selections into shell command, execute output as command",
shell_insert_output, "Insert shell command output before selections",
shell_append_output, "Append shell command output after selections",
shell_keep_pipe, "Filter selections with shell predicate",
Expand Down Expand Up @@ -5693,6 +5695,7 @@ enum ShellBehavior {
Ignore,
Insert,
Append,
Execute,
}

fn shell_pipe(cx: &mut Context) {
Expand All @@ -5703,6 +5706,10 @@ fn shell_pipe_to(cx: &mut Context) {
shell_prompt(cx, "pipe-to:".into(), ShellBehavior::Ignore);
}

fn shell_pipe_execute(cx: &mut Context) {
shell_prompt(cx, "pipe-execute:".into(), ShellBehavior::Execute);
}

fn shell_insert_output(cx: &mut Context) {
shell_prompt(cx, "insert-output:".into(), ShellBehavior::Insert);
}
Expand Down Expand Up @@ -5829,7 +5836,7 @@ async fn shell_impl_async(

fn shell(cx: &mut compositor::Context, cmd: &str, behavior: &ShellBehavior) {
let pipe = match behavior {
ShellBehavior::Replace | ShellBehavior::Ignore => true,
ShellBehavior::Replace | ShellBehavior::Ignore | ShellBehavior::Execute => true,
ShellBehavior::Insert | ShellBehavior::Append => false,
};

Expand Down Expand Up @@ -5876,6 +5883,7 @@ fn shell(cx: &mut compositor::Context, cmd: &str, behavior: &ShellBehavior) {
ShellBehavior::Replace => (range.from(), range.to(), range.len()),
ShellBehavior::Insert => (range.from(), range.from(), 0),
ShellBehavior::Append => (range.to(), range.to(), 0),
ShellBehavior::Execute => (range.from(), range.from(), 0),
_ => (range.from(), range.from(), 0),
};

Expand All @@ -5896,16 +5904,43 @@ fn shell(cx: &mut compositor::Context, cmd: &str, behavior: &ShellBehavior) {
changes.push((from, to, Some(output)));
}

if behavior != &ShellBehavior::Ignore {
let transaction = Transaction::change(doc.text(), changes.into_iter())
.with_selection(Selection::new(ranges, selection.primary_index()));
doc.apply(&transaction, view.id);
doc.append_changes_to_history(view);
}
let mut commands = Vec::with_capacity(changes.len());
match behavior {
ShellBehavior::Ignore => (),
ShellBehavior::Execute => {
for (_, _, command_text) in changes {
if let Some(command_text) = command_text {
if let Ok(command) = MappableCommand::from_str(&command_text[..]) {
commands.push(command)
}
}
}
}
_ => {
let transaction = Transaction::change(doc.text(), changes.into_iter())
.with_selection(Selection::new(ranges, selection.primary_index()));
doc.apply(&transaction, view.id);
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);

if behavior == &ShellBehavior::Execute {
for command in commands {
let mut ctx = Context {
register: None,
count: None,
editor: cx.editor,
callback: Vec::new(),
on_next_key_callback: None,
jobs: cx.jobs,
};
command.execute(&mut ctx);
}
}
}

fn shell_prompt(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBehavior) {
Expand Down
15 changes: 15 additions & 0 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2263,6 +2263,14 @@ fn pipe_to(
pipe_impl(cx, args, event, &ShellBehavior::Ignore)
}

fn pipe_execute(
cx: &mut compositor::Context,
args: &[Cow<str>],
event: PromptEvent,
) -> anyhow::Result<()> {
pipe_impl(cx, args, event, &ShellBehavior::Execute)
}

fn pipe(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) -> anyhow::Result<()> {
pipe_impl(cx, args, event, &ShellBehavior::Replace)
}
Expand Down Expand Up @@ -3092,6 +3100,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
fun: pipe_to,
signature: CommandSignature::none(),
},
TypableCommand {
name: "pipe-execute",
aliases: &[],
doc: "Pipe each selection to the shell command, execute output as command.",
fun: pipe_execute,
signature: CommandSignature::none(),
},
TypableCommand {
name: "run-shell-command",
aliases: &["sh"],
Expand Down
1 change: 1 addition & 0 deletions helix-term/src/keymap/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"!" => shell_insert_output,
"A-!" => shell_append_output,
"$" => shell_keep_pipe,
"A-$" => shell_pipe_execute,
"C-z" => suspend,

"C-a" => increment,
Expand Down

0 comments on commit 3c76d75

Please sign in to comment.