diff --git a/.github/workflows/sync_cling.yml b/.github/workflows/sync_cling.yml index e28a0664f7ebc..9740b662203b9 100644 --- a/.github/workflows/sync_cling.yml +++ b/.github/workflows/sync_cling.yml @@ -1,17 +1,13 @@ name: Sync Cling repo on: - push: - branches: - - 'master' + pull_request: paths: - 'interpreter/cling/**' - - 'core/textinput/src/textinput/**' - workflow_dispatch: - + - '.github/workflows/utilities/sync_cling.py' jobs: sync-cling-history: - if: github.repository_owner == 'root-project' + if: github.repository_owner == 'devajithvs' runs-on: ubuntu-latest steps: - name: Checkout ROOT @@ -23,8 +19,8 @@ jobs: - name: Checkout Cling uses: actions/checkout@v4 with: - repository: root-project/cling - token: ${{ secrets.CLING_GIT_TOKEN }} + repository: devajithvs/cling + token: ${{ secrets.CLING_GIT_TOKEN_TESTING }} path: cling fetch-depth: 32768 diff --git a/.github/workflows/utilities/sync_cling.py b/.github/workflows/utilities/sync_cling.py index cf45dbafe6910..9941eff13c79f 100755 --- a/.github/workflows/utilities/sync_cling.py +++ b/.github/workflows/utilities/sync_cling.py @@ -16,8 +16,6 @@ ROOT_REPO_DIR_NAME = 'root' INTERP_DIR_NAME = 'interpreter/cling' DEST_INTERP_DIR_NAME = '' -TEXTINPUT_DIR_NAME = 'core/textinput/src/textinput' -DEST_TEXTINPUT_DIR_NAME='lib/UserInterface/textinput' def printError(msg): print(f'*** Error: {msg}') @@ -87,26 +85,21 @@ def getHashes(repoDirName, startingHash, dirInRepoName=''): hashes = [line.split(' ', 1)[0] for line in out.split('\n')] return hashes -def createPatches(rootHashes, interpHashes, textinputHashes): +def createPatches(rootHashes, interpHashes): patches = [] # We'll need a few sets to quickly check what to do with ROOT hashes interpHashesSet = set(interpHashes) - textInputHashesSet = set(textinputHashes) - allHashesSet = interpHashesSet | textInputHashesSet # We filter the ROOT hashes that we do not want to sync - rootHashesToSync = list(filter(lambda hash: hash in allHashesSet, rootHashes)) + rootHashesToSync = list(filter(lambda hash: hash in interpHashesSet, rootHashes)) # We loop on ROOT hashes to sync, from oldest to newest - # to return a list of triples [label, hash, patchAsSting], where label allows us - # to disinguish between textinput and interpreter patches and hash is there - # for debugging purposes. - # One commit can be visible in both directories, ergo 2 patches per hash are possible. + # to return a list of triples [dirInRepo, hash, patchAsSting], where dirInRepo is the + # directory and hash is there for debugging purposes. for rootHashtoSync in reversed(rootHashesToSync): keys = [] if rootHashtoSync in interpHashesSet: keys.append(INTERP_DIR_NAME) - if rootHashtoSync in textInputHashesSet: keys.append(TEXTINPUT_DIR_NAME) for key in keys: patchAsStr = execCommand(f"git format-patch -1 {rootHashtoSync} {key} --stdout", ROOT_REPO_DIR_NAME) patches.append([key, rootHashtoSync, patchAsStr]) @@ -115,7 +108,7 @@ def createPatches(rootHashes, interpHashes, textinputHashes): def applyPatches(patches): for dirInRepo, hash, patchAsStr in patches: ignorePathLevel = dirInRepo.count('/') + 2 - destDirName = DEST_INTERP_DIR_NAME if dirInRepo == INTERP_DIR_NAME else DEST_TEXTINPUT_DIR_NAME + destDirName = DEST_INTERP_DIR_NAME directoryOption = f'--directory {destDirName}' if destDirName else '' printInfo(f'Applying {hash} restricted to {dirInRepo} to repository {CLING_REPO_DIR_NAME}') execCommand(f'git am -p {ignorePathLevel} {directoryOption}', CLING_REPO_DIR_NAME, patchAsStr) @@ -158,18 +151,17 @@ def principal(): # to commits in the directories we are interested in for the sync rootHashes = getHashes(ROOT_REPO_DIR_NAME, startingRootHash) interpHashes = getHashes(ROOT_REPO_DIR_NAME, startingRootHash, INTERP_DIR_NAME) - textinputHashes = getHashes(ROOT_REPO_DIR_NAME, startingRootHash, TEXTINPUT_DIR_NAME) # If we have no commits to sync, we quit. - if not interpHashes and not textinputHashes: + if not interpHashes: # nothing to do, we have no commits to sync printInfo('No commit to sync. Exiting now.') return 0 - printInfo(f'We found:\n - {len(interpHashes)} patches from the directory {INTERP_DIR_NAME}\n - {len(textinputHashes)} patches from the directory {TEXTINPUT_DIR_NAME}') + printInfo(f'We found:\n - {len(interpHashes)} patches from the directory {INTERP_DIR_NAME}') # We now create the patches we want to apply to the cling repo - patches = createPatches(rootHashes, interpHashes, textinputHashes) + patches = createPatches(rootHashes, interpHashes) # We now apply the patches if not patches: @@ -185,6 +177,10 @@ def principal(): applyPatches(patches) + # Remove text-input directory, revert this after the run. + execCommand(f'git rm lib/UserInterface/textinput -r', CLING_REPO_DIR_NAME) + execCommand(f'git commit -m "Remove `textinput` directory"', CLING_REPO_DIR_NAME) + syncTagAndPush(rootSyncTag, rootHashes[0]) if __name__ == '__main__': diff --git a/interpreter/cling/lib/CMakeLists.txt b/interpreter/cling/lib/CMakeLists.txt index 00c22081a6ab5..eb29252742387 100644 --- a/interpreter/cling/lib/CMakeLists.txt +++ b/interpreter/cling/lib/CMakeLists.txt @@ -8,8 +8,7 @@ add_subdirectory(Interpreter) add_subdirectory(MetaProcessor) -if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/UserInterface/textinput OR - CLING_INCLUDE_TESTS) +if(CLING_INCLUDE_TESTS) add_subdirectory(UserInterface) endif() add_subdirectory(Utils) diff --git a/interpreter/cling/lib/UserInterface/CMakeLists.txt b/interpreter/cling/lib/UserInterface/CMakeLists.txt index 1f9115f0a94c2..5fdaf0cc92865 100644 --- a/interpreter/cling/lib/UserInterface/CMakeLists.txt +++ b/interpreter/cling/lib/UserInterface/CMakeLists.txt @@ -7,40 +7,12 @@ #------------------------------------------------------------------------------ set( LLVM_LINK_COMPONENTS + LineEditor support ) -if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/textinput) - set(TEXTINPUTSRC ${CMAKE_SOURCE_DIR}/core/textinput/src/) - include_directories(${TEXTINPUTSRC}) -else() - # For cling, install textinput *.h in include/cling/UserInterface/textinput. - install(DIRECTORY ${TEXTINPUTSRC}textinput - DESTINATION include/cling/UserInterface - FILES_MATCHING - PATTERN "CMakeFiles" EXCLUDE - PATTERN "*.cpp" EXCLUDE - PATTERN "doc" EXCLUDE - PATTERN "*.h" - ) -endif() - add_cling_library(clingUserInterface UserInterface.cpp - ${TEXTINPUTSRC}textinput/Editor.cpp - ${TEXTINPUTSRC}textinput/History.cpp - ${TEXTINPUTSRC}textinput/KeyBinding.cpp - ${TEXTINPUTSRC}textinput/Range.cpp - ${TEXTINPUTSRC}textinput/SignalHandler.cpp - ${TEXTINPUTSRC}textinput/StreamReader.cpp - ${TEXTINPUTSRC}textinput/StreamReaderUnix.cpp - ${TEXTINPUTSRC}textinput/StreamReaderWin.cpp - ${TEXTINPUTSRC}textinput/TerminalConfigUnix.cpp - ${TEXTINPUTSRC}textinput/TerminalDisplay.cpp - ${TEXTINPUTSRC}textinput/TerminalDisplayUnix.cpp - ${TEXTINPUTSRC}textinput/TerminalDisplayWin.cpp - ${TEXTINPUTSRC}textinput/TextInput.cpp - ${TEXTINPUTSRC}textinput/TextInputContext.cpp LINK_LIBS clingMetaProcessor diff --git a/interpreter/cling/lib/UserInterface/UserInterface.cpp b/interpreter/cling/lib/UserInterface/UserInterface.cpp index 92cda1591adb0..2cc39db7ac02a 100644 --- a/interpreter/cling/lib/UserInterface/UserInterface.cpp +++ b/interpreter/cling/lib/UserInterface/UserInterface.cpp @@ -12,13 +12,9 @@ #include "cling/Interpreter/Exception.h" #include "cling/MetaProcessor/MetaProcessor.h" #include "cling/Utils/Output.h" -#include "textinput/Callbacks.h" -#include "textinput/History.h" -#include "textinput/StreamReader.h" -#include "textinput/TerminalDisplay.h" -#include "textinput/TextInput.h" #include "llvm/ADT/SmallString.h" +#include "llvm/LineEditor/LineEditor.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" @@ -30,44 +26,40 @@ namespace { /// to code complete through its own textinput mechanism which is part of the /// UserInterface. /// - class UITabCompletion : public textinput::TabCompletion { - const cling::Interpreter& m_ParentInterpreter; - - public: - UITabCompletion(const cling::Interpreter& Parent) : - m_ParentInterpreter(Parent) {} - ~UITabCompletion() {} - - bool Complete(textinput::Text& Line /*in+out*/, - size_t& Cursor /*in+out*/, - textinput::EditorRange& R /*out*/, - std::vector& Completions /*out*/) override { - m_ParentInterpreter.codeComplete(Line.GetText(), Cursor, Completions); - return true; - } - }; - ///\brief Delays ~TextInput until after ~StreamReader and ~TerminalDisplay - /// - class TextInputHolder { - textinput::StreamReader* m_Reader; - textinput::TerminalDisplay* m_Display; - textinput::TextInput m_Input; - - public: - TextInputHolder(llvm::SmallString<512>& Hist) - : m_Reader(textinput::StreamReader::Create()), - m_Display(textinput::TerminalDisplay::Create()), - m_Input(*m_Reader, *m_Display, Hist.empty() ? 0 : Hist.c_str()) {} - - ~TextInputHolder() { - delete m_Reader; - delete m_Display; - } + struct ClingListCompleter { + const cling::Interpreter& MainInterp; + + ClingListCompleter(const cling::Interpreter& Interp) : MainInterp(Interp) {} - textinput::TextInput* operator -> () { return &m_Input; } + std::vector operator()(llvm::StringRef Buffer, + size_t Pos) const; + std::vector + operator()(llvm::StringRef Buffer, size_t Pos, llvm::Error& ErrRes) const; }; + std::vector + ClingListCompleter::operator()(llvm::StringRef Buffer, size_t Pos) const { + auto Err = llvm::Error::success(); + auto res = (*this)(Buffer, Pos, Err); + if (Err) + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); + return res; + } + + std::vector + ClingListCompleter::operator()(llvm::StringRef Buffer, size_t Pos, + llvm::Error& ErrRes) const { + std::vector Comps; + std::vector Results; + + MainInterp.codeComplete(Buffer.str(), Pos, Results); + for (auto c : Results) { + Comps.push_back(llvm::LineEditor::Completion(c, c)); + } + return Comps; + } + llvm::SmallString<512> GetHistoryFilePath() { if (std::getenv("CLING_NOHISTORY")) { return {}; @@ -123,42 +115,27 @@ namespace cling { } auto histfilePath{GetHistoryFilePath()}; - - const auto Completion = - std::make_unique(m_MetaProcessor->getInterpreter()); - TextInputHolder TI(histfilePath); - - TI->SetCompletion(Completion.get()); + llvm::LineEditor LE("cling", histfilePath); + std::string Input; + std::string Prompt("[cling]$ "); if (const char* HistSizeEnvvar = std::getenv("CLING_HISTSIZE")) { const size_t HistSize = std::strtoull(HistSizeEnvvar, nullptr, 0); // std::strtoull() returns 0 if the parsing fails. // zero HistSize will disable history logging to file. - // refer to textinput::History::AppendToFile() - TI->SetHistoryMaxDepth(HistSize); - TI->SetHistoryPruneLength( - static_cast(textinput::History::kPruneLengthDefault)); + LE.setHistorySize(HistSize); } - bool Done = false; - std::string Line; - std::string Prompt("[cling]$ "); + LE.setPrompt(Prompt); - while (!Done) { + LE.setListCompleter(ClingListCompleter(m_MetaProcessor->getInterpreter())); + while (std::optional Line = LE.readLine()) { try { - m_MetaProcessor->getOuts().flush(); - { - MetaProcessor::MaybeRedirectOutputRAII RAII(*m_MetaProcessor); - TI->SetPrompt(Prompt.c_str()); - Done = TI->ReadInput() == textinput::TextInput::kRREOF; - TI->TakeInput(Line); - if (Done && Line.empty()) - break; - } + m_MetaProcessor->getOuts().flush(); // Do we need this now? cling::Interpreter::CompilationResult compRes; - const int indent = m_MetaProcessor->process(Line, compRes); + const int indent = m_MetaProcessor->process(*Line, compRes); // Quit requested? if (indent < 0) @@ -186,8 +163,10 @@ namespace cling { catch(...) { cling::errs() << "Exception occurred. Recovering...\n"; } + + LE.setPrompt(Prompt); } - m_MetaProcessor->getOuts().flush(); + m_MetaProcessor->getOuts().flush(); // Do we need this now? } void UserInterface::PrintLogo() { diff --git a/interpreter/cling/test/CodeGeneration/Statics.C b/interpreter/cling/test/CodeGeneration/Statics.C index 67b0ad82d60ad..04aadf5ad0067 100644 --- a/interpreter/cling/test/CodeGeneration/Statics.C +++ b/interpreter/cling/test/CodeGeneration/Statics.C @@ -37,5 +37,5 @@ inst02(); // expected-no-diagnostics .q -// CHECK-NEXT: TERD::~TERD::inst02 +// CHECK: TERD::~TERD::inst02 // CHECK-NEXT: TERD::~TERD::inst01 diff --git a/interpreter/cling/test/CodeGeneration/const.C b/interpreter/cling/test/CodeGeneration/const.C index 8fe1397be30d8..a69b6f6dd65d5 100644 --- a/interpreter/cling/test/CodeGeneration/const.C +++ b/interpreter/cling/test/CodeGeneration/const.C @@ -33,5 +33,5 @@ a.val a.getVal() // CHECK-NEXT: (int) 1 -// CHECK-NEXT: ~A(1), this = [[PTR]] +// CHECK: ~A(1), this = [[PTR]] // CHECK-NOT: ~A diff --git a/interpreter/cling/test/CodeUnloading/AtExit.C b/interpreter/cling/test/CodeUnloading/AtExit.C index cc391b166d6b2..ddaaa5a59cbae 100644 --- a/interpreter/cling/test/CodeUnloading/AtExit.C +++ b/interpreter/cling/test/CodeUnloading/AtExit.C @@ -115,7 +115,7 @@ struct ShutdownRecursion { // Reversed registration order -// CHECK-NEXT: ~ShutdownRecursion +// CHECK: ~ShutdownRecursion // CHECK-NEXT: ShutdownRecursion2 // CHECK-NEXT: ShutdownRecursion1 // CHECK-NEXT: ShutdownRecursion0 diff --git a/interpreter/cling/test/Driver/Inputs/cling_history b/interpreter/cling/test/Driver/Inputs/cling_history index eed01cab128cb..0d96520e1ca20 100644 --- a/interpreter/cling/test/Driver/Inputs/cling_history +++ b/interpreter/cling/test/Driver/Inputs/cling_history @@ -1,8 +1,9 @@ -/* -comment - * */ -static const int i = 37; -}; -// another comment -using std::cout; -std::cout << "test\n"; +_HiStOrY_V2_ +/*\012 +\011\011comment\012 +\040*\040*/\012 +\011static\040const\040int\040i\040=\04037;\012 +};\012 +//\040another\040comment\012 +using\040std::cout;\012 +std::cout\040<<\040"test\134n";\012 diff --git a/interpreter/cling/test/Interfaces/evaluate.C b/interpreter/cling/test/Interfaces/evaluate.C index ea9930481e916..d476206154025 100644 --- a/interpreter/cling/test/Interfaces/evaluate.C +++ b/interpreter/cling/test/Interfaces/evaluate.C @@ -224,7 +224,8 @@ gCling->evaluate("arrV", V); // Destruct the variables with static storage: // Destruct arrV: -//CHECK-NEXT: MADE{7}:dtor +// The error `err_verify_no_directives` will add a new line here. +//CHECK: MADE{7}:dtor //CHECK-NEXT: MADE{6}:dtor //CHECK-NEXT: MADE{5}:dtor diff --git a/interpreter/cling/test/Prompt/Continuation.C b/interpreter/cling/test/Prompt/Continuation.C index 43e6db9500b59..0bfdcc50bcf21 100644 --- a/interpreter/cling/test/Prompt/Continuation.C +++ b/interpreter/cling/test/Prompt/Continuation.C @@ -72,7 +72,7 @@ CLING_MULTILINE_MACRO("DOWHILE"); #define CLING_MULTILINE_TRAILING_SPACE \ "Trailing Space " \ "And A Tab" \ - " End" // expected-warning@1 {{backslash and newline separated by space}} // expected-warning@2 {{backslash and newline separated by space}} + " End" // expected-warning@1 {{backslash and newline separated by space}} // expected-warning@2 {{backslash and newline separated by space}} // expected-warning@3 {{backslash and newline separated by space}} CLING_MULTILINE_TRAILING_SPACE // CHECK-NEXT: (const char[29]) "Trailing Space And A Tab End" diff --git a/interpreter/cling/test/Prompt/DontWrap.C b/interpreter/cling/test/Prompt/DontWrap.C index a5d93787d768a..9ee94587e0426 100644 --- a/interpreter/cling/test/Prompt/DontWrap.C +++ b/interpreter/cling/test/Prompt/DontWrap.C @@ -350,6 +350,6 @@ N::X funcReturnsXint() { funcReturnsXint() // CHECK-NEXT: (N::X) @0x{{.*}} -// CHECK-NEXT: Nested::~Nested(80) +// CHECK: Nested::~Nested(80) // expected-no-diagnostics