diff --git a/.appveyor.yml b/.appveyor.yml index d370363..6dd147e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,7 +12,7 @@ cache: before_build: - git submodule update --init --recursive # - C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syyuu" - - C:\msys64\usr\bin\bash -lc "pacman --noconfirm --needed -S make mingw-w64-x86_64-{cmake,toolchain,clang,gtkmm3,gtksourceviewmm3,boost,aspell,aspell-en,libgit2,universal-ctags-git,libffi}" + - C:\msys64\usr\bin\bash -lc "pacman --noconfirm --needed -S make mingw-w64-x86_64-{cmake,toolchain,clang,gtkmm3,gtksourceviewmm3,boost,aspell,aspell-en,libgit2,universal-ctags-git,libffi,pygobject-devel}" build_script: - C:\msys64\usr\bin\bash -lc "cd $APPVEYOR_BUILD_FOLDER && mkdir build && cd build && cmake -G\"MSYS Makefiles\" -DCMAKE_INSTALL_PREFIX=/mingw64 -DBUILD_TESTING=1 .. && make -j$(nproc) && make test" diff --git a/.gitmodules b/.gitmodules index a963aaa..b67fd67 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/libclangmm"] path = lib/libclangmm url = https://gitlab.com/cppit/libclangmm +[submodule "lib/pybind11"] + path = lib/pybind11 + url = https://github.com/pybind/pybind11 diff --git a/CMakeLists.txt b/CMakeLists.txt index 56ae6fe..7d725d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ include(CPack) set(CMAKE_CXX_STANDARD 14) -add_compile_options(-pthread -Wall -Wextra -Wno-unused-parameter -Wno-deprecated-declarations) +add_compile_options(-pthread -Wall -Wextra -Wno-unused-parameter -Wno-deprecated-declarations -fvisibility=hidden) add_definitions(-DJUCI_VERSION="${JUCI_VERSION}") if(CMAKE_BUILD_TYPE STREQUAL "") add_compile_options(-O3) @@ -78,13 +78,69 @@ option(LIBCLANG_PATH "Use custom path for libclang") option(LIBLLDB_PATH "Use custom path for liblldb") option(FLATPAK_SANDBOX "Runs from within a flatpak sandbox") +if(${CMAKE_VERSION} VERSION_GREATER 3.11.4) + if (${CMAKE_HOST_WIN32}) + if("$ENV{APPVEYOR}" STREQUAL "True") + set(MINGW_PATH "C:/msys64/mingw64") + else() + set(MINGW_PATH "$ENV{MSYSTEM_PREFIX}") + endif() + set(MINGW_PYTHON_VERSION 3.7) + set(MINGW_LIBRARY_DIR "${MINGW_PATH}/lib") + set(MINGW_INCLUDE_DIR "${MINGW_PATH}/include") + find_file(Python3_LIBRARIES "libpython${MINGW_PYTHON_VERSION}m.dll.a" HINTS ${MINGW_LIBRARY_DIR} NO_DEFAULT_PATH) + find_path(Python3_INCLUDE_DIRS "Python.h" HINTS "${MINGW_INCLUDE_DIR}/python${MINGW_PYTHON_VERSION}m" NO_DEFAULT_PATH) + if (EXISTS ${Python3_LIBRARIES} AND EXISTS ${Python3_INCLUDE_DIRS}) + set(Python3_FOUND True) + set(Python3_LIBRARY_DIRS ${MINGW_LIBRARY_DIR}) + set(Python3_VERSION_MAJOR 3) + set(Python3_VERSION_MINOR 7) + endif() + else() + find_package(Python3 COMPONENTS Development) + endif() +else() + find_package(PythonLibs 3) + message(${PYTHONLIBS_VERSION_STRING}) +endif() + +if(${Python3_FOUND}) + if(${CMAKE_HOST_WIN32}) + set(PYTHON_MODULE_EXTENSION True) + endif() + set(PYTHONLIBS_FOUND ${Python3_FOUND}) + set(PYTHON_LIBRARIES ${Python3_LIBRARIES}) + set(PYTHON_INCLUDE_DIRS ${Python3_INCLUDE_DIRS}) + set(PYTHON_LIBRARY_DIR ${Python3_LIBRARY_DIRS}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}) +endif() + +include(FindPkgConfig) + +set(PYGOBJECT_FOUND False) + +if(${PYTHONLIBS_FOUND}) + add_subdirectory(lib/pybind11) + pkg_check_modules(PYGOBJECT pygobject-3.0) + if("${PYGOBJECT_FOUND}" STREQUAL "") + set(PYGOBJECT_FOUND False) + endif() +endif() + +if(${PYGOBJECT_FOUND}) + add_definitions(-DPYTHON_HOME_DIR=L"${PYTHON_LIBRARY_DIR}") +endif() + +set(BUILD_TESTING_SAVED ${BUILD_TESTING}) +set(BUILD_TESTING OFF CACHE BOOL "Disable sub-project tests" FORCE) +set(BUILD_TESTING ${BUILD_TESTING_SAVED} CACHE BOOL "Set to previous value" FORCE) + if(POLICY CMP0167) cmake_policy(SET CMP0167 NEW) endif() + find_package(Boost 1.54 COMPONENTS REQUIRED filesystem serialization) find_package(ASPELL REQUIRED) -include(FindPkgConfig) pkg_check_modules(GTKMM gtkmm-3.0 REQUIRED) pkg_check_modules(GTKSVMM gtksourceviewmm-3.0) if(NOT GTKSVMM_FOUND) @@ -155,6 +211,9 @@ include_directories( ${LIBCLANG_INCLUDE_DIRS} ${ASPELL_INCLUDE_DIR} ${LIBGIT2_INCLUDE_DIRS} + ${PYTHON_INCLUDE_DIRS} + ${PYGOBJECT_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR}/lib/pybind11/include ${CMAKE_SOURCE_DIR}/lib/json/include ) diff --git a/docs/install.md b/docs/install.md index f560acd..db8f9e9 100644 --- a/docs/install.md +++ b/docs/install.md @@ -207,7 +207,7 @@ make install Install dependencies (replace `x86_64` with `i686` for 32-bit MSYS2 installs): ```sh -pacman -S git mingw-w64-x86_64-cmake make mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-gtkmm3 mingw-w64-x86_64-gtksourceviewmm3 mingw-w64-x86_64-boost mingw-w64-x86_64-aspell mingw-w64-x86_64-aspell-en mingw-w64-x86_64-libgit2 mingw-w64-x86_64-universal-ctags-git +pacman -S git make mingw-w64-x86_64-{cmake,toolchain,clang,gtkmm3,gtksourceviewmm3,boost,aspell,aspell-en,libgit2,universal-ctags-git,pygobject-devel} ``` Note that juCi++ must be built and run in a MinGW Shell (for instance MinGW-w64 Win64 Shell). diff --git a/docs/plugins.md b/docs/plugins.md new file mode 100644 index 0000000..58d6ffc --- /dev/null +++ b/docs/plugins.md @@ -0,0 +1,14 @@ +# Plugins + +## Getting started + +Plugins are stored in .juci/plugins + +### Basic hello world +from Jucipp import Terminal + +print("Hello, world! From before the application is loaded") + +def init_hook(): + t = Terminal() + t.print("Hello, world! From after the application is started.\n") diff --git a/lib/pybind11 b/lib/pybind11 new file mode 160000 index 0000000..9a19306 --- /dev/null +++ b/lib/pybind11 @@ -0,0 +1 @@ +Subproject commit 9a19306fbf30642ca331d0ec88e7da54a96860f9 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 868462d..0ded628 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ set(JUCI_SHARED_FILES menu.cpp meson.cpp project_build.cpp + plugins.cc snippets.cpp source.cpp source_base.cpp @@ -24,9 +25,12 @@ set(JUCI_SHARED_FILES source_language_protocol.cpp source_spellcheck.cpp terminal.cpp + tiny_process_module.cpp tooltips.cpp usages_clang.cpp utility.cpp + python_module.cc + config_module.cc workers.cpp ) if(LIBLLDB_FOUND) @@ -54,14 +58,25 @@ set(JUCI_FILES notebook.cpp project.cpp selection_dialog.cpp + tooltips.cpp window.cpp + plugins.cc ) + if(APPLE) - list(APPEND JUCI_FILES window_macos.m) + list(APPEND JUCI_SOURCES window_macos.m) +endif() + +set(JUCI_TARGET_LIBRARIES + juci_shared +) + +if(${PYTHONLIBS_FOUND}) + list(APPEND JUCI_TARGET_LIBRARIES pybind11 ${PYTHON_LIBRARIES} ${PYGOBJECT_LIBRARIES}) endif() -add_executable(juci ${JUCI_FILES}) -target_link_libraries(juci juci_shared) +add_executable(juci ${JUCI_SOURCES}) +target_link_libraries(juci ${JUCI_TARGET_LIBRARIES}) if(APPLE) target_link_libraries(juci "-framework Foundation -framework AppKit") diff --git a/src/cmake.cpp b/src/cmake.cpp index caad5da..6fd1370 100644 --- a/src/cmake.cpp +++ b/src/cmake.cpp @@ -357,6 +357,23 @@ void CMake::parse_file(const std::string &src, std::map(api, "CMake") + .def(py::init()) + .def_readwrite("project_path", &CMake::project_path) + .def("update_default_build", &CMake::update_default_build, + py::arg("default_build_path"), + py::arg("force") = false) + .def("update_debug_build", &CMake::update_debug_build, + py::arg("debug_build_path"), + py::arg("force") = false) + .def("get_executable", &CMake::get_executable, + py::arg("build_path"), + py::arg("file_path")) + + ; +} + bool CMake::create_file_api_query(const boost::filesystem::path &build_path) { auto query_directory = build_path / ".cmake" / "api" / "v1" / "query" / "client-jucipp"; auto query_file = query_directory / "query.json"; diff --git a/src/cmake.hpp b/src/cmake.hpp index 3b15a3c..6c75e0f 100644 --- a/src/cmake.hpp +++ b/src/cmake.hpp @@ -4,16 +4,16 @@ #include #include #include +#include "python_bind.h" class CMake { public: CMake(const boost::filesystem::path &path); boost::filesystem::path project_path; - bool update_default_build(const boost::filesystem::path &default_build_path, bool force = false); bool update_debug_build(const boost::filesystem::path &debug_build_path, bool force = false); - boost::filesystem::path get_executable(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path); + static void init_module(py::module &api); private: std::vector paths; diff --git a/src/compile_commands.cpp b/src/compile_commands.cpp index 94a91e7..8b88856 100644 --- a/src/compile_commands.cpp +++ b/src/compile_commands.cpp @@ -1,6 +1,9 @@ #include "compile_commands.hpp" #include "clangmm.hpp" #include "config.hpp" +#include "python_type_casters.h" +#include +#include "terminal.hpp" #include "filesystem.hpp" #include "json.hpp" #include "utility.hpp" @@ -207,3 +210,27 @@ bool CompileCommands::is_source(const boost::filesystem::path &path) { else return false; } + +void CompileCommands::init_module(py::module &api) { + py::class_ compile_commands(api, "CompileCommands"); + py::class_(compile_commands, "Command") + .def_readwrite("directory", &CompileCommands::Command::directory) + .def_readwrite("parameters", &CompileCommands::Command::parameters) + .def_readwrite("file", &CompileCommands::Command::file) + .def("parameter_values", &CompileCommands::Command::parameter_values, + py::arg("parameter_name")) + + ; + compile_commands + .def(py::init()) + .def_readwrite("commands", &CompileCommands::commands) + .def_static("get_arguments", &CompileCommands::get_arguments, + py::arg("build_path"), + py::arg("file_path")) + .def_static("is_header", &CompileCommands::is_header, + py::arg("path")) + .def_static("is_source", &CompileCommands::is_source, + py::arg("path")) + + ; +} diff --git a/src/compile_commands.hpp b/src/compile_commands.hpp index deffd4e..48300f9 100644 --- a/src/compile_commands.hpp +++ b/src/compile_commands.hpp @@ -1,4 +1,5 @@ #pragma once +#include "python_bind.h" #include #include #include @@ -10,16 +11,14 @@ public: boost::filesystem::path directory; std::vector arguments; boost::filesystem::path file; - std::vector get_argument_values(const std::string &argument_name) const; }; CompileCommands(const boost::filesystem::path &build_path); std::vector commands; - /// Return arguments for the given file using libclangmm static std::vector get_arguments(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path); - static bool is_header(const boost::filesystem::path &path); static bool is_source(const boost::filesystem::path &path); + static void init_module(py::module &api); }; diff --git a/src/config.cpp b/src/config.cpp index 663864d..eb2030c 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -4,6 +4,7 @@ #include "terminal.hpp" #include "utility.hpp" #include +#include #include #include #include @@ -206,6 +207,11 @@ void Config::read(const JSON &cfg) { terminal.clear_on_run_command = terminal_json.boolean("clear_on_run_command", JSON::ParseOptions::accept_string); terminal.hide_entry_on_run_command = terminal_json.boolean("hide_entry_on_run_command", JSON::ParseOptions::accept_string); + auto plugins_path = cfg.get("plugins.path"); + boost::replace_all(plugins_path, "", home_juci_path.string()); + plugins.path = plugins_path; + plugins.enabled = cfg.get("plugins.enabled"); + auto log_json = cfg.object("log"); log.libclang = log_json.boolean("libclang", JSON::ParseOptions::accept_string); log.language_server = log_json.boolean("language_server", JSON::ParseOptions::accept_string); diff --git a/src/config.hpp b/src/config.hpp index ebc0e15..5200c6c 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -6,6 +6,7 @@ #include #include #include +#include "python_bind.h" class Config { public: @@ -118,6 +119,12 @@ public: bool language_server; }; + class Plugins { + public: + bool enabled; + std::string path; + }; + private: Config(); @@ -135,9 +142,11 @@ public: Project project; Source source; Log log; + Plugins plugins; boost::filesystem::path home_path; boost::filesystem::path home_juci_path; + static void init_module(py::module &api); private: /// Used to dispatch Terminal outputs after juCi++ GUI setup and configuration diff --git a/src/config_module.cc b/src/config_module.cc new file mode 100644 index 0000000..82d7b99 --- /dev/null +++ b/src/config_module.cc @@ -0,0 +1,116 @@ +#include "config.hpp" +#include "python_type_casters.h" +#include + +void Config::init_module(py::module &api) { + py::class_> config(api, "Config"); + + py::class_(config, "Menu") + .def(py::init()) + .def_readwrite("keys", &Config::Menu::keys) + + ; + py::class_(config, "Theme") + .def(py::init()) + .def_readwrite("name", &Config::Theme::name) + .def_readwrite("variant", &Config::Theme::variant) + .def_readwrite("font", &Config::Theme::font) + + ; + py::class_(config, "Terminal") + .def(py::init()) + .def_readwrite("history_size", &Config::Terminal::history_size) + .def_readwrite("font", &Config::Terminal::font) + + ; + py::class_ project(config, "Project"); + py::class_(project, "CMake") + .def(py::init()) + .def_readwrite("command", &Config::Project::CMake::command) + .def_readwrite("compile_command", &Config::Project::CMake::compile_command) + + ; + py::class_(project, "Meson") + .def(py::init()) + .def_readwrite("command", &Config::Project::Meson::command) + .def_readwrite("compile_command", &Config::Project::Meson::compile_command) + + ; + project + .def(py::init()) + .def_readwrite("default_build_path", &Config::Project::default_build_path) + .def_readwrite("debug_build_path", &Config::Project::debug_build_path) + .def_readwrite("cmake", &Config::Project::cmake) + .def_readwrite("meson", &Config::Project::meson) + .def_readwrite("save_on_compile_or_run", &Config::Project::save_on_compile_or_run) + // .def_readwrite("clear_terminal_on_compile", &Config::Project::clear_terminal_on_compile) + .def_readwrite("ctags_command", &Config::Project::ctags_command) + .def_readwrite("python_command", &Config::Project::python_command) + + ; + py::class_ source(config, "Source"); + py::class_(source, "DocumentationSearch") + .def(py::init()) + .def_readwrite("separator", &Config::Source::DocumentationSearch::separator) + .def_readwrite("queries", &Config::Source::DocumentationSearch::queries) + + ; + source + .def(py::init()) + .def_readwrite("style", &Config::Source::style) + .def_readwrite("font", &Config::Source::font) + .def_readwrite("spellcheck_language", &Config::Source::spellcheck_language) + .def_readwrite("cleanup_whitespace_characters", &Config::Source::cleanup_whitespace_characters) + .def_readwrite("show_whitespace_characters", &Config::Source::show_whitespace_characters) + .def_readwrite("format_style_on_save", &Config::Source::format_style_on_save) + .def_readwrite("format_style_on_save_if_style_file_found", &Config::Source::format_style_on_save_if_style_file_found) + .def_readwrite("smart_inserts", &Config::Source::smart_inserts) + .def_readwrite("show_map", &Config::Source::show_map) + .def_readwrite("map_font_size", &Config::Source::map_font_size) + .def_readwrite("show_git_diff", &Config::Source::show_git_diff) + .def_readwrite("show_background_pattern", &Config::Source::show_background_pattern) + .def_readwrite("show_right_margin", &Config::Source::show_right_margin) + .def_readwrite("right_margin_position", &Config::Source::right_margin_position) + .def_readwrite("auto_tab_char_and_size", &Config::Source::auto_tab_char_and_size) + .def_readwrite("default_tab_char", &Config::Source::default_tab_char) + .def_readwrite("default_tab_size", &Config::Source::default_tab_size) + .def_readwrite("tab_indents_line", &Config::Source::tab_indents_line) + // .def_readwrite("wrap_lines", &Config::Source::wrap_lines) + .def_readwrite("highlight_current_line", &Config::Source::highlight_current_line) + .def_readwrite("show_line_numbers", &Config::Source::show_line_numbers) + .def_readwrite("enable_multiple_cursors", &Config::Source::enable_multiple_cursors) + .def_readwrite("auto_reload_changed_files", &Config::Source::auto_reload_changed_files) + .def_readwrite("clang_format_style", &Config::Source::clang_format_style) + .def_readwrite("clang_usages_threads", &Config::Source::clang_usages_threads) + .def_readwrite("documentation_searches", &Config::Source::documentation_searches) + + ; + + py::class_(config, "Log") + .def(py::init()) + .def_readwrite("libclang", &Config::Log::libclang) + .def_readwrite("language_server", &Config::Log::language_server) + + ; + py::class_(config, "Plugins") + .def(py::init()) + .def_readwrite("enabled", &Config::Plugins::enabled) + .def_readwrite("path", &Config::Plugins::path) + + ; + config + .def(py::init([]() { return &(Config::get()); })) + .def("load", &Config::load) + .def_readonly("version", &Config::version) + .def_readwrite("menu", &Config::menu) + .def_readwrite("theme", &Config::theme) + .def_readwrite("terminal", &Config::terminal) + .def_readwrite("project", &Config::project) + .def_readwrite("source", &Config::source) + .def_readwrite("log", &Config::log) + .def_readwrite("plugins", &Config::plugins) + .def_readwrite("home_path", &Config::home_path) + .def_readwrite("home_juci_path", &Config::home_juci_path) + + ; +} diff --git a/src/ctags.cpp b/src/ctags.cpp index f8288a8..a04bc8e 100644 --- a/src/ctags.cpp +++ b/src/ctags.cpp @@ -334,3 +334,39 @@ std::vector Ctags::get_locations(const boost::filesystem::path return best_locations; } + +void Ctags::init_module(py::module &api) { + py::class_ ctags(api, "Ctags"); + py::class_(api, "Location") + .def(py::init<>()) + .def_readwrite("file_path", &Ctags::Location::file_path) + .def_readwrite("line", &Ctags::Location::line) + .def_readwrite("index", &Ctags::Location::index) + .def_readwrite("symbol", &Ctags::Location::symbol) + .def_readwrite("scope", &Ctags::Location::scope) + .def_readwrite("source", &Ctags::Location::source) + .def_readwrite("kind", &Ctags::Location::kind) + .def("__bool__", &Ctags::Location::operator bool) + + ; + + ctags + .def(py::init(), + py::arg("path"), + py::arg("enable_scope"), + py::arg("enable_kind"), + py::arg("languages")) + .def("get_location", &Ctags::get_location, + py::arg("line"), + py::arg("add_markup"), + py::arg("symbol_ends_with_open_parenthesis")) + .def_static("get_locations", &Ctags::get_locations, + py::arg("path"), + py::arg("name"), + py::arg("type"), + py::arg("languages")) + .def_readwrite("project_path", &Ctags::project_path) + .def("__bool__", &Ctags::operator bool) + + ; +} diff --git a/src/ctags.hpp b/src/ctags.hpp index d989006..ec891d1 100644 --- a/src/ctags.hpp +++ b/src/ctags.hpp @@ -1,4 +1,5 @@ #pragma once +#include "python_bind.h" #include #include #include @@ -28,6 +29,7 @@ public: std::stringstream output; static std::vector get_locations(const boost::filesystem::path &path, const std::string &name, const std::string &type, const std::string &languages = {}); + static void init_module(py::module &api); private: bool enable_scope, enable_kind; diff --git a/src/debug_lldb.cpp b/src/debug_lldb.cpp index 1f835da..5b23a0f 100644 --- a/src/debug_lldb.cpp +++ b/src/debug_lldb.cpp @@ -6,6 +6,8 @@ #include "utility.hpp" #include #include +#include +#include extern char **environ; @@ -560,3 +562,73 @@ void Debug::LLDB::write(const std::string &buffer) { process->PutSTDIN(buffer.c_str(), buffer.size()); } } + +void Debug::LLDB::init_module(pybind11::module &api) { + py::class_> dbg(api, "LLDB"); + py::class_(dbg, "Frame") + .def_readwrite("index", &Debug::LLDB::Frame::index) + .def_readwrite("module_filename", &Debug::LLDB::Frame::module_filename) + .def_readwrite("file_path", &Debug::LLDB::Frame::file_path) + .def_readwrite("function_name", &Debug::LLDB::Frame::function_name) + .def_readwrite("line_nr", &Debug::LLDB::Frame::line_nr) + .def_readwrite("line_index", &Debug::LLDB::Frame::line_index) + + ; + py::class_(dbg, "Variable") + .def_readwrite("thread_index_id", &Debug::LLDB::Variable::thread_index_id) + .def_readwrite("frame_index", &Debug::LLDB::Variable::frame_index) + .def_readwrite("name", &Debug::LLDB::Variable::name) + .def_readwrite("value", &Debug::LLDB::Variable::value) + .def_readwrite("declaration_found", &Debug::LLDB::Variable::declaration_found) + .def_readwrite("file_path", &Debug::LLDB::Variable::file_path) + .def_readwrite("line_nr", &Debug::LLDB::Variable::line_nr) + .def_readwrite("line_index", &Debug::LLDB::Variable::line_index) + + ; + + // py::class_(api, "SBProcess"); + // .def_readwrite("on_start", &Debug::LLDB::on_start) + // .def_readwrite("on_event", &Debug::LLDB::on_event) + + dbg + .def(py::init([]() { return &(Debug::LLDB::get()); })) + .def_static("destroy", &Debug::LLDB::destroy) + .def_readwrite("on_exit", &Debug::LLDB::on_exit) + .def("continue_debug", &Debug::LLDB::continue_debug) + .def("stop", &Debug::LLDB::stop) + .def("kill", &Debug::LLDB::kill) + .def("step_over", &Debug::LLDB::step_over) + .def("step_into", &Debug::LLDB::step_into) + .def("step_out", &Debug::LLDB::step_out) + .def("is_invalid", &Debug::LLDB::is_invalid) + .def("is_stopped", &Debug::LLDB::is_stopped) + .def("is_running", &Debug::LLDB::is_running) + .def("get_backtrace", &Debug::LLDB::get_backtrace) + .def("get_variables", &Debug::LLDB::get_variables) + .def("start", &Debug::LLDB::start, + py::arg("command"), + py::arg("path") = "", + py::arg("breakpoints") = std::vector>(), + py::arg("startup_commands") = std::vector(), + py::arg("remote_host") = "") + .def("run_command", &Debug::LLDB::run_command, + py::arg("command")) + .def("select_frame", &Debug::LLDB::select_frame, + py::arg("frame_index"), + py::arg("thread_index_id") = 0) + .def("get_return_value", &Debug::LLDB::get_return_value, + py::arg("file_path"), + py::arg("line_nr"), + py::arg("line_index")) + .def("add_breakpoint", &Debug::LLDB::add_breakpoint, + py::arg("file_path"), + py::arg("line_nr")) + .def("remove_breakpoint", &Debug::LLDB::remove_breakpoint, + py::arg("file_path"), + py::arg("line_nr"), + py::arg("line_count")) + .def("write", &Debug::LLDB::write, + py::arg("buffer")) + + ; +} diff --git a/src/debug_lldb.hpp b/src/debug_lldb.hpp index 92c3e73..91a11ec 100644 --- a/src/debug_lldb.hpp +++ b/src/debug_lldb.hpp @@ -5,6 +5,7 @@ #include #include #include +#include "python_bind.h" namespace Debug { class LLDB { @@ -82,8 +83,8 @@ namespace Debug { void add_breakpoint(const boost::filesystem::path &file_path, int line_nr) EXCLUDES(mutex); void remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) EXCLUDES(mutex); - void write(const std::string &buffer) EXCLUDES(mutex); + static void init_module(py::module &api); private: std::tuple, std::string, std::vector> parse_run_arguments(const std::string &command); diff --git a/src/dialog.cpp b/src/dialog.cpp index ca29bc9..cc180dd 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -98,6 +98,23 @@ std::string Dialog::gtk_dialog(const boost::filesystem::path &path, const std::s return dialog.run() == Gtk::RESPONSE_OK ? dialog.get_filename() : ""; } +void Dialog::init_module(py::module &api) { + py::class_(api, "Dialog") + .def_static("open_folder", Dialog::open_folder, + py::arg("path")) + + .def_static("open_file", Dialog::open_file, + py::arg("path")) + .def_static("new_file", Dialog::new_file, + py::arg("path")) + .def_static("new_folder", Dialog::new_folder, + py::arg("path")) + .def_static("save_file_as", Dialog::save_file_as, + py::arg("path")) + + ; +} + std::string Dialog::open_folder(const boost::filesystem::path &path) { return gtk_dialog(path, "Open Folder", {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL), std::make_pair("Open", Gtk::RESPONSE_OK)}, diff --git a/src/dialog.hpp b/src/dialog.hpp index 5ea0230..954548b 100644 --- a/src/dialog.hpp +++ b/src/dialog.hpp @@ -1,4 +1,5 @@ #pragma once +#include "python_bind.h" #include #include #include @@ -29,4 +30,5 @@ public: static std::string new_file(const boost::filesystem::path &path); static std::string new_folder(const boost::filesystem::path &path); static std::string save_file_as(const boost::filesystem::path &path); + static void init_module(py::module &api); }; diff --git a/src/dispatcher.cpp b/src/dispatcher.cpp index 1e1b555..5274389 100644 --- a/src/dispatcher.cpp +++ b/src/dispatcher.cpp @@ -40,3 +40,12 @@ void Dispatcher::reset() { functions.clear(); connect(); } + +void Dispatcher::init_module(py::module &api) { + py::class_(api, "Dispatcher") + .def(py::init()) + .def("disconnect", &Dispatcher::disconnect) + .def("post", &Dispatcher::post &>) + + ; +} diff --git a/src/dispatcher.hpp b/src/dispatcher.hpp index fe8981c..38f1ac6 100644 --- a/src/dispatcher.hpp +++ b/src/dispatcher.hpp @@ -1,5 +1,6 @@ #pragma once #include "mutex.hpp" +#include "python_bind.h" #include #include #include @@ -32,4 +33,6 @@ public: /// Must be called from main GUI thread void reset(); + + static void init_module(py::module &api); }; diff --git a/src/documentation.cpp b/src/documentation.cpp index 808e3f2..27fea53 100644 --- a/src/documentation.cpp +++ b/src/documentation.cpp @@ -12711,3 +12711,8 @@ std::experimental::filesystem::status_known cpp/experimental/fs/status_known return std::string(); return "http://en.cppreference.com/w/" + it->second; } + +void Documentation::CppReference::init_module(py::module &api) { + py::class_(api, "CppReference") + .def("get_url", &CppReference::get_url); +} diff --git a/src/documentation.hpp b/src/documentation.hpp index ceec3a2..078aa3f 100644 --- a/src/documentation.hpp +++ b/src/documentation.hpp @@ -1,4 +1,5 @@ #pragma once +#include "python_bind.h" #include #include @@ -7,5 +8,6 @@ namespace Documentation { public: static std::vector get_headers(const std::string &symbol) noexcept; static std::string get_url(const std::string &symbol) noexcept; + static void init_module(py::module &api); }; } // namespace Documentation diff --git a/src/files.hpp b/src/files.hpp new file mode 100644 index 0000000..0c325ea --- /dev/null +++ b/src/files.hpp @@ -0,0 +1,438 @@ +#pragma once +#include + +/// If you add or remove nodes from the default_config_file, increase the juci +/// version number (JUCI_VERSION) in ../CMakeLists.txt to automatically apply +/// the changes to user's ~/.juci/config/config.json files +const std::string default_config_file = R"RAW({ + "version": ")RAW" + std::string(JUCI_VERSION) + R"RAW(", + "gtk_theme": { + "name_comment": "Use \"\" for default theme, At least these two exist on all systems: Adwaita, Raleigh", + "name": "", + "variant_comment": "Use \"\" for default variant, and \"dark\" for dark theme variant. Note that not all themes support dark variant, but for instance Adwaita does", + "variant": "", + "font_comment": "Set to override theme font, for instance: \"Arial 12\"", + "font": "" + }, + "source": { + "style_comment": "Use \"\" for default style, and for instance juci-dark or juci-dark-blue together with dark gtk_theme variant. Styles from normal gtksourceview install: classic, cobalt, kate, oblivion, solarized-dark, solarized-light, tango", + "style": "juci-light", + "font_comment": "Use \"\" for default font, and for instance \"Monospace 12\" to also set size",)RAW" +#ifdef __APPLE__ + R"RAW( + "font": "Menlo",)RAW" +#else +#ifdef _WIN32 + R"RAW( + "font": "Consolas",)RAW" +#else + R"RAW( + "font": "Monospace",)RAW" +#endif +#endif + R"RAW( + "cleanup_whitespace_characters_comment": "Remove trailing whitespace characters on save, and add trailing newline if missing", + "cleanup_whitespace_characters": false, + "show_whitespace_characters_comment": "Determines what kind of whitespaces should be drawn. Use comma-separated list of: space, tab, newline, nbsp, leading, text, trailing or all", + "show_whitespace_characters": "", + "format_style_on_save_comment": "Performs style format on save if supported on language in buffer", + "format_style_on_save": false, + "format_style_on_save_if_style_file_found_comment": "Format style if format file is found, even if format_style_on_save is false", + "format_style_on_save_if_style_file_found": true, + "smart_brackets_comment": "If smart_inserts is enabled, this option is automatically enabled. When inserting an already closed bracket, the cursor might instead be moved, avoiding the need of arrow keys after autocomplete", + "smart_brackets": true, + "smart_inserts_comment": "When for instance inserting (, () gets inserted. Applies to: (), [], \", '. Also enables pressing ; inside an expression before a final ) to insert ; at the end of line, and deletions of empty insertions", + "smart_inserts": true, + "show_map": true, + "map_font_size": "1", + "show_git_diff": true, + "show_background_pattern": true, + "show_right_margin": false, + "right_margin_position": 80, + "spellcheck_language_comment": "Use \"\" to set language from your locale settings", + "spellcheck_language": "en_US", + "auto_tab_char_and_size_comment": "Use false to always use default tab char and size", + "auto_tab_char_and_size": true, + "default_tab_char_comment": "Use \"\t\" for regular tab", + "default_tab_char": " ", + "default_tab_size": 2, + "tab_indents_line": true, + "word_wrap_comment": "Specify language ids that should enable word wrap, for instance: chdr, c, cpphdr, cpp, js, python, or all to enable word wrap for all languages", + "word_wrap": "markdown, latex", + "highlight_current_line": true, + "show_line_numbers": true, + "enable_multiple_cursors": false, + "auto_reload_changed_files": true, + "search_for_selection": true, + "clang_format_style_comment": "IndentWidth, AccessModifierOffset and UseTab are set automatically. See http://clang.llvm.org/docs/ClangFormatStyleOptions.html", + "clang_format_style": "ColumnLimit: 0, NamespaceIndentation: All", + "clang_tidy_enable_comment": "Enable clang-tidy in new C/C++ buffers", + "clang_tidy_enable": false, + "clang_tidy_checks_comment": "In new C/C++ buffers, these checks are appended to the value of 'Checks' in the .clang-tidy file, if any", + "clang_tidy_checks": "", + "clang_usages_threads_comment": "The number of threads used in finding usages in unparsed files. -1 corresponds to the number of cores available, and 0 disables the search", + "clang_usages_threads": -1, + "clang_detailed_preprocessing_record_comment": "Set to true to, at the cost of increased resource use, include all macro definitions and instantiations when parsing new C/C++ buffers. You should reopen buffers and delete build/.usages_clang after changing this option.", + "clang_detailed_preprocessing_record": false, + "debug_place_cursor_at_stop": false + }, + "terminal": { + "history_size": 10000, + "font_comment": "Use \"\" to use source.font with slightly smaller size", + "font": "", + "clear_on_compile": true, + "clear_on_run_command": false + }, + "project": { + "default_build_path_comment": "Use to insert the project top level directory name", + "default_build_path": "./build", + "debug_build_path_comment": "Use to insert the project top level directory name, and to insert your default_build_path setting.", + "debug_build_path": "/debug", + "cmake": {)RAW" +#ifdef _WIN32 + R"RAW( + "command": "cmake -G\"MSYS Makefiles\"",)RAW" +#else + R"RAW( + "command": "cmake",)RAW" +#endif + R"RAW( + "compile_command": "cmake --build ." + }, + "meson": { + "command": "meson", + "compile_command": "ninja" + }, + "default_build_management_system_comment": "Select which build management system to use when creating a new C or C++ project, for instance \"cmake\" or \"meson\"", + "default_build_management_system": "cmake", + "save_on_compile_or_run": true,)RAW" +#ifdef JUCI_USE_UCTAGS + R"RAW( + "ctags_command": "uctags",)RAW" +#else + R"RAW( + "ctags_command": "ctags",)RAW" +#endif + R"RAW( + "grep_command": "grep", + "cargo_command": "cargo", + "python_command": "python -u", + "markdown_command": "grip -b" + }, + "keybindings": { + "preferences": "comma", + "snippets": "", + "quit": "q", + "file_new_file": "n", + "file_new_folder": "n", + "file_open_file": "o", + "file_open_folder": "o", + "file_reload_file": "", + "file_save": "s", + "file_save_as": "s", + "file_close_file": "w", + "file_close_folder": "", + "file_close_project": "", + "file_print": "", + "edit_undo": "z", + "edit_redo": "z", + "edit_cut": "x", + "edit_cut_lines": "x", + "edit_copy": "c", + "edit_copy_lines": "c", + "edit_paste": "v", + "edit_extend_selection": "a", + "edit_shrink_selection": "a", + "edit_show_or_hide": "", + "edit_find": "f", + "source_spellcheck": "", + "source_spellcheck_clear": "", + "source_spellcheck_next_error": "e", + "source_git_next_diff": "k", + "source_git_show_diff": "k", + "source_indentation_set_buffer_tab": "", + "source_indentation_auto_indent_buffer": "i", + "source_goto_line": "g", + "source_center_cursor": "l", + "source_cursor_history_back": "Left", + "source_cursor_history_forward": "Right", + "source_show_completion_comment" : "Add completion keybinding to disable interactive autocompletion", + "source_show_completion" : "", + "source_find_file": "p", + "source_find_symbol": "f", + "source_find_pattern": "f", + "source_comments_toggle": "slash", + "source_comments_add_documentation": "slash", + "source_find_documentation": "d", + "source_goto_declaration": "d", + "source_goto_type_declaration": "d", + "source_goto_implementation": "i", + "source_goto_usage": "u", + "source_goto_method": "m", + "source_rename": "r", + "source_implement_method": "m", + "source_goto_next_diagnostic": "e", + "source_apply_fix_its": "space", + "project_set_run_arguments": "", + "project_compile_and_run": "Return", + "project_compile": "Return", + "project_run_command": "Return", + "project_kill_last_running": "Escape", + "project_force_kill_last_running": "Escape", + "debug_set_run_arguments": "", + "debug_start_continue": "y", + "debug_stop": "y", + "debug_kill": "k", + "debug_step_over": "j", + "debug_step_into": "t", + "debug_step_out": "t", + "debug_backtrace": "j", + "debug_show_variables": "b", + "debug_run_command": "Return", + "debug_toggle_breakpoint": "b", + "debug_show_breakpoints": "b", + "debug_goto_stop": "l",)RAW" +#ifdef __linux + R"RAW( + "window_next_tab": "Tab", + "window_previous_tab": "Tab",)RAW" +#else + R"RAW( + "window_next_tab": "Right", + "window_previous_tab": "Left",)RAW" +#endif + R"RAW( + "window_goto_tab": "", + "window_toggle_split": "", + "window_split_source_buffer": "",)RAW" +#ifdef __APPLE__ + R"RAW( + "window_toggle_full_screen": "f",)RAW" +#else + R"RAW( + "window_toggle_full_screen": "F11",)RAW" +#endif + R"RAW( + "window_toggle_tabs": "", + "window_toggle_zen_mode": "", + "window_clear_terminal": "" + }, + "documentation_searches": { + "clang": { + "separator": "::", + "queries": { + "@empty": "https://www.google.com/search?q=c%2B%2B+", + "std": "https://www.google.com/search?q=site:http://www.cplusplus.com/reference/+", + "boost": "https://www.google.com/search?q=site:http://www.boost.org/doc/libs/1_59_0/+", + "Gtk": "https://www.google.com/search?q=site:https://developer.gnome.org/gtkmm/stable/+", + "@any": "https://www.google.com/search?q=" + } + } + }, + "log": { + "libclang_comment": "Outputs diagnostics for new C/C++ buffers", + "libclang": false, + "language_server": false + }, + "plugins": { + "enabled": true, + "path_comment": "Directory where plugins are loaded from.", + "path": "/plugins" + } +} +)RAW"; + +const std::string juci_light_style = R"RAW( + + + juCi++ team + <_description>Default juCi++ style + + + + + + + + + + + + + + +