Files
eepp/src/tools/ecode/plugins/autocomplete/autocompleteplugin.hpp

194 lines
5.7 KiB
C++

#ifndef ECODE_AUTOCOMPLETEPLUGIN_HPP
#define ECODE_AUTOCOMPLETEPLUGIN_HPP
#include "../lsp/lspprotocol.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 <set>
using namespace EE;
using namespace EE::System;
using namespace EE::UI;
namespace ecode {
class AutoCompletePlugin : public UICodeEditorPlugin {
public:
class Suggestion {
public:
LSPCompletionItemKind kind{ LSPCompletionItemKind::Text };
std::string text;
std::string detail;
std::string sortText;
TextRange range;
double score{ 0 };
void setScore( const double& score ) const {
const_cast<Suggestion*>( this )->score = score;
}
Suggestion( const std::string& text ) : text( text ), sortText( text ) {}
Suggestion( const LSPCompletionItemKind& kind, const std::string& text,
const std::string& detail, const std::string& sortText,
const TextRange& range = {} ) :
kind( kind ),
text( text ),
detail( detail ),
sortText( sortText.empty() ? text : sortText ),
range( range ){};
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, 0 } };
}
static UICodeEditorPlugin* New( PluginManager* pluginManager );
virtual ~AutoCompletePlugin();
std::string getId() { return Definition().id; }
std::string getTitle() { return Definition().name; }
std::string getDescription() { return Definition().description; }
bool isReady() const { return true; }
void onRegister( UICodeEditor* );
void onUnregister( UICodeEditor* );
bool onKeyDown( UICodeEditor*, const KeyEvent& );
bool onTextInput( UICodeEditor*, const TextInputEvent& );
void update( UICodeEditor* );
void postDraw( UICodeEditor*, const Vector2f& startScroll, const Float& lineHeight,
const TextPosition& cursor );
bool onMouseDown( UICodeEditor*, const Vector2i&, const Uint32& );
bool onMouseUp( UICodeEditor*, const Vector2i&, const Uint32& );
bool onMouseDoubleClick( UICodeEditor*, const Vector2i&, const Uint32& );
bool onMouseMove( UICodeEditor*, const Vector2i&, const Uint32& );
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 );
protected:
PluginManager* mManager{ nullptr };
std::string mSymbolPattern;
Rectf mBoxPadding;
std::shared_ptr<ThreadPool> mPool;
Clock mClock;
Mutex mLangSymbolsMutex;
Mutex mSuggestionsMutex;
Mutex mDocMutex;
Time mUpdateFreq{ Seconds( 5 ) };
std::unordered_map<UICodeEditor*, std::vector<Uint32>> mEditors;
std::set<TextDocument*> mDocs;
std::unordered_map<UICodeEditor*, TextDocument*> mEditorDocs;
bool mDirty{ false };
bool mClosing{ false };
bool mReplacing{ false };
bool mSignatureHelpVisible{ false };
struct DocCache {
Uint64 changeId{ static_cast<Uint64>( -1 ) };
SymbolsList symbols;
};
std::unordered_map<TextDocument*, DocCache> mDocCache;
std::unordered_map<std::string, SymbolsList> mLangCache;
SymbolsList mLangDirty;
std::vector<Suggestion> mSuggestions;
Mutex mSuggestionsEditorMutex;
Mutex mSignatureHelpEditorMutex;
UICodeEditor* mSuggestionsEditor{ nullptr };
UICodeEditor* mSignatureHelpEditor{ nullptr };
Int32 mSuggestionIndex{ 0 };
Int32 mSuggestionsMaxVisible{ 8 };
Int32 mSuggestionsStartIndex{ 0 };
std::map<std::string, LSPServerCapabilities> mCapabilities;
Mutex mCapabilitiesMutex;
LSPSignatureHelp mSignatureHelp;
TextPosition mSignatureHelpPosition;
Int32 mSignatureHelpSelected{ -1 };
Mutex mHandlesMutex;
std::map<TextDocument*, std::vector<PluginIDType>> mHandles;
std::map<TextDocument*, std::atomic<bool>> mDocsUpdating;
Mutex mDocsUpdatingMutex;
Float mRowHeight{ 0 };
Rectf mBoxRect;
AutoCompletePlugin( 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 );
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 );
};
} // namespace ecode
#endif // ECODE_AUTOCOMPLETEPLUGIN_HPP