From 4d74ebbc6a0695dc4def98ba89cceeb136298a3a Mon Sep 17 00:00:00 2001 From: ioanaif Date: Thu, 6 Jul 2023 12:18:44 +0200 Subject: [PATCH] Make rendering the type help in the pager work. --- CMakeLists.txt | 6 +- etc/xeus-cpp/tags.d/stl.json | 4 + etc/xeus-cpp/tags.d/xtensor.json | 4 + src/xinspect.hpp | 336 ++++++++++++----------------- src/xinterpreter.cpp | 354 ++++++------------------------- 5 files changed, 209 insertions(+), 495 deletions(-) create mode 100644 etc/xeus-cpp/tags.d/stl.json create mode 100644 etc/xeus-cpp/tags.d/xtensor.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 14b31854..1e9912ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,7 +136,7 @@ include(CheckCXXCompilerFlag) string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) -set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib; ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") +#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib; ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") macro(xeus_cpp_set_common_options target_name) if (MSVC) @@ -161,7 +161,7 @@ macro(xeus_cpp_set_common_options target_name) if (APPLE) set_target_properties(${target_name} PROPERTIES - MACOSX_RPATH ON + MACOSX_RPATH OFF ) else () set_target_properties(${target_name} PROPERTIES @@ -171,7 +171,7 @@ macro(xeus_cpp_set_common_options target_name) endif () set_target_properties(${target_name} PROPERTIES - INSTALL_RPATH_USE_LINK_PATH TRUE + INSTALL_RPATH_USE_LINK_PATH FALSE ) endmacro() diff --git a/etc/xeus-cpp/tags.d/stl.json b/etc/xeus-cpp/tags.d/stl.json new file mode 100644 index 00000000..6eedd965 --- /dev/null +++ b/etc/xeus-cpp/tags.d/stl.json @@ -0,0 +1,4 @@ +{ + "url": "https://en.cppreference.com/w/", + "tagfile": "cppreference-doxygen-web.tag" +} \ No newline at end of file diff --git a/etc/xeus-cpp/tags.d/xtensor.json b/etc/xeus-cpp/tags.d/xtensor.json new file mode 100644 index 00000000..f3b4c1db --- /dev/null +++ b/etc/xeus-cpp/tags.d/xtensor.json @@ -0,0 +1,4 @@ +{ + "url": "https://xtensor.readthedocs.io/en/latest/", + "tagfile": "xtensor.tag" +} \ No newline at end of file diff --git a/src/xinspect.hpp b/src/xinspect.hpp index e39b0060..64231bb3 100644 --- a/src/xinspect.hpp +++ b/src/xinspect.hpp @@ -1,4 +1,4 @@ -*/*********************************************************************************** +/*********************************************************************************** * Copyright (c) 2023, xeus-cpp contributors * * Copyright (c) 2023, Johan Mabille, Loic Gouarin, Sylvain Corlay, Wolf Vollprecht * * * @@ -6,7 +6,6 @@ * * * The full license is in the file LICENSE, distributed with this software. * ************************************************************************************/ - #ifndef XEUS_CPP_INSPECT_HPP #define XEUS_CPP_INSPECT_HPP @@ -15,10 +14,6 @@ #include -#include "cling/Interpreter/Interpreter.h" -#include "cling/Interpreter/Value.h" -#include "cling/Utils/Output.h" - #include #include @@ -84,62 +79,23 @@ namespace xcpp } }; - /* std::string find_type(const std::string& expression, cling::Interpreter& interpreter) - { - cling::Value result; - std::string typeString; - - // add typeinfo in include files in order to use typeid - std::string code = "#include "; - auto compilation_result = interpreter.process(code.c_str(), &result); - - // try to find the typename of the class - code = "typeid(" + expression + ").name();"; - - // Temporarily dismissing all std::cerr and std::cout resulting from `interpreter.process` - compilation_result = interpreter.process(code.c_str(), &result); - { - auto cout_strbuf = std::cout.rdbuf(); - auto cerr_strbuf = std::cerr.rdbuf(); - auto null = xnull(); - std::cout.rdbuf(&null); - std::cerr.rdbuf(&null); - - compilation_result = interpreter.process(code.c_str(), &result); + std::string find_type(const std::string& expression, clang::Interpreter& interpreter) + { + auto PTU = interpreter.Parse(expression + ";"); + if (llvm::Error Err = PTU.takeError()) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); + return ""; + } - std::cout.rdbuf(cout_strbuf); - std::cerr.rdbuf(cerr_strbuf); - } + clang::Decl *D = *PTU->TUPart->decls_begin(); + if (!llvm::isa(D)) + return ""; - if (compilation_result == cling::Interpreter::kSuccess) - { - // we found the typeid - std::string valueString; - { - llvm::raw_string_ostream os(valueString); - result.print(os); - } + clang::Expr *E = llvm::cast(llvm::cast(D)->getStmt()); - // search the typename in the output between "" - std::regex re_typename("\\\"(.*)\\\""); - std::smatch typename_; - std::regex_search(valueString, typename_, re_typename); - // set in valueString the typename given by typeid - valueString = typename_.str(1); - // we need demangling in order to have its string representation - valueString = demangle(valueString); - - re_typename = "(\\w*(?:\\:{2}?\\w*)*)"; - std::regex_search(valueString, typename_, re_typename); - if (!typename_.str(1).empty()) - { - typeString = typename_[1]; - } - } - - return typeString; - } - */ + clang::QualType QT = E->getType(); + return QT.getAsString(); + } static nl::json read_tagconfs(const char* path) { @@ -171,178 +127,152 @@ namespace xcpp return result; } - void inspect(const std::string& code, nl::json& kernel_res, cling::Interpreter& interpreter) + std::pair is_inspect_request(const std::string code, std::regex re) { - /* - std::string tagconf_dir = XCPP_TAGCONFS_DIR; - std::string tagfiles_dir = XCPP_TAGFILES_DIR; + std::smatch inspect; + if (std::regex_search(code, inspect, re)){ + return std::make_pair(true, inspect); + } + return std::make_pair(false, inspect); + + } - nl::json tagconfs = read_tagconfs(tagconf_dir.c_str()); + void inspect(const std::string& code, nl::json& kernel_res, clang::Interpreter& interpreter) + { + std::string tagconf_dir = XCPP_TAGCONFS_DIR; + std::string tagfiles_dir = XCPP_TAGFILES_DIR; - std::vector check{"class", "struct", "function"}; + nl::json tagconfs = read_tagconfs(tagconf_dir.c_str()); - std::string url, tagfile; + std::vector check{"class", "struct", "function"}; - std::regex re_expression(R"((((?:\w*(?:\:{2}|\<.*\>|\(.*\)|\[.*\])?)\.?)*))"); - std::smatch inspect; - std::regex_search(code, inspect, re_expression); + std::string url, tagfile; - std::string inspect_result; + std::regex re_expression(R"((((?:\w*(?:\:{2}|\<.*\>|\(.*\)|\[.*\])?)\.?)*))"); - std::smatch method; - std::string to_inspect = inspect[1]; + std::smatch inspect = is_inspect_request(code, re_expression).second; - // Method or variable of class found (xxxx.yyyy) - if (std::regex_search(to_inspect, method, std::regex(R"((.*)\.(\w*)$)"))) - { - std::string typename_ = find_type(method[1], interpreter); + std::string inspect_result; + + std::smatch method; + std::string to_inspect = inspect[1]; + + // Method or variable of class found (xxxx.yyyy) + if (std::regex_search(to_inspect, method, std::regex(R"((.*)\.(\w*)$)"))) + { + std::string typename_ = find_type(method[1], interpreter); - if (!typename_.empty()) + if (!typename_.empty()) + { + for (nl::json::const_iterator it = tagconfs.cbegin(); it != tagconfs.cend(); ++it) + { + url = it->at("url"); + tagfile = it->at("tagfile"); + std::string filename = tagfiles_dir + "/" + tagfile; + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(filename.c_str()); + class_member_predicate predicate{typename_, "function", method[2]}; + auto node = doc.find_node(predicate); + if (!node.empty()) { - for (nl::json::const_iterator it = tagconfs.cbegin(); it != tagconfs.cend(); ++it) - { - url = it->at("url"); - tagfile = it->at("tagfile"); - std::string filename = tagfiles_dir + "/" + tagfile; - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); - class_member_predicate predicate{typename_, "function", method[2]}; - auto node = doc.find_node(predicate); - if (!node.empty()) - { - inspect_result = url + predicate.get_filename(node); - } - } + inspect_result = url + predicate.get_filename(node); } } - else + } + } + else + { + std::string find_string; + + // check if we try to find the documentation of a namespace + // if yes, don't try to find the type using typeid + std::regex is_namespace(R"(\w+(\:{2}\w+)+)"); + std::smatch namespace_match; + if (std::regex_match(to_inspect, namespace_match, is_namespace)) + { + find_string = to_inspect; + } + else + { + std::string typename_ = find_type(to_inspect, interpreter); + find_string = (typename_.empty()) ? to_inspect : typename_; + } + + for (nl::json::const_iterator it = tagconfs.cbegin(); it != tagconfs.cend(); ++it) + { + url = it->at("url"); + tagfile = it->at("tagfile"); + std::string filename = tagfiles_dir + "/" + tagfile; + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(filename.c_str()); + for (auto c : check) { - std::string find_string; + node_predicate predicate{c, find_string}; + std::string node; - // check if we try to find the documentation of a namespace - // if yes, don't try to find the type using typeid - std::regex is_namespace(R"(\w+(\:{2}\w+)+)"); - std::smatch namespace_match; - if (std::regex_match(to_inspect, namespace_match, is_namespace)) + if (c == "class" || c == "struct") { - find_string = to_inspect; + node = doc.find_node(predicate).child("filename").child_value(); } else { - std::string typename_ = find_type(to_inspect, interpreter); - find_string = (typename_.empty()) ? to_inspect : typename_; + node = doc.find_node(predicate).child("anchorfile").child_value(); } - for (nl::json::const_iterator it = tagconfs.cbegin(); it != tagconfs.cend(); ++it) + if (!node.empty()) { - url = it->at("url"); - tagfile = it->at("tagfile"); - std::string filename = tagfiles_dir + "/" + tagfile; - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); - for (auto c : check) - { - node_predicate predicate{c, find_string}; - std::string node; - - if (c == "class" || c == "struct") - { - node = doc.find_node(predicate).child("filename").child_value(); - } - else - { - node = doc.find_node(predicate).child("anchorfile").child_value(); - } - - if (!node.empty()) - { - inspect_result = url + node; - } - } - } - } - - if (inspect_result.empty()) - { - std::cerr << "No documentation found for " << code << "\n"; - std::cout << std::flush; - kernel_res["found"] = false; - kernel_res["status"] = "error"; - kernel_res["ename"] = "No documentation found"; - kernel_res["evalue"] = ""; - kernel_res["traceback"] = nl::json::array(); - } - else - { - // Format html content. - std::string html_content = R"( - )"; - - // Note: Adding "?action=purge" suffix to force cppreference's - // Mediawiki to purge the HTTP cache. - - kernel_res["payload"] = nl::json::array(); - kernel_res["payload"][0] = nl::json::object({ - {"data", { - {"text/plain", inspect_result}, - {"text/html", html_content}} - }, - {"source", "page"}, - {"start", 0} - }); - kernel_res["user_expressions"] = nl::json::object(); - - std::cout << std::flush; - kernel_res["found"] = true; - kernel_res["status"] = "ok"; } - */ - } - - class xintrospection : public xpreamble - { - public: - - using xpreamble::pattern; - const std::string spattern = R"(^\?)"; - - xintrospection(cling::Interpreter& p) - : m_interpreter{p} - { - pattern = spattern; + } } - void apply(const std::string& code, nl::json& kernel_res) override + if (inspect_result.empty()) { - std::regex re(spattern + R"((.*))"); - std::smatch to_inspect; - std::regex_search(code, to_inspect, re); - inspect(to_inspect[1], kernel_res, m_interpreter); + std::cerr << "No documentation found for " << code << "\n"; + std::cout << std::flush; + kernel_res["found"] = false; + kernel_res["status"] = "error"; + kernel_res["ename"] = "No documentation found"; + kernel_res["evalue"] = ""; + kernel_res["traceback"] = nl::json::array(); } - - virtual xpreamble* clone() const override + else { - return new xintrospection(*this); + // Format html content. + std::string html_content = R"( + )"; + + // Note: Adding "?action=purge" suffix to force cppreference's + // Mediawiki to purge the HTTP cache. + + kernel_res["payload"] = nl::json::array(); + kernel_res["payload"][0] = nl::json::object( + {{"data", {{"text/plain", inspect_result}, {"text/html", html_content}}}, + {"source", "page"}, + {"start", 0}} + ); + kernel_res["user_expressions"] = nl::json::object(); + + std::cout << std::flush; + kernel_res["found"] = true; + kernel_res["status"] = "ok"; } - - private: - - cling::Interpreter& m_interpreter; - }; + } } #endif diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 918f3869..643fb235 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -10,7 +10,7 @@ #include "xeus-cpp/xinterpreter.hpp" #include "xinput.hpp" -// #include "xinspect.hpp" +#include "xinspect.hpp" // #include "xmagics/executable.hpp" // #include "xmagics/execution.hpp" #include "xmagics/os.hpp" @@ -62,54 +62,62 @@ auto DiagPrinter = std::make_unique(DiagnosticsOS, static bool process_code(clang::Interpreter& Interp, const std::string& code, llvm::raw_string_ostream& error_stream) { - auto PTU = Interp.Parse(code); - if (!PTU) - { - auto Err = PTU.takeError(); - error_stream << DiagnosticsOS.str(); - // avoid printing the "Parsing failed error" - // llvm::logAllUnhandledErrors(std::move(Err), error_stream, "error: "); + + if (code.substr(0, 1) == "?") + { + error_stream << " "; return true; } - if (PTU->TheModule) - { - llvm::Error ex = Interp.Execute(*PTU); - error_stream << DiagnosticsOS.str(); - if (code.substr(0, 3) == "int") + else { + auto PTU = Interp.Parse(code); + if (!PTU) + { + auto Err = PTU.takeError(); + error_stream << DiagnosticsOS.str(); + // avoid printing the "Parsing failed error" + // llvm::logAllUnhandledErrors(std::move(Err), error_stream, "error: "); + return true; + } + if (PTU->TheModule) { - for (clang::Decl* D : PTU->TUPart->decls()) + llvm::Error ex = Interp.Execute(*PTU); + error_stream << DiagnosticsOS.str(); + if (code.substr(0, 3) == "int") { - if (clang::VarDecl* VD = llvm::dyn_cast(D)) + for (clang::Decl* D : PTU->TUPart->decls()) { - auto Name = VD->getNameAsString(); - auto Addr = Interp.getSymbolAddress(clang::GlobalDecl(VD)); - if (!Addr) + if (clang::VarDecl* VD = llvm::dyn_cast(D)) { - llvm::logAllUnhandledErrors(std::move(Addr.takeError()), error_stream, "error: "); - return true; + auto Name = VD->getNameAsString(); + auto Addr = Interp.getSymbolAddress(clang::GlobalDecl(VD)); + if (!Addr) + { + llvm::logAllUnhandledErrors(std::move(Addr.takeError()), error_stream, "error: "); + return true; + } } } } - } - else if (code.substr(0, 16) == "std::vector") - { - for (clang::Decl* D : PTU->TUPart->decls()) + else if (code.substr(0, 16) == "std::vector") { - if (clang::VarDecl* VD = llvm::dyn_cast(D)) + for (clang::Decl* D : PTU->TUPart->decls()) { - auto Name = VD->getNameAsString(); - auto Addr = Interp.getSymbolAddress(clang::GlobalDecl(VD)); - if (!Addr) + if (clang::VarDecl* VD = llvm::dyn_cast(D)) { - llvm::logAllUnhandledErrors(std::move(Addr.takeError()), error_stream, "error: "); - return true; + auto Name = VD->getNameAsString(); + auto Addr = Interp.getSymbolAddress(clang::GlobalDecl(VD)); + if (!Addr) + { + llvm::logAllUnhandledErrors(std::move(Addr.takeError()), error_stream, "error: "); + return true; + } } } } - } - llvm::logAllUnhandledErrors(std::move(ex), error_stream, "error: "); - return false; + llvm::logAllUnhandledErrors(std::move(ex), error_stream, "error: "); + return false; + } } return false; } @@ -316,30 +324,38 @@ namespace xcpp // Scope guard performing the temporary redirection of input requests. auto input_guard = input_redirection(allow_stdin); - std::string error_message; llvm::raw_string_ostream error_stream(error_message); // Attempt normal evaluation + try - { + { std::string exp = R"(\w*(?:\:{2}|\<.*\>|\(.*\)|\[.*\])?)"; + std::regex re(R"((\w*(?:\:{2}|\<.*\>|\(.*\)|\[.*\])?)(\.?)*$)"); + auto inspect_request = is_inspect_request(code, re); + if (inspect_request.first) + { + inspect(inspect_request.second[0], kernel_res, *m_interpreter); + } + compilation_result = process_code(*m_interpreter, code, error_stream); + } catch (std::exception& e) { errorlevel = 1; - ename = "Standard Exception"; + ename = "Standard Exception :"; evalue = e.what(); } catch (...) { errorlevel = 1; - ename = "Error"; + ename = "Error :"; } - + if (compilation_result) { errorlevel = 1; - ename = "Error"; + ename = "Error :"; evalue = error_stream.str(); } @@ -366,7 +382,10 @@ namespace xcpp // // JupyterLab displays the "{ename}: {evalue}" if the traceback is // empty. - std::vector traceback({ename + ": " + evalue}); + if (evalue.size() < 4) { + ename = " "; + } + std::vector traceback({ename + evalue}); if (!silent) { publish_execution_error(ename, evalue, traceback); @@ -406,259 +425,15 @@ namespace xcpp ); } - struct node_predicate - { - std::string kind; - std::string child_value; - - bool operator()(pugi::xml_node node) const - { - return static_cast(node.attribute("kind").value()) == kind - && static_cast(node.child("name").child_value()) == child_value; - } - }; - - struct class_member_predicate - { - std::string class_name; - std::string kind; - std::string child_value; - - std::string get_filename(pugi::xml_node node) - { - for (pugi::xml_node child : node.children()) - { - if (static_cast(child.attribute("kind").value()) == kind - && static_cast(child.child("name").child_value()) == child_value) - { - return child.child("anchorfile").child_value(); - } - } - return ""; - } - - bool operator()(pugi::xml_node node) - { - auto parent = (static_cast(node.attribute("kind").value()) == "class" - || static_cast(node.attribute("kind").value()) == "struct") - && static_cast(node.child("name").child_value()) == class_name; - auto found = false; - if (parent) - { - for (pugi::xml_node child : node.children()) - { - if (static_cast(child.attribute("kind").value()) == kind - && static_cast(child.child("name").child_value()) == child_value) - { - found = true; - break; - } - } - } - return found; - } - }; - - std::string find_type(const std::string& expression, clang::Interpreter& interpreter) - { - printf("K\n"); - auto PTU = interpreter.Parse(expression + ";"); - printf("%s\n", expression.c_str()); - if (llvm::Error Err = PTU.takeError()) { - llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); - return ""; - } - - clang::Decl *D = *PTU->TUPart->decls_begin(); - if (!llvm::isa(D)) - return ""; - - clang::Expr *E = llvm::cast(llvm::cast(D)->getStmt()); - - clang::QualType QT = E->getType(); - return QT.getAsString(); - } - - static nl::json read_tagconfs(const char* path) - { - nl::json result = nl::json::array(); - DIR* directory = opendir(path); - if (directory == nullptr) - { - return result; - } - dirent* item = readdir(directory); - while (item != nullptr) - { - std::string extension = "json"; - if (item->d_type == DT_REG) - { - std::string fname = item->d_name; - - if (fname.find(extension, (fname.length() - extension.length())) != std::string::npos) - { - std::ifstream i(path + ('/' + fname)); - nl::json entry; - i >> entry; - result.emplace_back(std::move(entry)); - } - } - item = readdir(directory); - } - closedir(directory); - return result; - } - - void inspect(const std::string& code, nl::json& kernel_res, clang::Interpreter& interpreter) - { - std::string tagconf_dir = XCPP_TAGCONFS_DIR; - std::string tagfiles_dir = XCPP_TAGFILES_DIR; - - nl::json tagconfs = read_tagconfs(tagconf_dir.c_str()); - - std::vector check{"class", "struct", "function"}; - - std::string url, tagfile; - - std::regex re_expression(R"((((?:\w*(?:\:{2}|\<.*\>|\(.*\)|\[.*\])?)\.?)*))"); - std::smatch inspect; - std::regex_search(code, inspect, re_expression); - - std::string inspect_result; - - std::smatch method; - std::string to_inspect = inspect[1]; - - // Method or variable of class found (xxxx.yyyy) - if (std::regex_search(to_inspect, method, std::regex(R"((.*)\.(\w*)$)"))) - { - std::string typename_ = find_type(method[1], interpreter); - - if (!typename_.empty()) - { - for (nl::json::const_iterator it = tagconfs.cbegin(); it != tagconfs.cend(); ++it) - { - url = it->at("url"); - tagfile = it->at("tagfile"); - std::string filename = tagfiles_dir + "/" + tagfile; - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); - class_member_predicate predicate{typename_, "function", method[2]}; - auto node = doc.find_node(predicate); - if (!node.empty()) - { - inspect_result = url + predicate.get_filename(node); - } - } - } - } - else - { - std::string find_string; - - // check if we try to find the documentation of a namespace - // if yes, don't try to find the type using typeid - std::regex is_namespace(R"(\w+(\:{2}\w+)+)"); - std::smatch namespace_match; - if (std::regex_match(to_inspect, namespace_match, is_namespace)) - { - find_string = to_inspect; - } - else - { - std::string typename_ = find_type(to_inspect, interpreter); - find_string = (typename_.empty()) ? to_inspect : typename_; - } - - for (nl::json::const_iterator it = tagconfs.cbegin(); it != tagconfs.cend(); ++it) - { - url = it->at("url"); - tagfile = it->at("tagfile"); - std::string filename = tagfiles_dir + "/" + tagfile; - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); - for (auto c : check) - { - node_predicate predicate{c, find_string}; - std::string node; - - if (c == "class" || c == "struct") - { - node = doc.find_node(predicate).child("filename").child_value(); - } - else - { - node = doc.find_node(predicate).child("anchorfile").child_value(); - } - - if (!node.empty()) - { - inspect_result = url + node; - } - } - } - } - - if (inspect_result.empty()) - { - std::cerr << "No documentation found for " << code << "\n"; - std::cout << std::flush; - kernel_res["found"] = false; - kernel_res["status"] = "error"; - kernel_res["ename"] = "No documentation found"; - kernel_res["evalue"] = ""; - kernel_res["traceback"] = nl::json::array(); - } - else - { - // Format html content. - std::string html_content = R"( - )"; - - // Note: Adding "?action=purge" suffix to force cppreference's - // Mediawiki to purge the HTTP cache. - - kernel_res["payload"] = nl::json::array(); - kernel_res["payload"][0] = nl::json::object( - {{"data", {{"text/plain", inspect_result}, {"text/html", html_content}}}, - {"source", "page"}, - {"start", 0}} - ); - kernel_res["user_expressions"] = nl::json::object(); - - std::cout << std::flush; - kernel_res["found"] = true; - kernel_res["status"] = "ok"; - } - } - nl::json interpreter::inspect_request_impl(const std::string& code, int cursor_pos, int /*detail_level*/) { nl::json kernel_res; - - auto dummy = code.substr(0, cursor_pos); - // TODO: same pattern as in inspect function (keep only one) std::string exp = R"(\w*(?:\:{2}|\<.*\>|\(.*\)|\[.*\])?)"; - std::regex re_method{"(" + exp + R"(\.?)*$)"}; - std::smatch magic; - if (std::regex_search(dummy, magic, re_method)) + std::regex re(R"((\w*(?:\:{2}|\<.*\>|\(.*\)|\[.*\])?)(\.?)*$)"); + auto inspect_request = is_inspect_request(code.substr(0, cursor_pos), re); + if (inspect_request.first) { - inspect(magic[0], kernel_res, *m_interpreter); + inspect(inspect_request.second[0], kernel_res, *m_interpreter); } return kernel_res; } @@ -816,7 +591,6 @@ namespace xcpp void interpreter::init_preamble() { - // preamble_manager.register_preamble("introspection", new xintrospection(m_interpreter)); preamble_manager.register_preamble("magics", new xmagics_manager()); preamble_manager.register_preamble("shell", new xsystem()); } @@ -845,4 +619,6 @@ namespace xcpp } return res; } + + }