Add a ShellManager which handles executing shell commands
ShellManager provides shell commands with environement variable to retrieve some internal values in the shell parameters.
This commit is contained in:
parent
2a291e6868
commit
0c596a9d64
|
@ -3,11 +3,9 @@
|
|||
#include "utils.hh"
|
||||
#include "assert.hh"
|
||||
#include "context.hh"
|
||||
#include "shell_manager.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
@ -101,29 +99,7 @@ static void shell_eval(std::vector<String>& params,
|
|||
const String& cmdline,
|
||||
const Context& context)
|
||||
{
|
||||
int write_pipe[2];
|
||||
int read_pipe[2];
|
||||
|
||||
pipe(write_pipe);
|
||||
pipe(read_pipe);
|
||||
|
||||
if (pid_t pid = fork())
|
||||
{
|
||||
close(write_pipe[0]);
|
||||
close(read_pipe[1]);
|
||||
close(write_pipe[1]);
|
||||
|
||||
String output;
|
||||
char buffer[1024];
|
||||
while (size_t size = read(read_pipe[0], buffer, 1024))
|
||||
{
|
||||
if (size == -1)
|
||||
break;
|
||||
output += String(buffer, buffer+size);
|
||||
}
|
||||
close(read_pipe[0]);
|
||||
waitpid(pid, NULL, 0);
|
||||
|
||||
String output = ShellManager::instance().eval(cmdline, context);
|
||||
TokenList tokens = split(output);
|
||||
|
||||
for (auto it = tokens.begin(); it != tokens.end(); ++it)
|
||||
|
@ -132,19 +108,6 @@ static void shell_eval(std::vector<String>& params,
|
|||
it->second - it->first));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
close(write_pipe[1]);
|
||||
close(read_pipe[0]);
|
||||
|
||||
dup2(read_pipe[1], 1);
|
||||
dup2(write_pipe[0], 0);
|
||||
|
||||
if (context.has_buffer())
|
||||
setenv("kak_bufname", context.buffer().name().c_str(), 1);
|
||||
execlp("sh", "sh", "-c", cmdline.c_str(), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void CommandManager::execute(const CommandParameters& params,
|
||||
const Context& context)
|
||||
|
|
|
@ -12,6 +12,8 @@ namespace Kakoune
|
|||
|
||||
using namespace std::placeholders;
|
||||
|
||||
typedef boost::regex_iterator<BufferIterator> RegexIterator;
|
||||
|
||||
void colorize_regex_range(DisplayBuffer& display_buffer,
|
||||
const BufferIterator& range_begin,
|
||||
const BufferIterator& range_end,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "window.hh"
|
||||
#include "buffer.hh"
|
||||
#include "file.hh"
|
||||
#include "shell_manager.hh"
|
||||
#include "command_manager.hh"
|
||||
#include "buffer_manager.hh"
|
||||
#include "register_manager.hh"
|
||||
|
@ -929,6 +930,7 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
NCurses::init(prompt_func, get_key_func);
|
||||
|
||||
ShellManager shell_manager;
|
||||
CommandManager command_manager;
|
||||
BufferManager buffer_manager;
|
||||
RegisterManager register_manager;
|
||||
|
@ -939,6 +941,11 @@ int main(int argc, char* argv[])
|
|||
|
||||
run_unit_tests();
|
||||
|
||||
shell_manager.register_env_var("bufname",
|
||||
[](const Context& context)
|
||||
{ return context.buffer().name(); });
|
||||
|
||||
|
||||
command_manager.register_commands({ "e", "edit" }, edit<false>,
|
||||
CommandManager::None,
|
||||
PerArgumentCommandCompleter({ complete_filename }));
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
namespace Kakoune
|
||||
{
|
||||
|
||||
typedef boost::regex_iterator<BufferIterator> RegexIterator;
|
||||
typedef boost::basic_regex<Character> Regex;
|
||||
|
||||
}
|
||||
|
|
|
@ -87,6 +87,8 @@ bool skip_while_reverse(BufferIterator& it, T condition)
|
|||
|
||||
}
|
||||
|
||||
typedef boost::regex_iterator<BufferIterator> RegexIterator;
|
||||
|
||||
template<bool punctuation_is_word>
|
||||
SelectionAndCaptures select_to_next_word(const Selection& selection)
|
||||
{
|
||||
|
|
85
src/shell_manager.cc
Normal file
85
src/shell_manager.cc
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "shell_manager.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
ShellManager::ShellManager()
|
||||
: m_regex(LR"(\$\{kak_([a-z0-9_]+)[^}]*\}|\$kak_([a-z0-9_]+))")
|
||||
{
|
||||
}
|
||||
|
||||
String ShellManager::eval(const String& cmdline, const Context& context)
|
||||
{
|
||||
int write_pipe[2];
|
||||
int read_pipe[2];
|
||||
|
||||
pipe(write_pipe);
|
||||
pipe(read_pipe);
|
||||
|
||||
String output;
|
||||
if (pid_t pid = fork())
|
||||
{
|
||||
close(write_pipe[0]);
|
||||
close(read_pipe[1]);
|
||||
close(write_pipe[1]);
|
||||
|
||||
char buffer[1024];
|
||||
while (size_t size = read(read_pipe[0], buffer, 1024))
|
||||
{
|
||||
if (size == -1)
|
||||
break;
|
||||
output += String(buffer, buffer+size);
|
||||
}
|
||||
close(read_pipe[0]);
|
||||
waitpid(pid, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
close(write_pipe[1]);
|
||||
close(read_pipe[0]);
|
||||
|
||||
dup2(read_pipe[1], 1);
|
||||
dup2(write_pipe[0], 0);
|
||||
|
||||
boost::regex_iterator<String::iterator> it(cmdline.begin(), cmdline.end(), m_regex);
|
||||
boost::regex_iterator<String::iterator> end;
|
||||
|
||||
while (it != end)
|
||||
{
|
||||
auto& match = *it;
|
||||
|
||||
String name;
|
||||
if (match[1].matched)
|
||||
name = String(match[1].first, match[1].second);
|
||||
else if (match[2].matched)
|
||||
name = String(match[2].first, match[2].second);
|
||||
else
|
||||
assert(false);
|
||||
assert(name.length() > 0);
|
||||
|
||||
auto env_var = m_env_vars.find(name);
|
||||
if (env_var != m_env_vars.end())
|
||||
{
|
||||
String value = env_var->second(context);
|
||||
setenv(("kak_" + name).c_str(), value.c_str(), 1);
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
execlp("sh", "sh", "-c", cmdline.c_str(), NULL);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
void ShellManager::register_env_var(const String& name,
|
||||
EnvVarRetriever retriever)
|
||||
{
|
||||
m_env_vars[name] = std::move(retriever);
|
||||
}
|
||||
|
||||
}
|
32
src/shell_manager.hh
Normal file
32
src/shell_manager.hh
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef shell_manager_hh_INCLUDED
|
||||
#define shell_manager_hh_INCLUDED
|
||||
|
||||
#include "utils.hh"
|
||||
#include "regex.hh"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Kakoune
|
||||
{
|
||||
|
||||
class Context;
|
||||
typedef std::function<String (const Context&)> EnvVarRetriever;
|
||||
|
||||
class ShellManager : public Singleton<ShellManager>
|
||||
{
|
||||
public:
|
||||
ShellManager();
|
||||
|
||||
String eval(const String& cmdline, const Context& context);
|
||||
|
||||
void register_env_var(const String& name, EnvVarRetriever retriever);
|
||||
|
||||
private:
|
||||
Regex m_regex;
|
||||
std::unordered_map<String, EnvVarRetriever> m_env_vars;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // shell_manager_hh_INCLUDED
|
||||
|
Loading…
Reference in New Issue
Block a user