diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9e98f4f..f1e9092 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,4 +54,5 @@ add_qtc_plugin(QodeAssist
settings/CustomPromptSettings.hpp settings/CustomPromptSettings.cpp
settings/PresetPromptsSettings.hpp settings/PresetPromptsSettings.cpp
settings/SettingsUtils.hpp
+ core/ChangesManager.h core/ChangesManager.cpp
)
diff --git a/LLMClientInterface.cpp b/LLMClientInterface.cpp
index a473ac1..029a70c 100644
--- a/LLMClientInterface.cpp
+++ b/LLMClientInterface.cpp
@@ -29,6 +29,7 @@
#include "LLMProvidersManager.hpp"
#include "PromptTemplateManager.hpp"
#include "QodeAssistUtils.hpp"
+#include "core/ChangesManager.h"
#include "settings/ContextSettings.hpp"
#include "settings/GeneralSettings.hpp"
@@ -277,14 +278,19 @@ ContextData LLMClientInterface::prepareContext(const QJsonObject &request,
DocumentContextReader reader(widget->textDocument());
+ QString recentChanges = ChangesManager::instance().getRecentChangesContext(textDocument);
+
QString contextBefore = сontextBefore(widget, lineNumber, cursorPosition);
QString contextAfter = сontextAfter(widget, lineNumber, cursorPosition);
- QString instructions = QString("%1%2").arg(Settings::contextSettings().useSpecificInstructions()
- ? reader.getSpecificInstructions()
- : QString(),
- Settings::contextSettings().useFilePathInContext()
- ? reader.getLanguageAndFileInfo()
- : QString());
+ QString instructions
+ = QString("%1%2%3").arg(Settings::contextSettings().useSpecificInstructions()
+ ? reader.getSpecificInstructions()
+ : QString(),
+ Settings::contextSettings().useFilePathInContext()
+ ? reader.getLanguageAndFileInfo()
+ : QString(),
+ Settings::contextSettings().useProjectChangesCache() ? recentChanges
+ : QString());
return {QString("%1%2").arg(contextBefore, accumulatedCompletion), contextAfter, instructions};
}
diff --git a/QodeAssist.json.in b/QodeAssist.json.in
index 8e11076..d4cf82c 100644
--- a/QodeAssist.json.in
+++ b/QodeAssist.json.in
@@ -1,6 +1,6 @@
{
"Name" : "QodeAssist",
- "Version" : "0.1.1",
+ "Version" : "0.1.2",
"CompatVersion" : "${IDE_VERSION_COMPAT}",
"Vendor" : "Petr Mironychev",
"Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd",
diff --git a/QodeAssistClient.cpp b/QodeAssistClient.cpp
index d8593ec..f85056f 100644
--- a/QodeAssistClient.cpp
+++ b/QodeAssistClient.cpp
@@ -31,6 +31,8 @@
#include "LLMClientInterface.hpp"
#include "LLMSuggestion.hpp"
+#include "core/ChangesManager.h"
+#include "settings/ContextSettings.hpp"
#include "settings/GeneralSettings.hpp"
using namespace LanguageServerProtocol;
@@ -83,6 +85,13 @@ void QodeAssistClient::openDocument(TextEditor::TextDocument *document)
auto textEditor = BaseTextEditor::currentTextEditor();
if (!textEditor || textEditor->document() != document)
return;
+
+ if (Settings::contextSettings().useProjectChangesCache())
+ ChangesManager::instance().addChange(document,
+ position,
+ charsRemoved,
+ charsAdded);
+
TextEditorWidget *widget = textEditor->editorWidget();
if (widget->isReadOnly() || widget->multiTextCursor().hasMultipleCursors())
return;
diff --git a/QodeAssistConstants.hpp b/QodeAssistConstants.hpp
index 774bdca..8f51de7 100644
--- a/QodeAssistConstants.hpp
+++ b/QodeAssistConstants.hpp
@@ -59,6 +59,8 @@ const char API_KEY[] = "QodeAssist.apiKey";
const char USE_SPECIFIC_INSTRUCTIONS[] = "QodeAssist.useSpecificInstructions";
const char USE_FILE_PATH_IN_CONTEXT[] = "QodeAssist.useFilePathInContext";
const char CUSTOM_JSON_TEMPLATE[] = "QodeAssist.customJsonTemplate";
+const char USE_PROJECT_CHANGES_CACHE[] = "QodeAssist.useProjectChangesCache";
+const char MAX_CHANGES_CACHE_SIZE[] = "QodeAssist.maxChangesCacheSize";
const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions";
const char QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID[] = "QodeAssist.1GeneralSettingsPageId";
diff --git a/README.md b/README.md
index a0168c4..58bfac2 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,7 @@ If you've successfully used a model that's not listed here, please let us know b
- [x] Basic plugin with code autocomplete functionality
- [x] Improve and automate settings
- [ ] Add chat functionality
-- [ ] Sharing diff with model
+- [x] Sharing diff with model
- [ ] Sharing project source with model
- [ ] Support for more providers and models
diff --git a/core/ChangesManager.cpp b/core/ChangesManager.cpp
new file mode 100644
index 0000000..216465e
--- /dev/null
+++ b/core/ChangesManager.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 Petr Mironychev
+ *
+ * This file is part of QodeAssist.
+ *
+ * QodeAssist is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * QodeAssist is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with QodeAssist. If not, see .
+ */
+
+#include "ChangesManager.h"
+#include "QodeAssistUtils.hpp"
+#include "settings/ContextSettings.hpp"
+
+namespace QodeAssist {
+
+ChangesManager &ChangesManager::instance()
+{
+ static ChangesManager instance;
+ return instance;
+}
+
+ChangesManager::ChangesManager()
+ : QObject(nullptr)
+{
+}
+
+ChangesManager::~ChangesManager()
+{
+}
+
+void ChangesManager::addChange(TextEditor::TextDocument *document,
+ int position,
+ int charsRemoved,
+ int charsAdded)
+{
+ auto &documentQueue = m_documentChanges[document];
+
+ QTextBlock block = document->document()->findBlock(position);
+ int lineNumber = block.blockNumber();
+ QString lineContent = block.text();
+ QString fileName = document->filePath().fileName();
+
+ ChangeInfo change{fileName, lineNumber, lineContent};
+
+ auto it = std::find_if(documentQueue.begin(),
+ documentQueue.end(),
+ [lineNumber](const ChangeInfo &c) { return c.lineNumber == lineNumber; });
+
+ if (it != documentQueue.end()) {
+ it->lineContent = lineContent;
+ } else {
+ documentQueue.enqueue(change);
+
+ if (documentQueue.size() > Settings::contextSettings().maxChangesCacheSize()) {
+ documentQueue.dequeue();
+ }
+ }
+
+ logMessage(QString("ChangesManager: Updated %1 line %2: '%3'")
+ .arg(fileName)
+ .arg(lineNumber)
+ .arg(lineContent));
+ logMessage(QString("ChangesManager: Document queue size %1").arg(documentQueue.size()));
+}
+
+QString ChangesManager::getRecentChangesContext(const TextEditor::TextDocument *currentDocument) const
+{
+ QString context;
+ for (auto it = m_documentChanges.constBegin(); it != m_documentChanges.constEnd(); ++it) {
+ if (it.key() != currentDocument) {
+ for (const auto &change : it.value()) {
+ context += change.lineContent + "\n";
+ }
+ }
+ }
+ return context;
+}
+
+} // namespace QodeAssist
diff --git a/core/ChangesManager.h b/core/ChangesManager.h
new file mode 100644
index 0000000..d9c4c91
--- /dev/null
+++ b/core/ChangesManager.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 Petr Mironychev
+ *
+ * This file is part of QodeAssist.
+ *
+ * QodeAssist is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * QodeAssist is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with QodeAssist. If not, see .
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+namespace QodeAssist {
+
+class ChangesManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ struct ChangeInfo
+ {
+ QString fileName;
+ int lineNumber;
+ QString lineContent;
+ };
+
+ static ChangesManager &instance();
+
+ void addChange(TextEditor::TextDocument *document,
+ int position,
+ int charsRemoved,
+ int charsAdded);
+ QString getRecentChangesContext(const TextEditor::TextDocument *currentDocument) const;
+
+private:
+ ChangesManager();
+ ~ChangesManager();
+ ChangesManager(const ChangesManager &) = delete;
+ ChangesManager &operator=(const ChangesManager &) = delete;
+
+ void cleanupOldChanges();
+
+ QHash> m_documentChanges;
+};
+
+} // namespace QodeAssist
diff --git a/settings/ContextSettings.cpp b/settings/ContextSettings.cpp
index d0574df..5ff5d46 100644
--- a/settings/ContextSettings.cpp
+++ b/settings/ContextSettings.cpp
@@ -74,6 +74,15 @@ ContextSettings::ContextSettings()
resetToDefaults.m_buttonText = Tr::tr("Reset Page to Defaults");
+ useProjectChangesCache.setSettingsKey(Constants::USE_PROJECT_CHANGES_CACHE);
+ useProjectChangesCache.setDefaultValue(true);
+ useProjectChangesCache.setLabelText(Tr::tr("Use Project Changes Cache"));
+
+ maxChangesCacheSize.setSettingsKey(Constants::MAX_CHANGES_CACHE_SIZE);
+ maxChangesCacheSize.setLabelText(Tr::tr("Max Changes Cache Size"));
+ maxChangesCacheSize.setRange(2, 1000);
+ maxChangesCacheSize.setDefaultValue(20);
+
readSettings();
readStringsAfterCursor.setEnabled(!readFullFile());
@@ -90,6 +99,8 @@ ContextSettings::ContextSettings()
useFilePathInContext,
useSpecificInstructions,
specificInstractions,
+ useProjectChangesCache,
+ Row{maxChangesCacheSize, Stretch{1}},
Stretch{1}};
});
}
diff --git a/settings/ContextSettings.hpp b/settings/ContextSettings.hpp
index 4a6f539..dbe491b 100644
--- a/settings/ContextSettings.hpp
+++ b/settings/ContextSettings.hpp
@@ -37,6 +37,8 @@ public:
Utils::StringAspect specificInstractions{this};
Utils::BoolAspect useSpecificInstructions{this};
Utils::BoolAspect useFilePathInContext{this};
+ Utils::BoolAspect useProjectChangesCache{this};
+ Utils::IntegerAspect maxChangesCacheSize{this};
ButtonAspect resetToDefaults{this};
diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp
index 5f86830..7933965 100644
--- a/settings/GeneralSettings.cpp
+++ b/settings/GeneralSettings.cpp
@@ -72,7 +72,7 @@ GeneralSettings::GeneralSettings()
Tr::tr("The number of characters that need to be typed within the typing interval "
"before an AI suggestion request is sent."));
autoCompletionCharThreshold.setRange(0, 10);
- autoCompletionCharThreshold.setDefaultValue(1);
+ autoCompletionCharThreshold.setDefaultValue(0);
autoCompletionTypingInterval.setSettingsKey(Constants::AUTO_COMPLETION_TYPING_INTERVAL);
autoCompletionTypingInterval.setLabelText(Tr::tr("character(s) within(ms)"));