mirror of https://gitlab.com/cppit/jucipp
15 changed files with 218 additions and 25 deletions
@ -0,0 +1,55 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "config.h" |
||||||
|
#include "menu.h" |
||||||
|
#include "python_interpreter.h" |
||||||
|
#include "python_module.h" |
||||||
|
#include <pybind11/embed.h> |
||||||
|
#include <pybind11/functional.h> |
||||||
|
|
||||||
|
class __attribute__((visibility("default"))) |
||||||
|
Plugins { |
||||||
|
public: |
||||||
|
Plugins() : jucipp_module("Jucipp", Module::init_jucipp_module) { |
||||||
|
auto &config = Config::get(); |
||||||
|
config.load(); |
||||||
|
auto sys = py::module::import("sys"); |
||||||
|
sys.attr("path").cast<py::list>().append(config.plugins.path); |
||||||
|
// sys.attr("excepthook") = py::cpp_function([](py::object type, py::object value, py::object traceback) {
|
||||||
|
// Terminal::get().print("const std::string &message\n");
|
||||||
|
// });
|
||||||
|
} |
||||||
|
void load() { |
||||||
|
boost::filesystem::directory_iterator end_it; |
||||||
|
for(boost::filesystem::directory_iterator it(Config::get().plugins.path); it != end_it; it++) { |
||||||
|
auto module_name = it->path().stem().string(); |
||||||
|
if(module_name.empty()) |
||||||
|
continue; |
||||||
|
const auto is_directory = boost::filesystem::is_directory(it->path()); |
||||||
|
const auto has_py_extension = it->path().extension() == ".py"; |
||||||
|
const auto is_pycache = module_name == "__pycache__"; |
||||||
|
if((is_directory && !is_pycache) || has_py_extension) { |
||||||
|
try { |
||||||
|
auto module = interpreter.add_module(module_name); |
||||||
|
if (module) { |
||||||
|
Terminal::get().print("Reloading plugin ´" + module_name + "´\n"); |
||||||
|
interpreter.reload_module(module); |
||||||
|
} else { |
||||||
|
Terminal::get().print("Loading plugin ´" + module_name + "´\n"); |
||||||
|
py::module::import(module_name.c_str());
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
catch(py::error_already_set &error) { |
||||||
|
Terminal::get().print("Error loading plugin `" + module_name + "`:\n" + error.what() + "\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
if(interpreter.error()) |
||||||
|
std::cerr << py::error_already_set().what() << std::endl; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
py::detail::embedded_module jucipp_module; |
||||||
|
Python::Interpreter interpreter; |
||||||
|
}; |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
#pragma once |
||||||
|
#include <pybind11/pybind11.h> |
||||||
|
namespace py = pybind11; |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
#include "python_interpreter.h" |
||||||
|
|
||||||
|
pybind11::module Python::Interpreter::add_module(const std::string &module_name) { |
||||||
|
return pybind11::reinterpret_borrow<pybind11::module>(PyImport_AddModule(module_name.c_str())); |
||||||
|
} |
||||||
|
|
||||||
|
pybind11::object Python::Interpreter::error() { |
||||||
|
return pybind11::reinterpret_borrow<pybind11::object>(PyErr_Occurred()); |
||||||
|
} |
||||||
|
|
||||||
|
pybind11::module Python::Interpreter::reload_module(pybind11::module &module) { |
||||||
|
auto reload = pybind11::reinterpret_steal<pybind11::module>(PyImport_ReloadModule(module.ptr())); |
||||||
|
if(!reload) { |
||||||
|
throw pybind11::error_already_set(); |
||||||
|
} |
||||||
|
return reload; |
||||||
|
} |
||||||
|
|
||||||
|
#include <pybind11/embed.h> |
||||||
|
#include <iostream> |
||||||
|
|
||||||
|
Python::Interpreter::~Interpreter() { |
||||||
|
if (error()){ |
||||||
|
std::cout << py::error_already_set().what() << std::endl; |
||||||
|
} |
||||||
|
py::finalize_interpreter(); |
||||||
|
} |
||||||
|
|
||||||
|
Python::Interpreter::Interpreter() { |
||||||
|
py::initialize_interpreter(); |
||||||
|
} |
||||||
@ -0,0 +1,13 @@ |
|||||||
|
#pragma once |
||||||
|
#include "python_bind.h" |
||||||
|
|
||||||
|
namespace Python { |
||||||
|
class Interpreter { |
||||||
|
public: |
||||||
|
pybind11::module static add_module(const std::string &module_name); |
||||||
|
pybind11::module static reload_module(pybind11::module &module); |
||||||
|
pybind11::object static error(); |
||||||
|
~Interpreter(); |
||||||
|
Interpreter(); |
||||||
|
}; |
||||||
|
}; // namespace Python
|
||||||
@ -0,0 +1,62 @@ |
|||||||
|
#pragma once |
||||||
|
#include "python_bind.h" |
||||||
|
#include "terminal.h" |
||||||
|
#include <boost/filesystem.hpp> |
||||||
|
#include <pybind11/stl.h> |
||||||
|
|
||||||
|
namespace pybind11 { |
||||||
|
namespace detail { |
||||||
|
template <> |
||||||
|
struct type_caster<boost::filesystem::path> { |
||||||
|
public: |
||||||
|
PYBIND11_TYPE_CASTER(boost::filesystem::path, _("str")); |
||||||
|
bool load(handle src, bool) { |
||||||
|
const std::string path = pybind11::str(src); |
||||||
|
value = path; |
||||||
|
return !PyErr_Occurred(); |
||||||
|
} |
||||||
|
|
||||||
|
static handle cast(boost::filesystem::path src, return_value_policy, handle) { |
||||||
|
return pybind11::str(src.string()); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Module { |
||||||
|
static void init_terminal_module(pybind11::module &api) { |
||||||
|
py::class_<Terminal, std::unique_ptr<Terminal, py::nodelete>>(api, "Terminal") |
||||||
|
.def(py::init([]() { return &(Terminal::get()); })) |
||||||
|
.def("process", (int (Terminal::*)(const std::string &, const boost::filesystem::path &, bool)) & Terminal::process, |
||||||
|
py::arg("command"), |
||||||
|
py::arg("path") = "", |
||||||
|
py::arg("use_pipes") = false) |
||||||
|
.def("async_process", (void (Terminal::*)(const std::string &, const boost::filesystem::path &, const std::function<void(int)> &, bool)) & Terminal::async_process, |
||||||
|
py::arg("command"), |
||||||
|
py::arg("path") = "", |
||||||
|
py::arg("callback") = nullptr, |
||||||
|
py::arg("quiet") = false) |
||||||
|
.def("kill_last_async_process", &Terminal::kill_last_async_process, |
||||||
|
py::arg("force") = false) |
||||||
|
.def("kill_async_processes", &Terminal::kill_async_processes, |
||||||
|
py::arg("force") = false) |
||||||
|
.def("print", &Terminal::print, |
||||||
|
py::arg("message"), |
||||||
|
py::arg("bold") = false) |
||||||
|
.def("async_print", (void (Terminal::*)(const std::string &, bool)) & Terminal::async_print, |
||||||
|
py::arg("message"), |
||||||
|
py::arg("bold") = false) |
||||||
|
.def("async_print", (void (Terminal::*)(size_t, const std::string &)) & Terminal::async_print, |
||||||
|
py::arg("line_nr"), |
||||||
|
py::arg("message")) |
||||||
|
.def("configure", &Terminal::configure) |
||||||
|
.def("clear", &Terminal::clear); |
||||||
|
}; |
||||||
|
|
||||||
|
public: |
||||||
|
static auto init_jucipp_module() { |
||||||
|
auto api = py::module("Jucipp", "API"); |
||||||
|
Module::init_terminal_module(api); |
||||||
|
return api.ptr(); |
||||||
|
}; |
||||||
|
}; |
||||||
Loading…
Reference in new issue