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 "utils.hh"
|
||||||
#include "assert.hh"
|
#include "assert.hh"
|
||||||
#include "context.hh"
|
#include "context.hh"
|
||||||
|
#include "shell_manager.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
@ -101,29 +99,7 @@ static void shell_eval(std::vector<String>& params,
|
||||||
const String& cmdline,
|
const String& cmdline,
|
||||||
const Context& context)
|
const Context& context)
|
||||||
{
|
{
|
||||||
int write_pipe[2];
|
String output = ShellManager::instance().eval(cmdline, context);
|
||||||
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);
|
|
||||||
|
|
||||||
TokenList tokens = split(output);
|
TokenList tokens = split(output);
|
||||||
|
|
||||||
for (auto it = tokens.begin(); it != tokens.end(); ++it)
|
for (auto it = tokens.begin(); it != tokens.end(); ++it)
|
||||||
|
@ -131,19 +107,6 @@ static void shell_eval(std::vector<String>& params,
|
||||||
params.push_back(output.substr(it->first,
|
params.push_back(output.substr(it->first,
|
||||||
it->second - it->first));
|
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,
|
void CommandManager::execute(const CommandParameters& params,
|
||||||
|
|
|
@ -12,6 +12,8 @@ namespace Kakoune
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
typedef boost::regex_iterator<BufferIterator> RegexIterator;
|
||||||
|
|
||||||
void colorize_regex_range(DisplayBuffer& display_buffer,
|
void colorize_regex_range(DisplayBuffer& display_buffer,
|
||||||
const BufferIterator& range_begin,
|
const BufferIterator& range_begin,
|
||||||
const BufferIterator& range_end,
|
const BufferIterator& range_end,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "window.hh"
|
#include "window.hh"
|
||||||
#include "buffer.hh"
|
#include "buffer.hh"
|
||||||
#include "file.hh"
|
#include "file.hh"
|
||||||
|
#include "shell_manager.hh"
|
||||||
#include "command_manager.hh"
|
#include "command_manager.hh"
|
||||||
#include "buffer_manager.hh"
|
#include "buffer_manager.hh"
|
||||||
#include "register_manager.hh"
|
#include "register_manager.hh"
|
||||||
|
@ -929,6 +930,7 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
NCurses::init(prompt_func, get_key_func);
|
NCurses::init(prompt_func, get_key_func);
|
||||||
|
|
||||||
|
ShellManager shell_manager;
|
||||||
CommandManager command_manager;
|
CommandManager command_manager;
|
||||||
BufferManager buffer_manager;
|
BufferManager buffer_manager;
|
||||||
RegisterManager register_manager;
|
RegisterManager register_manager;
|
||||||
|
@ -939,6 +941,11 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
run_unit_tests();
|
run_unit_tests();
|
||||||
|
|
||||||
|
shell_manager.register_env_var("bufname",
|
||||||
|
[](const Context& context)
|
||||||
|
{ return context.buffer().name(); });
|
||||||
|
|
||||||
|
|
||||||
command_manager.register_commands({ "e", "edit" }, edit<false>,
|
command_manager.register_commands({ "e", "edit" }, edit<false>,
|
||||||
CommandManager::None,
|
CommandManager::None,
|
||||||
PerArgumentCommandCompleter({ complete_filename }));
|
PerArgumentCommandCompleter({ complete_filename }));
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef boost::regex_iterator<BufferIterator> RegexIterator;
|
|
||||||
typedef boost::basic_regex<Character> Regex;
|
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>
|
template<bool punctuation_is_word>
|
||||||
SelectionAndCaptures select_to_next_word(const Selection& selection)
|
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