summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command_manager.cc41
-rw-r--r--src/highlighters.cc2
-rw-r--r--src/main.cc7
-rw-r--r--src/regex.hh1
-rw-r--r--src/selectors.cc2
-rw-r--r--src/shell_manager.cc85
-rw-r--r--src/shell_manager.hh32
7 files changed, 130 insertions, 40 deletions
diff --git a/src/command_manager.cc b/src/command_manager.cc
index 606c2513..800b3a04 100644
--- a/src/command_manager.cc
+++ b/src/command_manager.cc
@@ -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)
@@ -131,19 +107,6 @@ static void shell_eval(std::vector<String>& params,
params.push_back(output.substr(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,
diff --git a/src/highlighters.cc b/src/highlighters.cc
index 7becf1d0..45cc95e5 100644
--- a/src/highlighters.cc
+++ b/src/highlighters.cc
@@ -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,
diff --git a/src/main.cc b/src/main.cc
index 0fa6d879..0af2824e 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -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 }));
diff --git a/src/regex.hh b/src/regex.hh
index 0ad93a1b..6099a57c 100644
--- a/src/regex.hh
+++ b/src/regex.hh
@@ -8,7 +8,6 @@
namespace Kakoune
{
-typedef boost::regex_iterator<BufferIterator> RegexIterator;
typedef boost::basic_regex<Character> Regex;
}
diff --git a/src/selectors.cc b/src/selectors.cc
index c327edfd..044f7bb9 100644
--- a/src/selectors.cc
+++ b/src/selectors.cc
@@ -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)
{
diff --git a/src/shell_manager.cc b/src/shell_manager.cc
new file mode 100644
index 00000000..f750ab05
--- /dev/null
+++ b/src/shell_manager.cc
@@ -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);
+}
+
+}
diff --git a/src/shell_manager.hh b/src/shell_manager.hh
new file mode 100644
index 00000000..b67136aa
--- /dev/null
+++ b/src/shell_manager.hh
@@ -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
+