diff --git a/include/eepp/scene/event.hpp b/include/eepp/scene/event.hpp index a86bd83b5..dd90accb4 100644 --- a/include/eepp/scene/event.hpp +++ b/include/eepp/scene/event.hpp @@ -117,6 +117,7 @@ class EE_API Event { OnModelChanged, OnWindowToFront, OnVisibleLinesCountChange, + OnDataChanged, NoEvent = eeINDEX_NOT_FOUND }; diff --git a/include/eepp/ui/doc/syntaxdefinition.hpp b/include/eepp/ui/doc/syntaxdefinition.hpp index ef4d5bb7c..a0165039e 100644 --- a/include/eepp/ui/doc/syntaxdefinition.hpp +++ b/include/eepp/ui/doc/syntaxdefinition.hpp @@ -26,6 +26,8 @@ template static auto toSyntaxStyleTypeV( const std::vector& s ) return std::vector{}; } +enum class SyntaxPatternMatchType { LuaPattern, RegEx }; + struct EE_API SyntaxPattern { static UnorderedMap SyntaxStyleTypeCache; @@ -37,19 +39,23 @@ struct EE_API SyntaxPattern { std::vector typesNames; std::string syntax{ "" }; DynamicSyntax dynSyntax; - bool isRegEx{ false }; + SyntaxPatternMatchType matchType{ SyntaxPatternMatchType::LuaPattern }; SyntaxPattern( std::vector&& _patterns, const std::string& _type, - const std::string& _syntax = "", bool isRegEx = false ); + const std::string& _syntax = "", + SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern ); SyntaxPattern( std::vector&& _patterns, std::vector&& _types, - const std::string& _syntax = "", bool isRegEx = false ); + const std::string& _syntax = "", + SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern ); SyntaxPattern( std::vector&& _patterns, const std::string& _type, - DynamicSyntax&& _syntax, bool isRegEx = false ); + DynamicSyntax&& _syntax, + SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern ); SyntaxPattern( std::vector&& _patterns, std::vector&& _types, - DynamicSyntax&& _syntax, bool isRegEx = false ); + DynamicSyntax&& _syntax, + SyntaxPatternMatchType matchType = SyntaxPatternMatchType::LuaPattern ); bool hasSyntax() const { return !syntax.empty() || dynSyntax; } }; diff --git a/include/eepp/ui/doc/syntaxtokenizer.hpp b/include/eepp/ui/doc/syntaxtokenizer.hpp index fc50ace9f..0d1d8a4bc 100644 --- a/include/eepp/ui/doc/syntaxtokenizer.hpp +++ b/include/eepp/ui/doc/syntaxtokenizer.hpp @@ -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; diff --git a/include/eepp/ui/tools/uicodeeditorsplitter.hpp b/include/eepp/ui/tools/uicodeeditorsplitter.hpp index f123b7fbe..6a3f13827 100644 --- a/include/eepp/ui/tools/uicodeeditorsplitter.hpp +++ b/include/eepp/ui/tools/uicodeeditorsplitter.hpp @@ -161,6 +161,9 @@ class EE_API UICodeEditorSplitter { void forEachWidgetClass( const std::string& className, std::function run ) const; + void forEachWidgetClassStoppable( const std::string& className, + std::function run ) const; + void forEachWidgetType( const UINodeType& nodeType, std::function run ) const; diff --git a/projects/linux/ee.files b/projects/linux/ee.files index b5ad83d06..5830bd3ba 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -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 diff --git a/src/eepp/scene/node.cpp b/src/eepp/scene/node.cpp index e92cdea76..76413af94 100644 --- a/src/eepp/scene/node.cpp +++ b/src/eepp/scene/node.cpp @@ -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; } diff --git a/src/eepp/ui/doc/languages/cpp.cpp b/src/eepp/ui/doc/languages/cpp.cpp index af9422ad3..f3f86f932 100644 --- a/src/eepp/ui/doc/languages/cpp.cpp +++ b/src/eepp/ui/doc/languages/cpp.cpp @@ -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" }, }, diff --git a/src/eepp/ui/doc/languages/css.cpp b/src/eepp/ui/doc/languages/css.cpp index 8f10c999d..e138cb8d2 100644 --- a/src/eepp/ui/doc/languages/css.cpp +++ b/src/eepp/ui/doc/languages/css.cpp @@ -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" }, diff --git a/src/eepp/ui/doc/syntaxdefinition.cpp b/src/eepp/ui/doc/syntaxdefinition.cpp index 00e11579e..4dad04f0e 100644 --- a/src/eepp/ui/doc/syntaxdefinition.cpp +++ b/src/eepp/ui/doc/syntaxdefinition.cpp @@ -259,44 +259,44 @@ const String::HashType& SyntaxDefinition::getLanguageId() const { } SyntaxPattern::SyntaxPattern( std::vector&& _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{ _type } ) ), typesNames( { _type } ), syntax( _syntax ), - isRegEx( isRegEx ) { + matchType( matchType ) { updateCache( *this ); } SyntaxPattern::SyntaxPattern( std::vector&& _patterns, std::vector&& _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( *this ); } SyntaxPattern::SyntaxPattern( std::vector&& _patterns, const std::string& _type, - DynamicSyntax&& _syntax, bool isRegEx ) : + DynamicSyntax&& _syntax, SyntaxPatternMatchType matchType ) : patterns( std::move( _patterns ) ), types( toSyntaxStyleTypeV( std::vector{ _type } ) ), typesNames( { _type } ), dynSyntax( std::move( _syntax ) ), - isRegEx( isRegEx ) { + matchType( matchType ) { updateCache( *this ); } SyntaxPattern::SyntaxPattern( std::vector&& _patterns, std::vector&& _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( *this ); } diff --git a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp index 4ecd79cf0..bab040a28 100644 --- a/src/eepp/ui/doc/syntaxdefinitionmanager.cpp +++ b/src/eepp/ui/doc/syntaxdefinitionmanager.cpp @@ -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" ) ) { diff --git a/src/eepp/ui/doc/syntaxtokenizer.cpp b/src/eepp/ui/doc/syntaxtokenizer.cpp index 248c6c57f..38c8a7fb7 100644 --- a/src/eepp/ui/doc/syntaxtokenizer.cpp +++ b/src/eepp/ui/doc/syntaxtokenizer.cpp @@ -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 wordsVar = - isRegEx ? std::variant( RegEx( pattern ) ) - : std::variant( LuaPattern( pattern ) ); + matchType == SyntaxPatternMatchType::RegEx + ? std::variant( RegEx( pattern ) ) + : std::variant( 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 wordsVar = - pattern.isRegEx ? std::variant( RegEx( patternStr ) ) - : std::variant( LuaPattern( patternStr ) ); + pattern.matchType == SyntaxPatternMatchType::RegEx + ? std::variant( RegEx( patternStr ) ) + : std::variant( LuaPattern( patternStr ) ); PatternMatcher& words = std::visit( []( auto& patternType ) -> PatternMatcher& { return patternType; }, wordsVar ); if ( !words.isValid() ) // Skip invalid patterns diff --git a/src/eepp/ui/iconmanager.cpp b/src/eepp/ui/iconmanager.cpp index 96f5416ee..befc24e40 100644 --- a/src/eepp/ui/iconmanager.cpp +++ b/src/eepp/ui/iconmanager.cpp @@ -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 ) diff --git a/src/eepp/ui/tools/uicodeeditorsplitter.cpp b/src/eepp/ui/tools/uicodeeditorsplitter.cpp index e8c0650f6..bb65e5fd7 100644 --- a/src/eepp/ui/tools/uicodeeditorsplitter.cpp +++ b/src/eepp/ui/tools/uicodeeditorsplitter.cpp @@ -786,6 +786,22 @@ void UICodeEditorSplitter::forEachWidgetClass( const std::string& className, } } +void UICodeEditorSplitter::forEachWidgetClassStoppable( + const std::string& className, std::function 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(); + if ( widget->hasClass( className ) && run( widget ) ) + return; + } + } + } +} + void UICodeEditorSplitter::forEachWidgetType( const UINodeType& nodeType, std::function run ) const { Node* node; diff --git a/src/eepp/ui/uitabwidget.cpp b/src/eepp/ui/uitabwidget.cpp index f8f513bf8..feebce2ff 100644 --- a/src/eepp/ui/uitabwidget.cpp +++ b/src/eepp/ui/uitabwidget.cpp @@ -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 ); diff --git a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/svelte.cpp b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/svelte.cpp index e5f687a5c..658504988 100644 --- a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/svelte.cpp +++ b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/svelte.cpp @@ -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{ "keyword", "keyword2" }, "", - true }, + SyntaxPatternMatchType::RegEx }, { { "{(/if|/each|/await|/key)}" }, std::vector{ "keyword", "keyword2" }, "", - true }, + SyntaxPatternMatchType::RegEx }, { { "{(#if|#each|#await|#key)", "}", "\\" }, std::vector{ "keyword", "keyword2", "normal" }, "JavaScript", - true }, + SyntaxPatternMatchType::RegEx }, { { "{", "}", "\\" }, "keyword", "JavaScript" }, { { "([%a_][%w_-]*)(:)([%a_][%w_-]*)(=)" }, { "keyword", "keyword2", "normal", "keyword", "operator" } }, diff --git a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xit.cpp b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xit.cpp index 223ffcfdb..706ecfaec 100644 --- a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xit.cpp +++ b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/xit.cpp @@ -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" }, diff --git a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yuescript.cpp b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yuescript.cpp index de1094745..a20bc4f01 100644 --- a/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yuescript.cpp +++ b/src/modules/languages-syntax-highlighting/src/eepp/ui/doc/languages/yuescript.cpp @@ -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" }, diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 0ed32cab4..c8d6e8cad 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -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& recentFiles, @@ -372,6 +373,8 @@ void AppConfig::save( const std::vector& 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(); } diff --git a/src/tools/ecode/plugins/aiassistant/aiassistantplugin.cpp b/src/tools/ecode/plugins/aiassistant/aiassistantplugin.cpp index c02cba657..6cfac3755 100644 --- a/src/tools/ecode/plugins/aiassistant/aiassistantplugin.cpp +++ b/src/tools/ecode/plugins/aiassistant/aiassistantplugin.cpp @@ -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( 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 AIAssistantPlugin::getApiKeyFromProvider( const std:: return {}; } +void AIAssistantPlugin::onSaveState( IniFile* state ) { + std::vector chats; + LLMChatUI* mainChat{ nullptr }; + + getPluginContext()->getSplitter()->forEachWidgetClass( + "llm_chatui", [&chats, &mainChat]( UIWidget* widget ) { + LLMChatUI* chat = static_cast( 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 diff --git a/src/tools/ecode/plugins/aiassistant/aiassistantplugin.hpp b/src/tools/ecode/plugins/aiassistant/aiassistantplugin.hpp index 1ca6f4c49..9ed50ee97 100644 --- a/src/tools/ecode/plugins/aiassistant/aiassistantplugin.hpp +++ b/src/tools/ecode/plugins/aiassistant/aiassistantplugin.hpp @@ -38,6 +38,8 @@ class AIAssistantPlugin : public PluginBase { LLMChatUI* newAIAssistant(); + void onSaveState( IniFile* state ) override; + protected: LLMProviders mProviders; bool mUIInit{ false }; diff --git a/src/tools/ecode/plugins/aiassistant/chatui.cpp b/src/tools/ecode/plugins/aiassistant/chatui.cpp index 27e067435..633884213 100644 --- a/src/tools/ecode/plugins/aiassistant/chatui.cpp +++ b/src/tools/ecode/plugins/aiassistant/chatui.cpp @@ -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 @@ -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 { - - - - + + + + + - - - + + + + @@ -165,7 +168,9 @@ static const char* DEFAULT_CHAT_GLOBE = R"xml( - + + + )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(); mChatsList = findByClass( "llm_chats" ); mModelDDL = findByClass( "model_ui" ); @@ -272,6 +278,27 @@ LLMChatUI::LLMChatUI( PluginManager* manager ) : UILinearLayout(), mManager( man } } ); + mChatPrivate = find( "llm_private_chat" ); + mChatPrivate->on( Event::OnValueChange, + [this]( auto ) { mChatIsPrivate = mChatPrivate->isSelected(); } ); + + mChatClone = find( "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( "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 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( 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( "data_ui" ); + auto* thinking = editor->findByClass( "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( 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( 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 diff --git a/src/tools/ecode/plugins/aiassistant/chatui.hpp b/src/tools/ecode/plugins/aiassistant/chatui.hpp index 53d43bd2a..65183a1e9 100644 --- a/src/tools/ecode/plugins/aiassistant/chatui.hpp +++ b/src/tools/ecode/plugins/aiassistant/chatui.hpp @@ -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 mRequest; @@ -72,6 +93,7 @@ class LLMChatUI : public UILinearLayout { LLMModel mCurModel; std::unordered_map 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 getModel( const std::string& provider, const std::string& modelName ); + void saveChat(); void onInit(); void showChatHistory(); - - void updateTabTitle(); - }; } // namespace ecode diff --git a/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.cpp b/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.cpp index 7d62e91e4..9f534ff3c 100644 --- a/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.cpp +++ b/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.cpp @@ -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 ); } } ); diff --git a/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.hpp b/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.hpp index a148ea4c0..7d82f4fb7 100644 --- a/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.hpp +++ b/src/tools/ecode/plugins/aiassistant/llmchatcompletionrequest.hpp @@ -14,15 +14,19 @@ namespace ecode { class LLMChatCompletionRequest { public: - using StreamedResponseCb = std::function; + using StreamedResponseCb = std::function; using StreamedResponseDoneCb = std::function; + using StreamedResponseCancelCb = std::function; + StreamedResponseCb streamedResponseCb; StreamedResponseDoneCb doneCb; + StreamedResponseCancelCb cancelCb; + LLMChatCompletionRequest( const std::string& uri, const std::string& auth, const std::string& reqBody, const std::string& provider ); diff --git a/src/tools/ecode/plugins/plugin.hpp b/src/tools/ecode/plugins/plugin.hpp index c7d485efb..66ca452f4 100644 --- a/src/tools/ecode/plugins/plugin.hpp +++ b/src/tools/ecode/plugins/plugin.hpp @@ -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*/ ) {}