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
This commit is contained in:
Maxime Coste 2014-05-05 18:00:24 +01:00
parent e6bda60ca4
commit 24f6471431
5 changed files with 45 additions and 7 deletions

View File

@ -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
----------------

View File

@ -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 │ │ ┃ ┃
┢━━━━━━━┷━━━┱───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┴───┬───┺━━━┳━━━━━━━━━━┫

View File

@ -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<bool indent_empty = false>
void indent(Context& context, int)
{
@ -1405,6 +1428,7 @@ KeyMap keymap =
{ alt('k'), keep<true> },
{ alt('K'), keep<false> },
{ '$', keep_pipe },
{ '<', deindent<true> },
{ '>', indent<false> },

View File

@ -18,15 +18,17 @@ ShellManager::ShellManager()
String ShellManager::eval(StringView cmdline, const Context& context,
memoryview<String> 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<String> 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
{

View File

@ -18,12 +18,14 @@ public:
String eval(StringView cmdline, const Context& context,
memoryview<String> params,
const EnvVarMap& env_vars);
const EnvVarMap& env_vars,
int* exit_status = nullptr);
String pipe(StringView input,
StringView cmdline, const Context& context,
memoryview<String> params,
const EnvVarMap& env_vars);
const EnvVarMap& env_vars,
int* exit_status = nullptr);
void register_env_var(StringView regex, EnvVarRetriever retriever);