mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-05 04:56:31 +03:00
234 lines
7.3 KiB
C++
234 lines
7.3 KiB
C++
#ifndef ECODE_AUTOCOMPLETEPLUGIN_HPP
|
|
#define ECODE_AUTOCOMPLETEPLUGIN_HPP
|
|
|
|
#include "../lsp/lspprotocol.hpp"
|
|
#include "../plugin.hpp"
|
|
#include "../pluginmanager.hpp"
|
|
#include <eepp/config.hpp>
|
|
#include <eepp/system/clock.hpp>
|
|
#include <eepp/system/mutex.hpp>
|
|
#include <eepp/system/sys.hpp>
|
|
#include <eepp/system/threadpool.hpp>
|
|
#include <eepp/ui/uicodeeditor.hpp>
|
|
#include <unordered_map>
|
|
using namespace EE;
|
|
using namespace EE::System;
|
|
using namespace EE::UI;
|
|
|
|
namespace ecode {
|
|
|
|
class AutoCompletePlugin : public Plugin {
|
|
public:
|
|
class Suggestion {
|
|
public:
|
|
LSPCompletionItemKind kind{ LSPCompletionItemKind::Text };
|
|
std::string text;
|
|
std::string detail;
|
|
std::string sortText;
|
|
TextRange range;
|
|
std::string insertText;
|
|
double score{ 0 };
|
|
LSPMarkupContent documentation;
|
|
|
|
void setScore( const double& score ) const {
|
|
const_cast<Suggestion*>( this )->score = score;
|
|
}
|
|
|
|
Suggestion( const std::string& text ) : text( text ), sortText( text ) {}
|
|
|
|
Suggestion( LSPCompletionItemKind kind, std::string&& text, std::string&& detail,
|
|
std::string&& sortText, const TextRange& range, std::string&& insertText,
|
|
LSPMarkupContent&& doc ) :
|
|
kind( kind ),
|
|
text( std::move( text ) ),
|
|
detail( std::move( detail ) ),
|
|
sortText( sortText.empty() ? std::string{ this->text } : std::move( sortText ) ),
|
|
range( range ),
|
|
insertText( std::move( insertText ) ),
|
|
documentation( doc ) {};
|
|
|
|
bool operator<( const Suggestion& other ) const { return getCmpStr() < other.getCmpStr(); }
|
|
|
|
bool operator==( const Suggestion& other ) const { return text == other.text; }
|
|
|
|
protected:
|
|
const std::string* getCmpStr() const { return !sortText.empty() ? &sortText : &text; }
|
|
};
|
|
typedef std::vector<Suggestion> SymbolsList;
|
|
|
|
static PluginDefinition Definition() {
|
|
return { "autocomplete",
|
|
"Auto Complete",
|
|
"Auto complete shows the completion popup as you type, so you can fill "
|
|
"in long words by typing only a few characters.",
|
|
AutoCompletePlugin::New,
|
|
{ 0, 2, 8 },
|
|
AutoCompletePlugin::NewSync };
|
|
}
|
|
|
|
static Plugin* New( PluginManager* pluginManager );
|
|
|
|
static Plugin* NewSync( PluginManager* pluginManager );
|
|
|
|
virtual ~AutoCompletePlugin();
|
|
|
|
std::string getId() override { return Definition().id; }
|
|
|
|
std::string getTitle() override { return Definition().name; }
|
|
|
|
std::string getDescription() override { return Definition().description; }
|
|
|
|
bool isReady() const override { return true; }
|
|
|
|
void onRegister( UICodeEditor* ) override;
|
|
void onUnregister( UICodeEditor* ) override;
|
|
bool onKeyDown( UICodeEditor*, const KeyEvent& ) override;
|
|
bool onTextInput( UICodeEditor*, const TextInputEvent& ) override;
|
|
void update( UICodeEditor* ) override;
|
|
void postDraw( UICodeEditor*, const Vector2f& startScroll, const Float& lineHeight,
|
|
const TextPosition& cursor ) override;
|
|
bool onMouseDown( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
|
bool onMouseUp( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
|
bool onMouseDoubleClick( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
|
bool onMouseMove( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
|
|
|
const Rectf& getBoxPadding() const;
|
|
|
|
void setBoxPadding( const Rectf& boxPadding );
|
|
|
|
const Int32& getSuggestionsMaxVisible() const;
|
|
|
|
void setSuggestionsMaxVisible( const Uint32& suggestionsMaxVisible );
|
|
|
|
const Time& getUpdateFreq() const;
|
|
|
|
void setUpdateFreq( const Time& updateFreq );
|
|
|
|
const std::string& getSymbolPattern() const;
|
|
|
|
void setSymbolPattern( const std::string& symbolPattern );
|
|
|
|
bool isDirty() const;
|
|
|
|
void setDirty( bool dirty );
|
|
|
|
bool onCreateContextMenu( UICodeEditor* editor, UIPopUpMenu* menu, const Vector2i& position,
|
|
const Uint32& flags ) override;
|
|
|
|
protected:
|
|
std::string mSymbolPattern;
|
|
Rectf mBoxPadding;
|
|
Clock mClock;
|
|
Mutex mLangSymbolsMutex;
|
|
Mutex mSuggestionsMutex;
|
|
Mutex mDocMutex;
|
|
Time mUpdateFreq{ Seconds( 5 ) };
|
|
std::unordered_map<UICodeEditor*, std::vector<Uint32>> mEditors;
|
|
std::unordered_set<TextDocument*> mDocs;
|
|
std::unordered_map<UICodeEditor*, TextDocument*> mEditorDocs;
|
|
bool mDirty{ false };
|
|
bool mReplacing{ false };
|
|
bool mSignatureHelpVisible{ false };
|
|
bool mHighlightSuggestions{ true };
|
|
struct DocCache {
|
|
Uint64 changeId{ static_cast<Uint64>( -1 ) };
|
|
SymbolsList symbols;
|
|
};
|
|
std::unordered_map<TextDocument*, DocCache> mDocCache;
|
|
std::unordered_map<TextDocument*, bool> mDocUsesOwnSymbols;
|
|
std::unordered_map<std::string, SymbolsList> mLangCache;
|
|
std::vector<Suggestion> mSuggestions;
|
|
Mutex mSuggestionsEditorMutex;
|
|
Mutex mSignatureHelpEditorMutex;
|
|
UICodeEditor* mSuggestionsEditor{ nullptr };
|
|
UICodeEditor* mSignatureHelpEditor{ nullptr };
|
|
Int32 mSuggestionIndex{ 0 };
|
|
Int32 mSuggestionsMaxVisible{ 8 };
|
|
Int32 mSuggestionsStartIndex{ 0 };
|
|
std::unordered_map<std::string, LSPServerCapabilities> mCapabilities;
|
|
Mutex mCapabilitiesMutex;
|
|
Mutex mDocUsesOwnSymbolsMutex;
|
|
|
|
struct SignatureInformation {
|
|
String label;
|
|
LSPMarkupContent documentation;
|
|
std::vector<TextRange> parameters;
|
|
};
|
|
|
|
struct SignatureHelp {
|
|
std::vector<SignatureInformation> signatures;
|
|
int activeSignature{ 0 };
|
|
int activeParameter{ 0 };
|
|
};
|
|
|
|
SignatureHelp mSignatureHelp;
|
|
TextPosition mSignatureHelpPosition;
|
|
Int32 mSignatureHelpSelected{ -1 };
|
|
Mutex mHandlesMutex;
|
|
std::unordered_map<TextDocument*, std::vector<PluginIDType>> mHandles;
|
|
std::unordered_map<TextDocument*, std::atomic<bool>> mDocsUpdating;
|
|
Mutex mDocsUpdatingMutex;
|
|
Text mSuggestionDoc;
|
|
size_t mMaxLabelCharacters{ 100 };
|
|
String::HashType mConfigHash{ 0 };
|
|
std::unordered_map<std::string, std::string> mKeyBindings;
|
|
std::unordered_map<std::string, KeyBindings::Shortcut> mShortcuts;
|
|
std::string mMaxSuggestionDocumentationWidth;
|
|
|
|
Float mRowHeight{ 0 };
|
|
Rectf mBoxRect;
|
|
|
|
explicit AutoCompletePlugin( PluginManager* pluginManager, bool sync );
|
|
|
|
void load( PluginManager* pluginManager );
|
|
|
|
void resetSuggestions( UICodeEditor* editor );
|
|
|
|
void updateSuggestions( const std::string& symbol, UICodeEditor* editor );
|
|
|
|
SymbolsList getDocumentSymbols( TextDocument* );
|
|
|
|
void updateDocCache( TextDocument* doc );
|
|
|
|
std::string getPartialSymbol( TextDocument* doc );
|
|
|
|
void runUpdateSuggestions( const std::string& symbol, const SymbolsList& symbols,
|
|
UICodeEditor* editor, bool fromDocCache );
|
|
|
|
void updateLangCache( const std::string& langName );
|
|
|
|
void pickSuggestion( UICodeEditor* editor );
|
|
|
|
PluginRequestHandle processResponse( const PluginMessage& msg );
|
|
|
|
bool tryRequestCapabilities( UICodeEditor* editor );
|
|
|
|
void requestCodeCompletion( UICodeEditor* editor );
|
|
|
|
void requestSignatureHelp( UICodeEditor* editor );
|
|
|
|
PluginRequestHandle processCodeCompletion( const LSPCompletionList& completion );
|
|
|
|
PluginRequestHandle processSignatureHelp( const LSPSignatureHelp& signatureHelp );
|
|
|
|
void resetSignatureHelp();
|
|
|
|
void drawSignatureHelp( UICodeEditor* editor, const Vector2f& startScroll,
|
|
const Float& lineHeight, bool drawUp );
|
|
|
|
bool hasCompleteSteps( const Suggestion& suggestion );
|
|
|
|
void tryStartSnippetNav( const Suggestion& suggestion, UICodeEditor* editor,
|
|
const TextRanges& prevSels );
|
|
|
|
Rectf findBestDocumentationPlacement( UICodeEditor* editor, const Suggestion& suggestion,
|
|
const Rectf& anchorBox, const Rectf& rowRect, bool drawUp,
|
|
Float lineHeight );
|
|
|
|
void updateShortcuts();
|
|
};
|
|
|
|
} // namespace ecode
|
|
|
|
#endif // ECODE_AUTOCOMPLETEPLUGIN_HPP
|