From 24f64714315888120f702f26e9a3ac1512d3dfb5 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 5 May 2014 18:00:24 +0100 Subject: [PATCH] Add '$' for keeping selections that passes a shell command '$' pipes each selections through a given shell command, and only keeps the one that have an exit code of 0 Fixes #36 --- README.asciidoc | 3 +++ doc/keymap | 2 +- src/normal.cc | 24 ++++++++++++++++++++++++ src/shell_manager.cc | 17 +++++++++++++---- src/shell_manager.hh | 6 ++++-- 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index 9cc5b6d6..8a6085f3 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -303,6 +303,9 @@ _alt-k_ allows you to enter a regex and keep only the selections that contains a match for this regex. using _alt-K_ you can keep the selections not containing a match. +_$_ allows you to enter a shell command and pipe each selections to it. +Selections whose shell command returns 0 will be kept, other will be dropped. + Object Selection ---------------- diff --git a/doc/keymap b/doc/keymap index e7671160..053d257c 100644 --- a/doc/keymap +++ b/doc/keymap @@ -1,5 +1,5 @@ ┌───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┲━━━━━━━━━━━━━━┓ -│ upper│ │convtab│ │ │sel all│ │ align│pattern│ │ │ │ ┃ ⇤ ┃ +│ upper│ │convtab│ │selpipe│sel all│ │ align│pattern│ │ │ │ ┃ ⇤ ┃ ├┄┄CASE┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┨ ┃ │ lower│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ │ ┃ ┃ ┢━━━━━━━┷━━━┱───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┺━━━┳━━━━━━━━━━┫ diff --git a/src/normal.cc b/src/normal.cc index c8a46cef..d58f5c8c 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -791,6 +791,29 @@ void keep(Context& context, int) }); } +void keep_pipe(Context& context, int) +{ + context.input_handler().prompt( + "keep pipe:", "", get_color("Prompt"), shell_complete, + [](const String& cmdline, PromptEvent event, Context& context) { + if (event != PromptEvent::Validate) + return; + const Buffer& buffer = context.buffer(); + auto& shell_manager = ShellManager::instance(); + SelectionList keep; + for (auto& sel : context.selections()) + { + int status = 0; + shell_manager.pipe(content(buffer, sel), cmdline, context, + {}, EnvVarMap{}, &status); + if (status == 0) + keep.push_back(sel); + } + if (keep.empty()) + throw runtime_error("no selections remaining"); + context.selections() = std::move(keep); + }); +} template void indent(Context& context, int) { @@ -1405,6 +1428,7 @@ KeyMap keymap = { alt('k'), keep }, { alt('K'), keep }, + { '$', keep_pipe }, { '<', deindent }, { '>', indent }, diff --git a/src/shell_manager.cc b/src/shell_manager.cc index 448b3ddc..d7caceb5 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -18,15 +18,17 @@ ShellManager::ShellManager() String ShellManager::eval(StringView cmdline, const Context& context, memoryview params, - const EnvVarMap& env_vars) + const EnvVarMap& env_vars, + int* exit_status) { - return pipe("", cmdline, context, params, env_vars); + return pipe("", cmdline, context, params, env_vars, exit_status); } String ShellManager::pipe(StringView input, StringView cmdline, const Context& context, memoryview params, - const EnvVarMap& env_vars) + const EnvVarMap& env_vars, + int* exit_status) { int write_pipe[2]; // child stdin int read_pipe[2]; // child stdout @@ -66,7 +68,14 @@ String ShellManager::pipe(StringView input, if (not errorout.empty()) write_debug("shell stderr: <<<\n" + errorout + ">>>"); - waitpid(pid, nullptr, 0); + waitpid(pid, exit_status, 0); + if (exit_status) + { + if (WIFEXITED(*exit_status)) + *exit_status = WEXITSTATUS(*exit_status); + else + *exit_status = -1; + } } else try { diff --git a/src/shell_manager.hh b/src/shell_manager.hh index 742ba1cd..16a5f27e 100644 --- a/src/shell_manager.hh +++ b/src/shell_manager.hh @@ -18,12 +18,14 @@ public: String eval(StringView cmdline, const Context& context, memoryview params, - const EnvVarMap& env_vars); + const EnvVarMap& env_vars, + int* exit_status = nullptr); String pipe(StringView input, StringView cmdline, const Context& context, memoryview params, - const EnvVarMap& env_vars); + const EnvVarMap& env_vars, + int* exit_status = nullptr); void register_env_var(StringView regex, EnvVarRetriever retriever);