mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-18 19:43:24 +03:00
Refactor in SyntaxDefinition and related classes.
Minor improvements in CPP, CSS, xit syntax highlighting. AI Assistant / LLM Chat now can restore previous opened chats and states (last model used, panel split), can have private conversations, can clone a previous conversation, plus some visual improvements. Fixed a bug in tab widget splitting.
This commit is contained in:
@@ -117,6 +117,7 @@ class EE_API Event {
|
||||
OnModelChanged,
|
||||
OnWindowToFront,
|
||||
OnVisibleLinesCountChange,
|
||||
OnDataChanged,
|
||||
NoEvent = eeINDEX_NOT_FOUND
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ template <typename T> static auto toSyntaxStyleTypeV( const std::vector<T>& s )
|
||||
return std::vector<SyntaxStyleType>{};
|
||||
}
|
||||
|
||||
enum class SyntaxPatternMatchType { LuaPattern, RegEx };
|
||||
|
||||
struct EE_API SyntaxPattern {
|
||||
static UnorderedMap<SyntaxStyleType, std::string> SyntaxStyleTypeCache;
|
||||
|
||||
@@ -37,19 +39,23 @@ struct EE_API SyntaxPattern {
|
||||
std::vector<std::string> typesNames;
|
||||
std::string syntax{ "" };
|
||||
DynamicSyntax dynSyntax;
|
||||
bool isRegEx{ false };
|
||||
SyntaxPatternMatchType matchType{ SyntaxPatternMatchType::LuaPattern };
|
||||
|
||||
SyntaxPattern( std::vector<std::string>&& _patterns, const std::string& _type,
|
||||
const std::string& _syntax = "", bool isRegEx = false );
|
||||
const std::string& _syntax = "",
|
||||
SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern );
|
||||
|
||||
SyntaxPattern( std::vector<std::string>&& _patterns, std::vector<std::string>&& _types,
|
||||
const std::string& _syntax = "", bool isRegEx = false );
|
||||
const std::string& _syntax = "",
|
||||
SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern );
|
||||
|
||||
SyntaxPattern( std::vector<std::string>&& _patterns, const std::string& _type,
|
||||
DynamicSyntax&& _syntax, bool isRegEx = false );
|
||||
DynamicSyntax&& _syntax,
|
||||
SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern );
|
||||
|
||||
SyntaxPattern( std::vector<std::string>&& _patterns, std::vector<std::string>&& _types,
|
||||
DynamicSyntax&& _syntax, bool isRegEx = false );
|
||||
DynamicSyntax&& _syntax,
|
||||
SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern );
|
||||
|
||||
bool hasSyntax() const { return !syntax.empty() || dynSyntax; }
|
||||
};
|
||||
|
||||
@@ -55,8 +55,8 @@ struct SyntaxState {
|
||||
Uint8 state[MAX_SUB_SYNTAXS]{ SYNTAX_TOKENIZER_STATE_NONE, SYNTAX_TOKENIZER_STATE_NONE,
|
||||
SYNTAX_TOKENIZER_STATE_NONE, SYNTAX_TOKENIZER_STATE_NONE };
|
||||
|
||||
// 8 bits per language (language index) - max 4 sub-languages - max 255 languages
|
||||
Uint8 langStack[MAX_SUB_SYNTAXS]{ 0, 0, 0, 0 };
|
||||
// 16 bits per language (language index) - max 4 sub-languages - max 65k languages
|
||||
Uint16 langStack[MAX_SUB_SYNTAXS]{ 0, 0, 0, 0 };
|
||||
|
||||
bool operator==( const SyntaxState& other ) {
|
||||
return memcmp( this, &other, sizeof( SyntaxState ) ) == 0;
|
||||
|
||||
@@ -161,6 +161,9 @@ class EE_API UICodeEditorSplitter {
|
||||
void forEachWidgetClass( const std::string& className,
|
||||
std::function<void( UIWidget* )> run ) const;
|
||||
|
||||
void forEachWidgetClassStoppable( const std::string& className,
|
||||
std::function<bool( UIWidget* )> run ) const;
|
||||
|
||||
void forEachWidgetType( const UINodeType& nodeType,
|
||||
std::function<void( UIWidget* )> run ) const;
|
||||
|
||||
|
||||
@@ -309,6 +309,7 @@
|
||||
../../include/eepp/ui/abstract/uiabstractview.hpp
|
||||
../../include/eepp/ui/base.hpp
|
||||
../../include/eepp/ui.hpp
|
||||
../../include/eepp/ui/border.hpp
|
||||
../../include/eepp/ui/models/modeleditingdelegate.hpp
|
||||
../../include/eepp/ui/models/modelindex.hpp
|
||||
../../include/eepp/ui/models/modelselection.hpp
|
||||
@@ -348,6 +349,7 @@
|
||||
../../include/eepp/ui/doc/textposition.hpp
|
||||
../../include/eepp/ui/doc/textrange.hpp
|
||||
../../include/eepp/ui/doc/textundostack.hpp
|
||||
../../include/eepp/ui/iconmanager.hpp
|
||||
../../include/eepp/ui/keyboardshortcut.hpp
|
||||
../../include/eepp/ui/marginmove/scale.hpp
|
||||
../../include/eepp/ui/models/csspropertiesmodel.hpp
|
||||
@@ -367,6 +369,7 @@
|
||||
../../include/eepp/ui/tools/uidocfindreplace.hpp
|
||||
../../include/eepp/ui/tools/uiwidgetinspector.hpp
|
||||
../../include/eepp/ui/uiabstractview.hpp
|
||||
../../include/eepp/ui/uiapplication.hpp
|
||||
../../include/eepp/ui/uibackgrounddrawable.hpp
|
||||
../../include/eepp/ui/uiborderdrawable.hpp
|
||||
../../include/eepp/ui/uicheckbox.hpp
|
||||
@@ -393,9 +396,11 @@
|
||||
../../include/eepp/ui/uilistview.hpp
|
||||
../../include/eepp/ui/uiloader.hpp
|
||||
../../include/eepp/ui/uimanager.hpp
|
||||
../../include/eepp/ui/uimenu.hpp
|
||||
../../include/eepp/ui/uimenubar.hpp
|
||||
../../include/eepp/ui/uimenucheckbox.hpp
|
||||
../../include/eepp/ui/uimenu.hpp
|
||||
../../include/eepp/ui/uimenucheckbox.hpp
|
||||
../../include/eepp/ui/uimenuitem.hpp
|
||||
../../include/eepp/ui/uimenuradiobutton.hpp
|
||||
../../include/eepp/ui/uimenuseparator.hpp
|
||||
@@ -421,6 +426,7 @@
|
||||
../../include/eepp/ui/uispinbox.hpp
|
||||
../../include/eepp/ui/uisplitter.hpp
|
||||
../../include/eepp/ui/uisprite.hpp
|
||||
../../include/eepp/ui/uistacklayout.hpp
|
||||
../../include/eepp/ui/uistackwidget.hpp
|
||||
../../include/eepp/ui/uistate.hpp
|
||||
../../include/eepp/ui/uistyle.hpp
|
||||
@@ -441,11 +447,13 @@
|
||||
../../include/eepp/ui/uitouchdraggablewidget.hpp
|
||||
../../include/eepp/ui/uitreeview.hpp
|
||||
../../include/eepp/ui/uiviewpager.hpp
|
||||
../../include/eepp/ui/uiwidget.hpp
|
||||
../../include/eepp/ui/uiwidgetcreator.hpp
|
||||
../../include/eepp/ui/uiwidget.hpp
|
||||
../../include/eepp/ui/uiwidgettable.hpp
|
||||
../../include/eepp/ui/uiwidgettablerow.hpp
|
||||
../../include/eepp/ui/uiwindow.hpp
|
||||
../../include/eepp/ui/undostack.hpp
|
||||
../../include/eepp/ui/widgetcommandexecuter.hpp
|
||||
../../include/eepp/version.hpp
|
||||
../../include/eepp/window/base.hpp
|
||||
@@ -867,6 +875,7 @@
|
||||
../../src/eepp/system/virtualfilesystem.cpp
|
||||
../../src/eepp/system/zip.cpp
|
||||
../../src/eepp/ui/abstract/filesystemmodel.hpp
|
||||
../../src/eepp/ui/border.cpp
|
||||
../../src/eepp/ui/doc/foldrangeservice.cpp
|
||||
../../src/eepp/ui/doc/languages/adept.cpp
|
||||
../../src/eepp/ui/doc/languages/adept.hpp
|
||||
@@ -1131,6 +1140,7 @@
|
||||
../../src/eepp/ui/doc/textrange.cpp
|
||||
../../src/eepp/ui/doc/textundostack.cpp
|
||||
../../src/eepp/ui/doc/documentview.cpp
|
||||
../../src/eepp/ui/iconmanager.cpp
|
||||
../../src/eepp/ui/keyboardshortcut.cpp
|
||||
../../src/eepp/ui/models/filesystemmodel.cpp
|
||||
../../src/eepp/ui/models/model.cpp
|
||||
@@ -1174,9 +1184,11 @@
|
||||
../../src/eepp/ui/uilistview.cpp
|
||||
../../src/eepp/ui/uiloader.cpp
|
||||
../../src/eepp/ui/uimanager.cpp
|
||||
../../src/eepp/ui/uimenu.cpp
|
||||
../../src/eepp/ui/uimenubar.cpp
|
||||
../../src/eepp/ui/uimenucheckbox.cpp
|
||||
../../src/eepp/ui/uimenu.cpp
|
||||
../../src/eepp/ui/uimenucheckbox.cpp
|
||||
../../src/eepp/ui/uimenuitem.cpp
|
||||
../../src/eepp/ui/uimenuradiobutton.cpp
|
||||
../../src/eepp/ui/uimenuseparator.cpp
|
||||
@@ -1365,6 +1377,241 @@
|
||||
../../src/modules/eterm/src/eterm/terminal/wide.hpp
|
||||
../../src/modules/eterm/src/eterm/terminal/windowserrors.hpp
|
||||
../../src/modules/eterm/src/eterm/ui/uiterminal.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ada.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ada.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/adept.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/adept.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/angelscript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/angelscript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/awkscript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/awkscript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/batchscript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/batchscript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/bazel.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/bazel.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/bend.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/bend.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/blade.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/blade.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/blueprint.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/blueprint.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/brainfuck.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/brainfuck.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/buzz.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/buzz.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/carbon.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/carbon.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/clojure.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/clojure.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/cmake.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/cmake.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/containerfile.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/containerfile.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/crystal.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/crystal.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/csharp.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/csharp.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/d.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/d.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/dart.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/dart.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/difffile.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/difffile.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/elixir.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/elixir.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/elm.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/elm.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/environmentfile.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/environmentfile.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fantom.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fantom.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fennel.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fennel.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fortran.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fortran.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fstab.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/fstab.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/gdscript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/gdscript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/glsl.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/glsl.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/go.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/go.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/graphql.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/graphql.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/groovy.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/groovy.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/hare.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/hare.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/haskell.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/haskell.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/haxe.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/haxe.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/hlsl.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/hlsl.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/htaccess.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/htaccess.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ignorefile.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ignorefile.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/jai.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/jai.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/java.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/java.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/jsx.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/jsx.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/jule.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/jule.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/julia.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/julia.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/kotlin.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/kotlin.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/latex.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/latex.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/lobster.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/lobster.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/meson.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/meson.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/moonscript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/moonscript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/nelua.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/nelua.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/nim.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/nim.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objeck.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objeck.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-c.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/objective-c.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ocaml.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ocaml.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/odin.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/odin.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/openscad.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/openscad.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/pascal.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/pascal.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/perl.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/perl.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/php.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/php.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/pico-8.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/pico-8.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/po.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/po.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/pony.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/pony.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/postgresql.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/postgresql.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/powershell.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/powershell.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/r.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/r.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/rave.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/rave.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ring.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ring.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ruby.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/ruby.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/rust.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/rust.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/sass.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/sass.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/scala.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/scala.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/shellscript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/shellscript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/smallbasic.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/smallbasic.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/solidity.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/solidity.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/sql.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/sql.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/svelte.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/svelte.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/swift.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/swift.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/tcl.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/tcl.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/teal.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/teal.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/toml.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/toml.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/typescript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/typescript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/v.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/v.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/v1.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/v1.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/vala.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/vala.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/vb.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/vb.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/verilog.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/verilog.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/vue.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/vue.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/wren.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/wren.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/x86assembly.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/x86assembly.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xit.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xit.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xtend.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xtend.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yaml.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yaml.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yuescript.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yuescript.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/zig.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/zig.hpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languagessyntaxhighlighting.cpp
|
||||
../../src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languagessyntaxhighlighting.hpp
|
||||
../../src/modules/maps/include/eepp/maps/base.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobject.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobjectobject.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobjectpolygon.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobjectpolyline.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobjectsprite.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobjecttextureregion.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobjecttextureregionex.hpp
|
||||
../../src/modules/maps/include/eepp/maps/gameobjectvirtual.hpp
|
||||
../../src/modules/maps/include/eepp/maps/mapeditor/mapeditor.hpp
|
||||
../../src/modules/maps/include/eepp/maps/maphelper.hpp
|
||||
../../src/modules/maps/include/eepp/maps/maplayer.hpp
|
||||
../../src/modules/maps/include/eepp/maps/maplight.hpp
|
||||
../../src/modules/maps/include/eepp/maps/maplightmanager.hpp
|
||||
../../src/modules/maps/include/eepp/maps/mapobjectlayer.hpp
|
||||
../../src/modules/maps/include/eepp/maps/maps.hpp
|
||||
../../src/modules/maps/include/eepp/maps/tilemap.hpp
|
||||
../../src/modules/maps/include/eepp/maps/tilemaplayer.hpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobject.cpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobjectobject.cpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobjectpolygon.cpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobjectpolyline.cpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobjectsprite.cpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobjecttextureregion.cpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobjecttextureregionex.cpp
|
||||
../../src/modules/maps/src/eepp/maps/gameobjectvirtual.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/mapeditor.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/maplayerproperties.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/maplayerproperties.hpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/mapobjectproperties.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/mapobjectproperties.hpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/tilemapproperties.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/tilemapproperties.hpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uigotypenew.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uigotypenew.hpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uimap.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uimap.hpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uimaplayernew.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uimaplayernew.hpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uimapnew.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapeditor/uimapnew.hpp
|
||||
../../src/modules/maps/src/eepp/maps/maplayer.cpp
|
||||
../../src/modules/maps/src/eepp/maps/maplight.cpp
|
||||
../../src/modules/maps/src/eepp/maps/maplightmanager.cpp
|
||||
../../src/modules/maps/src/eepp/maps/mapobjectlayer.cpp
|
||||
../../src/modules/maps/src/eepp/maps/tilemap.cpp
|
||||
../../src/modules/maps/src/eepp/maps/tilemaplayer.cpp
|
||||
../../src/modules/physics/include/eepp/physics/arbiter.hpp
|
||||
../../src/modules/physics/include/eepp/physics/area.hpp
|
||||
../../src/modules/physics/include/eepp/physics/base.hpp
|
||||
|
||||
@@ -441,7 +441,10 @@ Node* Node::getNextNodeLoop() const {
|
||||
}
|
||||
|
||||
Node* Node::setData( const UintPtr& data ) {
|
||||
mData = data;
|
||||
if ( data != mData ) {
|
||||
mData = data;
|
||||
sendCommonEvent( Event::OnDataChanged );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ void addCPP() {
|
||||
{ { "[%+%-=/%*%^%%<>!~|&]" }, "operator" },
|
||||
{ { "[%a_][%w_]*%f[(]" }, "function" },
|
||||
{ { "std%:%:[%w_]*" }, "keyword2" },
|
||||
{ { "(%[)(%[)(%a[%w_]+)(%])(%])" },
|
||||
{ "normal", "keyword", "keyword3", "keyword2", "keyword3", "keyword" } },
|
||||
{ { "[%a_][%w_]*" }, "symbol" },
|
||||
|
||||
},
|
||||
|
||||
@@ -21,6 +21,7 @@ void addCSS() {
|
||||
{ { "#[%a%_%-][%w%_%-]*" }, "keyword2" },
|
||||
{ { "%-%-%a[%w%-%_]*" }, "keyword2" },
|
||||
{ { "-?%d+[%d%.]*p[xt]" }, "number" },
|
||||
{ { "-?%d+[%d%.]*dp" }, "number" },
|
||||
{ { "-?%d+[%d%.]*deg" }, "number" },
|
||||
{ { "-?%d+[%d%.]*" }, "number" },
|
||||
{ { "@[%a][%w%_%-]*" }, "keyword2" },
|
||||
|
||||
@@ -259,44 +259,44 @@ const String::HashType& SyntaxDefinition::getLanguageId() const {
|
||||
}
|
||||
|
||||
SyntaxPattern::SyntaxPattern( std::vector<std::string>&& _patterns, const std::string& _type,
|
||||
const std::string& _syntax, bool isRegEx ) :
|
||||
const std::string& _syntax, SyntaxPatternMatchType matchType ) :
|
||||
patterns( std::move( _patterns ) ),
|
||||
types( toSyntaxStyleTypeV( std::vector<std::string>{ _type } ) ),
|
||||
typesNames( { _type } ),
|
||||
syntax( _syntax ),
|
||||
isRegEx( isRegEx ) {
|
||||
matchType( matchType ) {
|
||||
updateCache<SyntaxStyleType>( *this );
|
||||
}
|
||||
|
||||
SyntaxPattern::SyntaxPattern( std::vector<std::string>&& _patterns,
|
||||
std::vector<std::string>&& _types, const std::string& _syntax,
|
||||
bool isRegEx ) :
|
||||
SyntaxPatternMatchType matchType ) :
|
||||
patterns( std::move( _patterns ) ),
|
||||
types( toSyntaxStyleTypeV( _types ) ),
|
||||
typesNames( std::move( _types ) ),
|
||||
syntax( _syntax ),
|
||||
isRegEx( isRegEx ) {
|
||||
matchType( matchType ) {
|
||||
updateCache<SyntaxStyleType>( *this );
|
||||
}
|
||||
|
||||
SyntaxPattern::SyntaxPattern( std::vector<std::string>&& _patterns, const std::string& _type,
|
||||
DynamicSyntax&& _syntax, bool isRegEx ) :
|
||||
DynamicSyntax&& _syntax, SyntaxPatternMatchType matchType ) :
|
||||
patterns( std::move( _patterns ) ),
|
||||
types( toSyntaxStyleTypeV( std::vector<std::string>{ _type } ) ),
|
||||
typesNames( { _type } ),
|
||||
dynSyntax( std::move( _syntax ) ),
|
||||
isRegEx( isRegEx ) {
|
||||
matchType( matchType ) {
|
||||
updateCache<SyntaxStyleType>( *this );
|
||||
}
|
||||
|
||||
SyntaxPattern::SyntaxPattern( std::vector<std::string>&& _patterns,
|
||||
std::vector<std::string>&& _types, DynamicSyntax&& _syntax,
|
||||
bool isRegEx ) :
|
||||
SyntaxPatternMatchType matchType ) :
|
||||
patterns( std::move( _patterns ) ),
|
||||
types( toSyntaxStyleTypeV( _types ) ),
|
||||
typesNames( std::move( _types ) ),
|
||||
dynSyntax( std::move( _syntax ) ),
|
||||
isRegEx( isRegEx ) {
|
||||
matchType( matchType ) {
|
||||
updateCache<SyntaxStyleType>( *this );
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ static json toJson( const SyntaxDefinition& def ) {
|
||||
j["patterns"] = json::array();
|
||||
for ( const auto& ptrn : def.getPatterns() ) {
|
||||
json pattern;
|
||||
auto ptrnType = ptrn.isRegEx ? "regex" : "pattern";
|
||||
auto ptrnType = ptrn.matchType == SyntaxPatternMatchType::RegEx ? "regex" : "pattern";
|
||||
if ( ptrn.patterns.size() == 1 ) {
|
||||
pattern[ptrnType] = ptrn.patterns[0];
|
||||
} else {
|
||||
@@ -206,12 +206,13 @@ namespace EE { namespace UI { namespace Doc { namespace Language {
|
||||
buf += "{\n";
|
||||
for ( const auto& pattern : def.getPatterns() ) {
|
||||
buf += "{ " + join( pattern.patterns ) + ", " +
|
||||
join( pattern.typesNames, true, true, pattern.isRegEx ) +
|
||||
join( pattern.typesNames, true, true,
|
||||
pattern.matchType == SyntaxPatternMatchType::RegEx ) +
|
||||
str( pattern.syntax, ", ", "", false );
|
||||
if ( pattern.isRegEx && pattern.syntax.empty() )
|
||||
buf += ", \"\", true";
|
||||
else if ( pattern.isRegEx )
|
||||
buf += ", true";
|
||||
if ( pattern.matchType == SyntaxPatternMatchType::RegEx && pattern.syntax.empty() )
|
||||
buf += ", \"\", SyntaxPatternMatchType::RegEx";
|
||||
else if ( pattern.matchType == SyntaxPatternMatchType::RegEx )
|
||||
buf += ", SyntaxPatternMatchType::RegEx";
|
||||
buf += " },\n";
|
||||
}
|
||||
buf += "\n},\n";
|
||||
@@ -400,8 +401,9 @@ static SyntaxDefinition loadLanguage( const nlohmann::json& json ) {
|
||||
ptrns.emplace_back( pattern["regex"] );
|
||||
}
|
||||
}
|
||||
def.addPattern(
|
||||
SyntaxPattern( std::move( ptrns ), std::move( type ), syntax, isRegEx ) );
|
||||
def.addPattern( SyntaxPattern( std::move( ptrns ), std::move( type ), syntax,
|
||||
isRegEx ? SyntaxPatternMatchType::RegEx
|
||||
: SyntaxPatternMatchType::LuaPattern ) );
|
||||
}
|
||||
}
|
||||
if ( json.contains( "symbols" ) ) {
|
||||
|
||||
@@ -105,13 +105,15 @@ struct NonEscapedMatch {
|
||||
};
|
||||
|
||||
static NonEscapedMatch findNonEscaped( const std::string& text, const std::string& pattern,
|
||||
int offset, const std::string& escapeStr, bool isRegEx ) {
|
||||
int offset, const std::string& escapeStr,
|
||||
SyntaxPatternMatchType matchType ) {
|
||||
eeASSERT( !pattern.empty() );
|
||||
if ( pattern.empty() )
|
||||
return {};
|
||||
std::variant<RegEx, LuaPattern> wordsVar =
|
||||
isRegEx ? std::variant<RegEx, LuaPattern>( RegEx( pattern ) )
|
||||
: std::variant<RegEx, LuaPattern>( LuaPattern( pattern ) );
|
||||
matchType == SyntaxPatternMatchType::RegEx
|
||||
? std::variant<RegEx, LuaPattern>( RegEx( pattern ) )
|
||||
: std::variant<RegEx, LuaPattern>( LuaPattern( pattern ) );
|
||||
PatternMatcher& words =
|
||||
std::visit( []( auto& patternType ) -> PatternMatcher& { return patternType; }, wordsVar );
|
||||
int start, end;
|
||||
@@ -272,7 +274,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
|
||||
curState.currentSyntax->getPatterns()[curState.currentPatternIdx - 1];
|
||||
auto range = findNonEscaped( text, pattern.patterns[1], i,
|
||||
pattern.patterns.size() >= 3 ? pattern.patterns[2] : "",
|
||||
pattern.isRegEx )
|
||||
pattern.matchType )
|
||||
.range;
|
||||
|
||||
bool skip = false;
|
||||
@@ -283,7 +285,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
|
||||
curState.subsyntaxInfo->patterns.size() >= 3
|
||||
? curState.subsyntaxInfo->patterns[2]
|
||||
: "",
|
||||
pattern.isRegEx );
|
||||
pattern.matchType );
|
||||
|
||||
if ( rangeSubsyntax.range.first != -1 &&
|
||||
( range.first == -1 || rangeSubsyntax.range.first < range.first ) ) {
|
||||
@@ -320,7 +322,7 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
|
||||
text, "^" + curState.subsyntaxInfo->patterns[1], i,
|
||||
curState.subsyntaxInfo->patterns.size() >= 3 ? curState.subsyntaxInfo->patterns[2]
|
||||
: "",
|
||||
curState.subsyntaxInfo->isRegEx );
|
||||
curState.subsyntaxInfo->matchType );
|
||||
|
||||
if ( rangeSubsyntax.range.first != -1 ) {
|
||||
if ( !skipSubSyntaxSeparator ) {
|
||||
@@ -342,8 +344,9 @@ _tokenize( const SyntaxDefinition& syntax, const std::string& text, const Syntax
|
||||
patternStr =
|
||||
pattern.patterns[0][0] == '^' ? pattern.patterns[0] : "^" + pattern.patterns[0];
|
||||
std::variant<RegEx, LuaPattern> wordsVar =
|
||||
pattern.isRegEx ? std::variant<RegEx, LuaPattern>( RegEx( patternStr ) )
|
||||
: std::variant<RegEx, LuaPattern>( LuaPattern( patternStr ) );
|
||||
pattern.matchType == SyntaxPatternMatchType::RegEx
|
||||
? std::variant<RegEx, LuaPattern>( RegEx( patternStr ) )
|
||||
: std::variant<RegEx, LuaPattern>( LuaPattern( patternStr ) );
|
||||
PatternMatcher& words = std::visit(
|
||||
[]( auto& patternType ) -> PatternMatcher& { return patternType; }, wordsVar );
|
||||
if ( !words.isValid() ) // Skip invalid patterns
|
||||
|
||||
@@ -99,6 +99,8 @@ UIIconTheme* IconManager::init( const std::string& iconThemeName, FontTrueType*
|
||||
{ "code-ai", 0xF56F },
|
||||
{ "robot-2", 0xF3D9 },
|
||||
{ "chat-history", 0xEB61 },
|
||||
{ "chat-private", 0xEB69 },
|
||||
{ "loader-2", 0xEEC2 },
|
||||
};
|
||||
|
||||
for ( const auto& icon : icons )
|
||||
|
||||
@@ -786,6 +786,22 @@ void UICodeEditorSplitter::forEachWidgetClass( const std::string& className,
|
||||
}
|
||||
}
|
||||
|
||||
void UICodeEditorSplitter::forEachWidgetClassStoppable(
|
||||
const std::string& className, std::function<bool( UIWidget* )> run ) const {
|
||||
Node* node;
|
||||
UIWidget* widget;
|
||||
for ( auto tabWidget : mTabWidgets ) {
|
||||
for ( size_t i = 0; i < tabWidget->getTabCount(); i++ ) {
|
||||
node = tabWidget->getTab( i )->getOwnedWidget();
|
||||
if ( node && node->isWidget() ) {
|
||||
widget = node->asType<UIWidget>();
|
||||
if ( widget->hasClass( className ) && run( widget ) )
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UICodeEditorSplitter::forEachWidgetType( const UINodeType& nodeType,
|
||||
std::function<void( UIWidget* )> run ) const {
|
||||
Node* node;
|
||||
|
||||
@@ -1036,6 +1036,8 @@ Uint32 UITabWidget::onMessage( const NodeMessage* msg ) {
|
||||
return 1;
|
||||
}
|
||||
} else if ( dir && tab->getTabWidget()->allowDragAndDropTabs() ) {
|
||||
if ( tab->getTabWidget() == this && tab->getTabWidget()->getTabCount() <= 1 )
|
||||
return 0;
|
||||
tab->getTabWidget()->removeTab( tab, false, false, false );
|
||||
auto tabWidget = mSplitFn( *dir, this );
|
||||
tabWidget->add( tab );
|
||||
|
||||
@@ -30,20 +30,20 @@ void addSvelte() {
|
||||
{ { "<!%-%-", "%-%->" }, "comment" },
|
||||
{ { "\"", "\"", "\\" }, "string" },
|
||||
{ { "'", "'", "\\" }, "string" },
|
||||
{ { "{@html[^}]*}" }, "keyword", "", true },
|
||||
{ { "{@debug[^}]*}" }, "keyword", "", true },
|
||||
{ { "{@html[^}]*}" }, "keyword", "", SyntaxPatternMatchType::RegEx },
|
||||
{ { "{@debug[^}]*}" }, "keyword", "", SyntaxPatternMatchType::RegEx },
|
||||
{ { "{(:else|:then|:catch)}" },
|
||||
std::vector<std::string>{ "keyword", "keyword2" },
|
||||
"",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "{(/if|/each|/await|/key)}" },
|
||||
std::vector<std::string>{ "keyword", "keyword2" },
|
||||
"",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "{(#if|#each|#await|#key)", "}", "\\" },
|
||||
std::vector<std::string>{ "keyword", "keyword2", "normal" },
|
||||
"JavaScript",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "{", "}", "\\" }, "keyword", "JavaScript" },
|
||||
{ { "([%a_][%w_-]*)(:)([%a_][%w_-]*)(=)" },
|
||||
{ "keyword", "keyword2", "normal", "keyword", "operator" } },
|
||||
|
||||
@@ -4,12 +4,20 @@
|
||||
namespace EE { namespace UI { namespace Doc { namespace Language {
|
||||
|
||||
void addXit() {
|
||||
auto dynSyntax = []( const SyntaxPattern&, const std::string_view& match ) -> std::string {
|
||||
std::string lang = String::toLower( std::string{ match.substr( 3 ) } );
|
||||
String::trimInPlace( lang );
|
||||
if ( !lang.empty() && lang[lang.size() - 1] == '\n' )
|
||||
lang.pop_back();
|
||||
return SyntaxDefinitionManager::instance()->findFromString( lang ).getLanguageName();
|
||||
};
|
||||
|
||||
SyntaxDefinitionManager::instance()->add(
|
||||
|
||||
{ "[x]it!",
|
||||
{ "%.xit$" },
|
||||
{
|
||||
{ { "```[%w%s+-#]+", "```" }, "function", dynSyntax },
|
||||
{ { "%f[^%s%(]%-%>%s%d%d%d%d%-%d%d%-%d%d%f[\n%s%!%?%)]" }, "number" },
|
||||
{ { "%f[^%s%(]%-%>%s%d%d%d%d%/%d%d%/%d%d%f[\n%s%!%?%)]" }, "number" },
|
||||
{ { "%f[^%s%(]%-%>%s%d%d%d%d%-[wWqQ]?%d%d?%f[\n%s%!%?%)]" }, "number" },
|
||||
|
||||
@@ -45,7 +45,7 @@ void addYueScript() {
|
||||
"local|class|if|else|elseif|repeat|continue|break|using|import)\\s+)" },
|
||||
{ "normal", "normal", "keyword" },
|
||||
"",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "([%a_][%w_]*)(%s+not%s+in)" }, { "normal", "normal", "keyword" } },
|
||||
{ { "([%a_][%w_]*)(%s+%f[%[%$%a_])" }, { "normal", "function", "normal" } },
|
||||
{ { "(|>%s*)([%a_][%.%w_]*%.%s*)([%a_][%w_]*)" },
|
||||
@@ -55,16 +55,16 @@ void addYueScript() {
|
||||
"\\da-fA-F])*)?)" },
|
||||
{ "normal", "function", "number" },
|
||||
"",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "([a-zA-Z_]\\w*\\s+)(\\-?\\.\\d(?:_?\\d)*(?:[eE][\\+\\-]?\\d(?:_?\\d)*)?)" },
|
||||
{ "normal", "function", "number" },
|
||||
"",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "([a-zA-Z_]\\w*\\s+)(\\-?(?:\\d(?:_?\\d)*)(?:(?:\\.\\d(?:_?\\d)*(?:[eE][\\+\\-]?"
|
||||
"\\d(?:_?\\d)*)?)|[eE][\\+\\-]?\\d(?:_?\\d)*)?)" },
|
||||
{ "normal", "function", "number" },
|
||||
"",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "([%a_][%w_]*)(%??%s*!=)" }, { "normal", "normal", "operator" } },
|
||||
{ { "([%a_][%w_]*)(%??%s*!)" }, { "normal", "function", "operator" } },
|
||||
{ { "(::)([%a_][%w_]*)(::)" }, { "normal", "operator", "keyword2", "operator" } },
|
||||
@@ -73,13 +73,16 @@ void addYueScript() {
|
||||
{ { "\\-?0x[\\da-fA-F](?:_?[\\da-fA-F])*(?:\\.[\\da-fA-F](?:_?[\\da-fA-F])*)?" },
|
||||
"number",
|
||||
"",
|
||||
true },
|
||||
{ { "\\-?\\.\\d(?:_?\\d)*(?:[eE][\\+\\-]?\\d(?:_?\\d)*)?" }, "number", "", true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "\\-?\\.\\d(?:_?\\d)*(?:[eE][\\+\\-]?\\d(?:_?\\d)*)?" },
|
||||
"number",
|
||||
"",
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "\\-?(?:\\d(?:_?\\d)*)(?:(?:\\.\\d(?:_?\\d)*(?:[eE][\\+\\-]?\\d(?:_?\\d)*)?)|[eE]"
|
||||
"[\\+\\-]?\\d(?:_?\\d)*)?" },
|
||||
"number",
|
||||
"",
|
||||
true },
|
||||
SyntaxPatternMatchType::RegEx },
|
||||
{ { "@@?[%w_]*" }, "keyword2" },
|
||||
{ { "$[%w_]+" }, "keyword2" },
|
||||
{ { "[%a_][%w_]*" }, "symbol" },
|
||||
|
||||
@@ -223,11 +223,12 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
|
||||
"git" == creator.first || "debugger" == creator.first ||
|
||||
"aiassistant" == creator.first );
|
||||
}
|
||||
pluginManager->setPluginsEnabled( pluginsEnabled, sync );
|
||||
|
||||
languagesExtensions.priorities = ini.getKeyMap( "languages_extensions" );
|
||||
|
||||
iniInfo = FileInfo( ini.path() );
|
||||
|
||||
pluginManager->setPluginsEnabled( pluginsEnabled, sync );
|
||||
}
|
||||
|
||||
void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
@@ -372,6 +373,8 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
for ( const auto& langExt : languagesExtensions.priorities )
|
||||
ini.setValue( "languages_extensions", langExt.first, langExt.second );
|
||||
|
||||
pluginManager->forEachPlugin( [this]( Plugin* plugin ) { plugin->onSaveState( &iniState ); } );
|
||||
|
||||
ini.writeFile();
|
||||
iniState.writeFile();
|
||||
}
|
||||
|
||||
@@ -167,11 +167,45 @@ void AIAssistantPlugin::load( PluginManager* pluginManager ) {
|
||||
|
||||
TabWidgetCbs config;
|
||||
config.onLoad = [this]( const nlohmann::json& j ) {
|
||||
return TabWidgetData{ LLMChatUI::New( mManager ), getPluginContext()->findIcon( "code-ai" ),
|
||||
LLMChatUI* chatUI = LLMChatUI::New( mManager );
|
||||
|
||||
if ( j.contains( "uuid" ) && j.contains( "summary" ) ) {
|
||||
auto uuid = j.value( "uuid", "" );
|
||||
auto filePath = chatUI->getNewFilePath( uuid, j.value( "summary", "" ) );
|
||||
if ( filePath.empty() || !FileSystem::fileExists( filePath ) ) {
|
||||
auto conversationsPath = getConversationsPath();
|
||||
FileSystem::dirAddSlashAtEnd( conversationsPath );
|
||||
auto conversations = FileSystem::filesGetInPath( conversationsPath );
|
||||
|
||||
auto foundIt = std::find_if( conversations.begin(), conversations.end(),
|
||||
[&uuid]( const std::string& path ) {
|
||||
return String::startsWith( path, uuid );
|
||||
} );
|
||||
|
||||
if ( foundIt != conversations.end() )
|
||||
filePath = conversationsPath + *foundIt;
|
||||
}
|
||||
|
||||
if ( !filePath.empty() ) {
|
||||
std::string data;
|
||||
FileSystem::fileGet( filePath, data );
|
||||
auto j = nlohmann::json::parse( data, nullptr, false );
|
||||
chatUI->unserialize( j );
|
||||
}
|
||||
|
||||
chatUI->on( Event::OnDataChanged, [chatUI]( auto ) { chatUI->updateTabTitle(); } );
|
||||
}
|
||||
|
||||
return TabWidgetData{ chatUI, getPluginContext()->findIcon( "code-ai" ),
|
||||
i18n( "ai_assistant", "AI Assistant" ) };
|
||||
};
|
||||
config.onSave = []( UIWidget* widget ) {
|
||||
LLMChatUI* chatUI = static_cast<LLMChatUI*>( widget );
|
||||
nlohmann::json j;
|
||||
if ( chatUI->hasChat() ) {
|
||||
j["uuid"] = chatUI->getUUID().toString();
|
||||
j["summary"] = chatUI->getSummary();
|
||||
}
|
||||
return j;
|
||||
};
|
||||
|
||||
@@ -365,7 +399,7 @@ void AIAssistantPlugin::initUI() {
|
||||
mStatusButton->setClass( "status_but" );
|
||||
mStatusButton->setIcon( iconDrawable( "code-ai", 14 ) );
|
||||
mStatusButton->setTooltipText( i18n( "ai_assistant", "AI Assistant" ) );
|
||||
mStatusButton->on( Event::MouseClick, [this]( const Event* event ) { newAIAssistant(); } );
|
||||
mStatusButton->on( Event::MouseClick, [this]( const Event* ) { newAIAssistant(); } );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,4 +442,32 @@ std::optional<std::string> AIAssistantPlugin::getApiKeyFromProvider( const std::
|
||||
return {};
|
||||
}
|
||||
|
||||
void AIAssistantPlugin::onSaveState( IniFile* state ) {
|
||||
std::vector<LLMChatUI*> chats;
|
||||
LLMChatUI* mainChat{ nullptr };
|
||||
|
||||
getPluginContext()->getSplitter()->forEachWidgetClass(
|
||||
"llm_chatui", [&chats, &mainChat]( UIWidget* widget ) {
|
||||
LLMChatUI* chat = static_cast<LLMChatUI*>( widget );
|
||||
chats.emplace_back( chat );
|
||||
if ( widget->isVisible() && mainChat == nullptr )
|
||||
mainChat = chat;
|
||||
} );
|
||||
|
||||
if ( mainChat == nullptr && !chats.empty() )
|
||||
mainChat = chats[chats.size() - 1];
|
||||
|
||||
if ( mainChat == nullptr )
|
||||
return;
|
||||
|
||||
auto partition = mainChat->getSplitter()->getSplitPartition();
|
||||
auto modelProvider = mainChat->getCurModel().provider;
|
||||
auto modelName = mainChat->getCurModel().name;
|
||||
|
||||
const std::string keyname = "aiassistant";
|
||||
state->setValue( keyname, "split_partition", partition.toString() );
|
||||
state->setValue( keyname, "default_provider", modelProvider );
|
||||
state->setValue( keyname, "default_model", modelName );
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -38,6 +38,8 @@ class AIAssistantPlugin : public PluginBase {
|
||||
|
||||
LLMChatUI* newAIAssistant();
|
||||
|
||||
void onSaveState( IniFile* state ) override;
|
||||
|
||||
protected:
|
||||
LLMProviders mProviders;
|
||||
bool mUIInit{ false };
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "chatui.hpp"
|
||||
#include "../../appconfig.hpp"
|
||||
#include "../../notificationcenter.hpp"
|
||||
#include "aiassistantplugin.hpp"
|
||||
#include "chathistory.hpp"
|
||||
#include "chatui.hpp"
|
||||
#include "eepp/ui/uiloader.hpp"
|
||||
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
@@ -66,9 +68,6 @@ static const char* DEFAULT_LAYOUT = R"xml(
|
||||
border: 0;
|
||||
background-color: var(--tab-back);
|
||||
}
|
||||
.llm_chatui #llm_settings_but {
|
||||
tint: var(--floating-icon);
|
||||
}
|
||||
.llm_conversation {
|
||||
margin-bottom: 8dp;
|
||||
}
|
||||
@@ -103,11 +102,13 @@ CodeEditor.llm_chat_input {
|
||||
border-radius: 8dp;
|
||||
padding-bottom: 38dp;
|
||||
}
|
||||
.llm_chatui PushButton {
|
||||
.llm_chatui PushButton,
|
||||
.llm_chatui SelectButton {
|
||||
border-color: transparent;
|
||||
text-as-fallback: true;
|
||||
}
|
||||
.llm_chatui PushButton:hover {
|
||||
.llm_chatui PushButton:hover,
|
||||
.llm_chatui SelectButton:hover {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
.llm_conversation_opt PushButton {
|
||||
@@ -137,17 +138,19 @@ DropDownList.role_ui {
|
||||
<RelativeLayout lw="mp" class="llm_controls">
|
||||
<CodeEditor class="llm_chat_input" lw="mp" lh="mp" />
|
||||
<hbox lw="mp" lh="wc" layout_gravity="bottom|left" layout_margin="8dp" clip="false">
|
||||
<PushButton id="llm_user" class="llm_button" text="@string(user, User)" min-width="60dp" layout-margin-right="8dp" />
|
||||
<PushButton class="llm_button" text="@string(attach, Attach)" icon="icon(attach, 14dp)" min-width="32dp" />
|
||||
<PushButton id="llm_chat_history" class="llm_button" text="@string(chat_history, Chat History)" icon="icon(chat-history, 14dp)" min-width="32dp" />
|
||||
<PushButton id="llm_settings_but" text="@string(settings, Settings)" icon="icon(settings, 14dp)" tooltip="@string(settings, Settings)" margin-right="8dp" />
|
||||
<PushButton id="llm_user" class="llm_button" text="@string(user, User)" min-width="60dp" margin-right="8dp" />
|
||||
<!-- <PushButton class="llm_button" text="@string(attach, Attach)" tooltip="@string(attach, Attach)" icon="icon(attach, 14dp)" min-width="32dp" /> -->
|
||||
<PushButton id="llm_chat_history" class="llm_button" text="@string(chat_history, Chat History)" tooltip="@string(chat_history, Chat History)" icon="icon(chat-history, 14dp)" min-width="32dp" />
|
||||
<PushButton id="llm_settings_but" class="llm_button" text="@string(settings, Settings)" tooltip="@string(settings, Settings)" icon="icon(settings, 14dp)" min-width="32dp" />
|
||||
<PushButton id="llm_clone_chat" class="llm_button" text="@string(clone_current_conversation, Clone Current Conversation)" tooltip="@string(clone_current_chat, Clone Current Chat)" icon="icon(file-copy, 12dp)" min-width="32dp" />
|
||||
<hbox lw="0" lw8="1" lh="mp" layout_gravity="center" padding-left="8dp" padding-right="8dp">
|
||||
<DropDownList class="model_ui" lw="0" lw8="1" selected-index="0"></DropDownList>
|
||||
<PushButton id="refresh_model_ui" text="@string(refresh_model_ui, Refresh)" icon="icon(refresh, 14dp)" />
|
||||
</hbox>
|
||||
<PushButton id="llm_add_chat" class="llm_button" text="@string(add, Add)" icon="icon(add, 15dp)" min-width="32dp" layout-margin-right="8dp" />
|
||||
<PushButton id="llm_run" class="llm_button primary" text="@string(run, Run)" icon="icon(play-filled, 14dp)" />
|
||||
<PushButton id="llm_stop" class="llm_button primary" text="@string(stop, Stop)" icon="icon(stop, 12dp)" visible="false" enabled="false" />
|
||||
<SelectButton id="llm_private_chat" class="llm_button" tooltip="@string(private_chat, Toggle Private Chat)" icon="icon(chat-private, 14dp)" min-width="32dp" margin-right="8dp" select-on-click="true" />
|
||||
<PushButton id="llm_add_chat" class="llm_button" text="@string(add, Add)" tooltip="@string(add_message, Add Message)" icon="icon(add, 15dp)" min-width="32dp" layout-margin-right="8dp" />
|
||||
<PushButton id="llm_run" class="llm_button primary" text="@string(run, Run)" tooltip="@string(add_message_and_run_prompt, Add Message and Run Prompt)" icon="icon(play-filled, 14dp)" />
|
||||
<PushButton id="llm_stop" class="llm_button primary" text="@string(stop, Stop)" icon="icon(stop, 12dp)" min-width="32dp" visible="false" enabled="false" />
|
||||
</hbox>
|
||||
</RelativeLayout>
|
||||
</Splitter>
|
||||
@@ -165,7 +168,9 @@ static const char* DEFAULT_CHAT_GLOBE = R"xml(
|
||||
<PushButton class="move_down" text="@string(move_down, Move Down)" icon="icon(arrow-down-s, 12dp)" tooltip="@string(move_down, Move Down)" />
|
||||
<PushButton class="erase_but" text="@string(remove_chat, Remove Chat)" icon="icon(chrome-close, 10dp)" tooltip="@string(remove_chat, Remove Chat)" />
|
||||
</hbox>
|
||||
<CodeEditor class="data_ui" lw="mp" lh="32dp" />
|
||||
<CodeEditor class="data_ui" lw="mp" lh="32dp">
|
||||
<Image class="thinking" icon="icon(loader-2, 24dp)" visible="false" />
|
||||
</CodeEditor>
|
||||
</vbox>
|
||||
)xml";
|
||||
|
||||
@@ -173,7 +178,8 @@ LLMChatUI::LLMChatUI( PluginManager* manager ) : UILinearLayout(), mManager( man
|
||||
setClass( "llm_chatui" );
|
||||
setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
|
||||
getUISceneNode()->loadLayoutFromString( DEFAULT_LAYOUT, this );
|
||||
mChatSplitter =
|
||||
getUISceneNode()->loadLayoutFromString( DEFAULT_LAYOUT, this )->asType<UISplitter>();
|
||||
|
||||
mChatsList = findByClass( "llm_chats" );
|
||||
mModelDDL = findByClass<UIDropDownList>( "model_ui" );
|
||||
@@ -272,6 +278,27 @@ LLMChatUI::LLMChatUI( PluginManager* manager ) : UILinearLayout(), mManager( man
|
||||
}
|
||||
} );
|
||||
|
||||
mChatPrivate = find<UISelectButton>( "llm_private_chat" );
|
||||
mChatPrivate->on( Event::OnValueChange,
|
||||
[this]( auto ) { mChatIsPrivate = mChatPrivate->isSelected(); } );
|
||||
|
||||
mChatClone = find<UIPushButton>( "llm_clone_chat" );
|
||||
mChatClone->onClick( [this]( auto ) {
|
||||
if ( getPlugin() == nullptr )
|
||||
return;
|
||||
auto chats = findAllByClass( "llm_conversation" );
|
||||
if ( chats.empty() ) {
|
||||
getPlugin()->getPluginContext()->getNotificationCenter()->addNotification(
|
||||
i18n( "nothing_to_clone", "Nothing to Clone" ) );
|
||||
return;
|
||||
}
|
||||
auto* chatUI = getPlugin()->newAIAssistant();
|
||||
chatUI->unserialize( serialize() );
|
||||
chatUI->mUUID = UUID();
|
||||
chatUI->mSummary += i18n( "chat_cloned", " (cloned)" );
|
||||
updateTabTitle();
|
||||
} );
|
||||
|
||||
mChatHistory = find<UIPushButton>( "llm_chat_history" );
|
||||
mChatHistory->onClick( [this]( auto ) { showChatHistory(); } );
|
||||
|
||||
@@ -282,32 +309,61 @@ LLMChatUI::LLMChatUI( PluginManager* manager ) : UILinearLayout(), mManager( man
|
||||
setProviders( std::move( providers ) );
|
||||
mCurModel = getDefaultModel();
|
||||
|
||||
AppConfig& config = getPlugin()->getPluginContext()->getConfig();
|
||||
auto partition = config.iniState.getValue( "aiassistant", "split_partition", "" );
|
||||
|
||||
if ( !partition.empty() )
|
||||
mChatSplitter->setSplitPartition( StyleSheetLength::fromString( partition ) );
|
||||
|
||||
auto modelProvider = config.iniState.getValue( "aiassistant", "default_provider", "" );
|
||||
auto modelName = config.iniState.getValue( "aiassistant", "default_model", "" );
|
||||
|
||||
if ( !modelProvider.empty() && !modelName.empty() ) {
|
||||
auto modelOpt = getModel( modelProvider, modelName );
|
||||
if ( modelOpt ) {
|
||||
mCurModel = *modelOpt;
|
||||
}
|
||||
}
|
||||
|
||||
fillModelDropDownList( mModelDDL );
|
||||
}
|
||||
|
||||
std::optional<LLMModel> LLMChatUI::getModel( const std::string& provider,
|
||||
const std::string& modelName ) {
|
||||
auto providerIt = mProviders.find( provider );
|
||||
if ( providerIt != mProviders.end() ) {
|
||||
const auto& models = providerIt->second.models;
|
||||
auto modelIt =
|
||||
std::find_if( models.begin(), models.end(), [&modelName]( const LLMModel& model ) {
|
||||
return model.name == modelName;
|
||||
} );
|
||||
if ( modelIt != models.end() )
|
||||
return *modelIt;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void LLMChatUI::showChatHistory() {
|
||||
auto plugin = getPlugin();
|
||||
if ( plugin == nullptr )
|
||||
return;
|
||||
|
||||
UIWindow* win =
|
||||
UIWindow::NewOpt( UIMessageBox::WindowBaseContainerType::VERTICAL_LINEAR_LAYOUT );
|
||||
UIWindow* win = UIWindow::New();
|
||||
|
||||
win->setMinWindowSize( mDpSize.getWidth(), getUISceneNode()->getSize().getHeight() * 0.7f );
|
||||
win->setKeyBindingCommand( "closeWindow", [win, this] {
|
||||
win->closeWindow();
|
||||
setFocus();
|
||||
} );
|
||||
win->getKeyBindings().addKeybind( { KEY_ESCAPE }, "closeWindow" );
|
||||
win->setWindowFlags( UI_WIN_NO_DECORATION | UI_WIN_SHADOW |
|
||||
UI_WIN_MODAL | UI_WIN_EPHEMERAL );
|
||||
win->setWindowFlags( UI_WIN_SHADOW | UI_WIN_MODAL | UI_WIN_EPHEMERAL );
|
||||
win->setTitle( i18n( "ai_conversations_history", "AI Conversations History" ) );
|
||||
win->center();
|
||||
win->setId( UUID().toString() );
|
||||
|
||||
UITextInput* input = UITextInput::New();
|
||||
input->setParent( win->getContainer() );
|
||||
input->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
input->setHint( i18n( "search_chat_ellipsis", "Search Chat..." ) );
|
||||
input->setVisible( false );
|
||||
UILinearLayout* layout = UILinearLayout::NewVertical();
|
||||
layout->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
layout->setParent( win->getContainer() );
|
||||
|
||||
UILoader* loader = UILoader::New();
|
||||
loader->setId( "loader" );
|
||||
@@ -315,19 +371,26 @@ void LLMChatUI::showChatHistory() {
|
||||
loader->setOutlineThickness( 6 );
|
||||
loader->setParent( win->getContainer() );
|
||||
loader->setIndeterminate( true );
|
||||
loader->center();
|
||||
|
||||
UITextInput* input = UITextInput::New();
|
||||
input->setParent( layout );
|
||||
input->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent );
|
||||
input->setHint( i18n( "search_chat_ellipsis", "Search Chat..." ) );
|
||||
input->setVisible( false );
|
||||
|
||||
UITableView* tv = UITableView::New();
|
||||
tv->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::Fixed );
|
||||
tv->setLayoutWeight( 1 );
|
||||
tv->setParent( win->getContainer() );
|
||||
tv->setParent( layout );
|
||||
tv->setVisible( false );
|
||||
tv->setAutoColumnsWidth( true );
|
||||
tv->setFitAllColumnsToWidget( true );
|
||||
tv->setSetupCellCb( [this, tv]( UITableCell* cell ) {
|
||||
tv->setSetupCellCb( [this, tv, win]( UITableCell* cell ) {
|
||||
if ( cell->getCurIndex().column() != ChatHistoryModel::Remove )
|
||||
return;
|
||||
|
||||
cell->onClick( [this, tv, cell]( const MouseEvent* event ) {
|
||||
cell->onClick( [this, tv, cell, win]( const MouseEvent* ) {
|
||||
ChatHistoryModel* model = static_cast<ChatHistoryModel*>( tv->getModel() );
|
||||
auto summary =
|
||||
model->data( model->index( cell->getCurIndex().row(), ChatHistoryModel::Summary ) )
|
||||
@@ -338,6 +401,8 @@ void LLMChatUI::showChatHistory() {
|
||||
"Are you sure you want to remove \"%s?\"" )
|
||||
.toUtf8(),
|
||||
summary ) );
|
||||
msgBox->setParent( win );
|
||||
msgBox->center();
|
||||
msgBox->showWhenReady();
|
||||
msgBox->on( Event::OnConfirm,
|
||||
[model, cell]( auto ) { model->remove( cell->getCurIndex() ); } );
|
||||
@@ -570,11 +635,12 @@ nlohmann::json LLMChatUI::serializeChat( const LLMModel& model ) {
|
||||
}
|
||||
|
||||
nlohmann::json LLMChatUI::serialize() {
|
||||
mTimestamp = std::chrono::system_clock::to_time_t( std::chrono::system_clock::now() );
|
||||
nlohmann::json j;
|
||||
j["uuid"] = mUUID.toString();
|
||||
j["chat"] = serializeChat( mCurModel );
|
||||
j["provider"] = mCurModel.provider;
|
||||
j["timestamp"] = std::chrono::system_clock::to_time_t( std::chrono::system_clock::now() );
|
||||
j["timestamp"] = mTimestamp;
|
||||
j["summary"] = mSummary;
|
||||
return j;
|
||||
}
|
||||
@@ -630,15 +696,25 @@ LLMModel LLMChatUI::getDefaultModel() {
|
||||
return findModel( "openai", "gpt-4o" );
|
||||
}
|
||||
|
||||
void LLMChatUI::saveChat() {
|
||||
std::string LLMChatUI::getNewFilePath( const std::string& uuid, const std::string& summary ) const {
|
||||
auto plugin = getPlugin();
|
||||
if ( plugin == nullptr )
|
||||
return;
|
||||
if ( plugin == nullptr || mChatIsPrivate )
|
||||
return "";
|
||||
std::string conversationsPath = plugin->getConversationsPath();
|
||||
if ( !FileSystem::fileExists( conversationsPath ) )
|
||||
FileSystem::makeDir( conversationsPath, true );
|
||||
std::string path( conversationsPath + mUUID.toString() + " - " + mSummary + ".json" );
|
||||
FileSystem::fileWrite( path, serialize().dump( 2 ) );
|
||||
return conversationsPath + uuid + " - " + summary + ".json";
|
||||
}
|
||||
|
||||
std::string LLMChatUI::getFilePath() const {
|
||||
return getNewFilePath( mUUID.toString(), mSummary );
|
||||
}
|
||||
|
||||
void LLMChatUI::saveChat() {
|
||||
auto plugin = getPlugin();
|
||||
if ( plugin == nullptr || mChatIsPrivate )
|
||||
return;
|
||||
FileSystem::fileWrite( getFilePath(), serialize().dump( 2 ) );
|
||||
}
|
||||
|
||||
std::string LLMChatUI::prepareApiUrl( const std::string& apiKey ) {
|
||||
@@ -669,17 +745,38 @@ void LLMChatUI::doRequest() {
|
||||
|
||||
auto model = mCurModel;
|
||||
auto* editor = chat->findByClass<UICodeEditor>( "data_ui" );
|
||||
auto* thinking = editor->findByClass<UIImage>( "thinking" );
|
||||
auto thinkingID = String::hash( String::format( "thinking-%p", thinking ) );
|
||||
thinking->setVisible( true );
|
||||
thinking->setPosition( { PixelDensity::dpToPx( 16 ), PixelDensity::dpToPx( 4 ) } );
|
||||
thinking->setInterval( [thinking] { thinking->rotate( 360 / 32 ); }, Seconds( 0.125 ),
|
||||
thinkingID );
|
||||
|
||||
std::string apiUrl( prepareApiUrl( apiKeyStr ) );
|
||||
mRequest = std::make_unique<LLMChatCompletionRequest>(
|
||||
apiUrl, apiKeyStr, serializeChat( model ).dump(), model.provider );
|
||||
mRequest->streamedResponseCb = [this, editor]( const std::string& chunk ) {
|
||||
|
||||
mRequest->streamedResponseCb = [this, editor, thinking, thinkingID]( const std::string& chunk,
|
||||
bool fromReasoning ) {
|
||||
if ( fromReasoning )
|
||||
return;
|
||||
auto conversation = chunk;
|
||||
editor->runOnMainThread( [this, conversation = std::move( conversation ), editor] {
|
||||
editor->getDocument().textInput( String::fromUtf8( conversation ) );
|
||||
editor->setCursorVisible( false );
|
||||
resizeToFit( editor );
|
||||
} );
|
||||
editor->runOnMainThread(
|
||||
[this, conversation = std::move( conversation ), editor, thinking, thinkingID] {
|
||||
editor->getDocument().textInput( String::fromUtf8( conversation ) );
|
||||
editor->setCursorVisible( false );
|
||||
thinking->removeActionsByTag( thinkingID );
|
||||
thinking->setVisible( false );
|
||||
resizeToFit( editor );
|
||||
} );
|
||||
};
|
||||
|
||||
mRequest->cancelCb = [this, thinking, thinkingID]( const LLMChatCompletionRequest& ) {
|
||||
thinking->removeActionsByTag( thinkingID );
|
||||
thinking->setVisible( false );
|
||||
removeLastChat();
|
||||
};
|
||||
|
||||
mRequest->doneCb = [this, editor, apiUrl = std::move( apiUrl ),
|
||||
apiKeyStr = std::move( apiKeyStr ), model = std::move( model )](
|
||||
const LLMChatCompletionRequest&, Http::Response& response ) {
|
||||
@@ -709,7 +806,8 @@ void LLMChatUI::doRequest() {
|
||||
if ( editor->hasFocus() )
|
||||
mChatInput->setFocus();
|
||||
|
||||
if ( !mSummaryRequest && mSummary.empty() && status == Http::Response::Ok ) {
|
||||
if ( !mChatIsPrivate && !mSummaryRequest && mSummary.empty() &&
|
||||
status == Http::Response::Ok ) {
|
||||
static const std::string SummaryPrompt =
|
||||
"Generate a concise 3-7 word title for this conversation, omitting "
|
||||
"punctuation. Go "
|
||||
@@ -869,7 +967,7 @@ void LLMChatUI::showMsg( String msg ) {
|
||||
msgBox->showWhenReady();
|
||||
}
|
||||
|
||||
AIAssistantPlugin* LLMChatUI::getPlugin() {
|
||||
AIAssistantPlugin* LLMChatUI::getPlugin() const {
|
||||
auto plugin = mManager->get( "aiassistant" );
|
||||
if ( plugin )
|
||||
return reinterpret_cast<AIAssistantPlugin*>( plugin );
|
||||
@@ -903,4 +1001,12 @@ void LLMChatUI::updateTabTitle() {
|
||||
tab->setText( title );
|
||||
}
|
||||
|
||||
UISplitter* LLMChatUI::getSplitter() const {
|
||||
return mChatSplitter;
|
||||
}
|
||||
|
||||
const LLMModel& LLMChatUI::getCurModel() const {
|
||||
return mCurModel;
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -53,17 +53,38 @@ class LLMChatUI : public UILinearLayout {
|
||||
|
||||
void unserialize( const nlohmann::json& payload );
|
||||
|
||||
UISplitter* getSplitter() const;
|
||||
|
||||
const LLMModel& getCurModel() const;
|
||||
|
||||
const UUID& getUUID() const { return mUUID; }
|
||||
|
||||
const std::string& getSummary() const { return mSummary; }
|
||||
|
||||
long getTimestamp() const { return mTimestamp; }
|
||||
|
||||
bool hasChat() const { return getTimestamp() && !getSummary().empty(); }
|
||||
|
||||
std::string getNewFilePath( const std::string& uuid, const std::string& summary ) const;
|
||||
|
||||
std::string getFilePath() const;
|
||||
|
||||
void updateTabTitle();
|
||||
|
||||
protected:
|
||||
UUID mUUID;
|
||||
std::string mSummary;
|
||||
long mTimestamp;
|
||||
long mTimestamp{ 0 };
|
||||
PluginManager* mManager{ nullptr };
|
||||
UISplitter* mChatSplitter{ nullptr };
|
||||
UIWidget* mChatsList{ nullptr };
|
||||
UICodeEditor* mChatInput{ nullptr };
|
||||
UIPushButton* mChatUserRole{ nullptr };
|
||||
UIPushButton* mChatRun{ nullptr };
|
||||
UIPushButton* mChatStop{ nullptr };
|
||||
UIPushButton* mChatHistory{ nullptr };
|
||||
UIPushButton* mChatClone{ nullptr };
|
||||
UISelectButton* mChatPrivate{ nullptr };
|
||||
UIScrollView* mChatScrollView{ nullptr };
|
||||
UIDropDownList* mModelDDL{ nullptr };
|
||||
std::unique_ptr<LLMChatCompletionRequest> mRequest;
|
||||
@@ -72,6 +93,7 @@ class LLMChatUI : public UILinearLayout {
|
||||
LLMModel mCurModel;
|
||||
std::unordered_map<String::HashType, LLMModel> mModelsMap;
|
||||
int mPendingModelsToLoad{ 0 };
|
||||
bool mChatIsPrivate{ false };
|
||||
|
||||
LLMModel findModel( const std::string& provider, const std::string& model );
|
||||
|
||||
@@ -79,7 +101,7 @@ class LLMChatUI : public UILinearLayout {
|
||||
|
||||
LLMChatUI( PluginManager* manager );
|
||||
|
||||
AIAssistantPlugin* getPlugin();
|
||||
AIAssistantPlugin* getPlugin() const;
|
||||
|
||||
void showMsg( String msg );
|
||||
|
||||
@@ -119,14 +141,13 @@ class LLMChatUI : public UILinearLayout {
|
||||
|
||||
const LLMModel& getCheapestModelFromCurrentProvider() const;
|
||||
|
||||
std::optional<LLMModel> getModel( const std::string& provider, const std::string& modelName );
|
||||
|
||||
void saveChat();
|
||||
|
||||
void onInit();
|
||||
|
||||
void showChatHistory();
|
||||
|
||||
void updateTabTitle();
|
||||
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -24,6 +24,8 @@ LLMChatCompletionRequest::LLMChatCompletionRequest( const std::string& uri, cons
|
||||
const Http::Request::Status& status, size_t, size_t ) {
|
||||
if ( mCancel ) {
|
||||
mRequest.cancel();
|
||||
if ( cancelCb )
|
||||
cancelCb( *this );
|
||||
return false;
|
||||
}
|
||||
if ( status != Http::Request::ContentReceived )
|
||||
@@ -47,7 +49,7 @@ LLMChatCompletionRequest::LLMChatCompletionRequest( const std::string& uri, cons
|
||||
if ( delta.empty() )
|
||||
return;
|
||||
if ( streamedResponseCb )
|
||||
streamedResponseCb( delta );
|
||||
streamedResponseCb( delta, false );
|
||||
mResponse += std::move( delta );
|
||||
}
|
||||
}
|
||||
@@ -64,10 +66,14 @@ LLMChatCompletionRequest::LLMChatCompletionRequest( const std::string& uri, cons
|
||||
nlohmann::json& choices = data["choices"];
|
||||
|
||||
for ( const auto& choice : choices ) {
|
||||
if ( choice["delta"].contains( "content" ) ) {
|
||||
if ( choice["delta"].contains( "reasoning_content" ) ) {
|
||||
std::string delta = choice["delta"]["reasoning_content"];
|
||||
if ( streamedResponseCb )
|
||||
streamedResponseCb( delta, true );
|
||||
} else if ( choice["delta"].contains( "content" ) ) {
|
||||
std::string delta = choice["delta"]["content"];
|
||||
if ( streamedResponseCb )
|
||||
streamedResponseCb( delta );
|
||||
streamedResponseCb( delta, false );
|
||||
mResponse += std::move( delta );
|
||||
}
|
||||
}
|
||||
@@ -76,7 +82,7 @@ LLMChatCompletionRequest::LLMChatCompletionRequest( const std::string& uri, cons
|
||||
data["delta"].value( "type", "" ) == "text_delta" ) {
|
||||
std::string delta = data["delta"]["text"];
|
||||
if ( streamedResponseCb )
|
||||
streamedResponseCb( delta );
|
||||
streamedResponseCb( delta, false );
|
||||
mResponse += std::move( delta );
|
||||
}
|
||||
} );
|
||||
|
||||
@@ -14,15 +14,19 @@ namespace ecode {
|
||||
|
||||
class LLMChatCompletionRequest {
|
||||
public:
|
||||
using StreamedResponseCb = std::function<void( const std::string& chunk )>;
|
||||
using StreamedResponseCb = std::function<void( const std::string& chunk, bool fromReasoning )>;
|
||||
|
||||
using StreamedResponseDoneCb =
|
||||
std::function<void( const LLMChatCompletionRequest& request, Http::Response& )>;
|
||||
|
||||
using StreamedResponseCancelCb = std::function<void( const LLMChatCompletionRequest& request )>;
|
||||
|
||||
StreamedResponseCb streamedResponseCb;
|
||||
|
||||
StreamedResponseDoneCb doneCb;
|
||||
|
||||
StreamedResponseCancelCb cancelCb;
|
||||
|
||||
LLMChatCompletionRequest( const std::string& uri, const std::string& auth,
|
||||
const std::string& reqBody, const std::string& provider );
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ using namespace EE;
|
||||
using namespace EE::UI;
|
||||
using namespace EE::UI::Models;
|
||||
|
||||
namespace EE::System {
|
||||
class IniFile;
|
||||
}
|
||||
|
||||
namespace ecode {
|
||||
|
||||
class PluginManager;
|
||||
@@ -53,6 +57,8 @@ class Plugin : public UICodeEditorPlugin {
|
||||
void showMessage( LSPMessageType type, const std::string& message,
|
||||
const std::string& title = "" );
|
||||
|
||||
virtual void onSaveState( IniFile* state ) {}
|
||||
|
||||
virtual void onSaveProject( const std::string& /*projectFolder*/,
|
||||
const std::string& /*projectStatePath*/,
|
||||
bool /*rewriteStateOnlyIfNeeded*/ ) {}
|
||||
|
||||
Reference in New Issue
Block a user