mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-02 03:00:23 +03:00
ecode: add structured settings pages for plugins
- introduce reusable settings models, documents, and plugin settings pages - expose all registered plugin configuration options in the Settings panel - support groups, choices, editable values, lists, secrets, and JSON objects - stage plugin changes and persist them when the Settings window closes - preserve raw JSON access for advanced configuration - safely migrate legacy AI provider API keys - add translated plugin setting labels and descriptions - remove the obsolete plugin GUI configuration API - fix autocomplete signature documentation persistence - fix AI model catalog refresh interval loading
This commit is contained in:
+108
-3
@@ -47,7 +47,6 @@ Diese Operation kann nicht rückgängig gemacht werden!</string>
|
||||
<string name="author">Autor</string>
|
||||
<string name="auto_close_brackets_and_tags">Klammern & Tags automatisch vervollständigen</string>
|
||||
<string name="auto_close_xml_tags">XML-Tags automatisch vervollständigen</string>
|
||||
<string name="auto_close_brackets_and_tags">Klammern & Tags automatisch vervollständigen</string>
|
||||
<string name="auto_detect_indent_type_and_width">Einzugsart- & weite automatisch erkennen</string>
|
||||
<string name="autoreload_on_disk_change">Auto-Auffrischen bei Dateiänderung im Festspeicher</string>
|
||||
<string name="back_quotes">Backticks ``</string>
|
||||
@@ -267,6 +266,8 @@ Soll es jetzt heruntergeladen werden?</string>
|
||||
<string name="edit">Bearbeiten</string>
|
||||
<string name="edit_build">Build bearbeiten</string>
|
||||
<string name="edit_custom_output_parser">Angewählten individuellen Output-Parser bearbeiten</string>
|
||||
<string name="edit_settings_json">JSON-Einstellungen bearbeiten</string>
|
||||
<string name="edit_settings_json_desc">Vollständige Plugin-Konfigurationsdatei öffnen.</string>
|
||||
<string name="editor_font_and_size_ellipsis">Editor-Schriftart und -größe...</string>
|
||||
<string name="editor_font_features">Editor-Schriftfunktionen</string>
|
||||
<string name="ui_font_features">UI-Schriftfunktionen</string>
|
||||
@@ -279,7 +280,6 @@ Soll es jetzt heruntergeladen werden?</string>
|
||||
<string name="discretionary_ligatures">Optionale Ligaturen (dlig)</string>
|
||||
<string name="discretionary_ligatures_desc">Optionale dekorative oder stilistische Ligaturen der Schriftart.</string>
|
||||
<string name="editor_font_size">Editor-Schriftgröße</string>
|
||||
<string name="editor_font_features">Editor-Schriftfunktionen</string>
|
||||
<string name="editor_go_back">Editor: Schritt zurück</string>
|
||||
<string name="editor_go_forward">Editor: Schritt nach vorn</string>
|
||||
<string name="empty_file_name">Der Dateiname darf nicht leer sein.</string>
|
||||
@@ -486,6 +486,22 @@ Beachten Sie, dass der Großteil der Tastenzuweisungen hier definiert wird.</str
|
||||
<string name="lsp_memory_usage">LSP: Speichernutzung</string>
|
||||
<string name="lsp_plugin_restart">LSP: Plugin-Neustart</string>
|
||||
<string name="lsp_refresh_semantic_highlighting">LSP: Semantische Markierungen aktualisieren</string>
|
||||
<string name="lsp_breadcrumb_navigation">Breadcrumb-Navigation</string>
|
||||
<string name="lsp_breadcrumb_navigation_desc">Sprachbezogene Breadcrumb-Navigation über dem Editor anzeigen.</string>
|
||||
<string name="lsp_breadcrumb_height">Breadcrumb-Höhe</string>
|
||||
<string name="lsp_breadcrumb_height_desc">Höhe der Editor-Breadcrumb-Navigation als CSS-Längenangabe.</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang">Semantische Hervorhebung für Sprachen deaktivieren</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang_desc">Kommagetrennte Sprachkennungen, für die semantische Hervorhebung deaktiviert ist.</string>
|
||||
<string name="lsp_hover_delay">Hover-Verzögerung</string>
|
||||
<string name="lsp_hover_delay_desc">Wartezeit vor der Anzeige von Sprachserver-Informationen beim Darüberfahren.</string>
|
||||
<string name="lsp_semantic_highlighting">Semantische Hervorhebung</string>
|
||||
<string name="lsp_semantic_highlighting_desc">Semantische Tokens von Sprachservern verwenden, wenn verfügbar.</string>
|
||||
<string name="lsp_server_close_after_idle_time">Server nach Leerlauf schließen</string>
|
||||
<string name="lsp_server_close_after_idle_time_desc">Zeit, die ein ungenutzter Sprachserver vor dem Schließen weiterläuft.</string>
|
||||
<string name="lsp_silent">Sprachserver-Protokolle unterdrücken</string>
|
||||
<string name="lsp_silent_desc">Unkritische Sprachserver-Protokollmeldungen ausblenden.</string>
|
||||
<string name="lsp_trim_logs">Sprachserver-Protokolle kürzen</string>
|
||||
<string name="lsp_trim_logs_desc">Jede Sprachserver-Protokollzeile auf 1 KiB begrenzen.</string>
|
||||
<string name="lsp_rename_symbol_under_cursor">LSP: Symbol unter Eingabemarke umbenennen</string>
|
||||
<string name="lsp_restart_lsp_client">LSP-Client neu starten</string>
|
||||
<string name="lsp_show_document_symbols">LSP: Dokumentsymbole anzeigen</string>
|
||||
@@ -607,6 +623,7 @@ in einem neuen Fenster geöffnet werden.</string>
|
||||
<string name="pick_widget">Widget wählen</string>
|
||||
<string name="please_enter_file_url_ellipsis">Bitte Datei-URL eingeben...</string>
|
||||
<string name="plugin_manager">Erweiterungsverwaltung</string>
|
||||
<string name="plugins">Plugins</string>
|
||||
<string name="plugin_manager_open">Erweiterungsverwaltung öffnen</string>
|
||||
<string name="pluginsmodel_description">Beschreibung</string>
|
||||
<string name="pluginsmodel_enabled">Aktiviert</string>
|
||||
@@ -843,7 +860,6 @@ in der Baumansicht und in Öffen-/Schließdialogen aktivieren.</string>
|
||||
<string name="type_to_locate">Zu findender Typ</string>
|
||||
<string name="ui_font_and_size_ellipsis">Schriftart und -größe der Oberfläche...</string>
|
||||
<string name="ui_font_size">Schriftgröße der Oberfläche</string>
|
||||
<string name="ui_font_features">UI-Schriftfunktionen</string>
|
||||
<string name="ui_language">Sprache der Oberfläche</string>
|
||||
<string name="ui_multisamples_level">Multisample-Antialiasing-Stufe</string>
|
||||
<string name="ui_panel_font_size">Schriftgröße im Paneel der Oberfläche</string>
|
||||
@@ -1105,4 +1121,93 @@ Für sichtbare Änderung ecode neu starten.</string>
|
||||
<string name="vsync_desc">Synchronisiert die Darstellung mit der Bildwiederholrate. Neustart erforderlich.</string>
|
||||
<string name="warn_before_closing_tab">Vor dem Schließen des Tabs warnen</string>
|
||||
<string name="warn_before_closing_tab_tooltip">Fragt vor dem Schließen eines Terminals mit laufendem Programm nach.</string>
|
||||
<string name="aiassistant_api_key_anthropic">Anthropic API Key</string>
|
||||
<string name="aiassistant_api_key_deepseek">DeepSeek API Key</string>
|
||||
<string name="aiassistant_api_key_desc">Credential used to access this model provider.</string>
|
||||
<string name="aiassistant_api_key_github">GitHub Models API Key</string>
|
||||
<string name="aiassistant_api_key_google">Google AI API Key</string>
|
||||
<string name="aiassistant_api_key_mistral">Mistral API Key</string>
|
||||
<string name="aiassistant_api_key_moonshotai">Moonshot AI API Key</string>
|
||||
<string name="aiassistant_api_key_nvidia">NVIDIA API Key</string>
|
||||
<string name="aiassistant_api_key_openai">OpenAI API Key</string>
|
||||
<string name="aiassistant_api_key_openrouter">OpenRouter API Key</string>
|
||||
<string name="aiassistant_api_key_perplexity">Perplexity API Key</string>
|
||||
<string name="aiassistant_api_key_togetherai">Together AI API Key</string>
|
||||
<string name="aiassistant_api_key_xai">xAI API Key</string>
|
||||
<string name="aiassistant_api_key_xiaomi">Xiaomi MiMo API Key</string>
|
||||
<string name="aiassistant_api_keys">API Keys</string>
|
||||
<string name="aiassistant_display_reasoning">Display Reasoning</string>
|
||||
<string name="aiassistant_display_reasoning_desc">Display reasoning content returned by supported models.</string>
|
||||
<string name="aiassistant_model_catalog_enabled">Enable Model Catalog</string>
|
||||
<string name="aiassistant_model_catalog_enabled_desc">Download model metadata from the configured catalog.</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours">Model Catalog Refresh Interval</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours_desc">Hours between model catalog refreshes.</string>
|
||||
<string name="aiassistant_model_catalog_url">Model Catalog URL</string>
|
||||
<string name="aiassistant_model_catalog_url_desc">URL used to download model catalog metadata.</string>
|
||||
<string name="autocomplete_load_vscode_snippets">Load VS Code Snippets</string>
|
||||
<string name="autocomplete_load_vscode_snippets_desc">Load compatible snippets installed for VS Code.</string>
|
||||
<string name="autocomplete_max_label_characters">Maximum Label Characters</string>
|
||||
<string name="autocomplete_max_label_characters_desc">Maximum number of characters shown in a suggestion label.</string>
|
||||
<string name="autocomplete_max_signature_helper_width">Maximum Signature Help Width</string>
|
||||
<string name="autocomplete_max_signature_helper_width_desc">Maximum signature help popup width as a CSS length.</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width">Maximum Suggestion Documentation Width</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width_desc">Maximum documentation popup width as a CSS length.</string>
|
||||
<string name="autocomplete_signature_help_documentation">Signature Help Documentation</string>
|
||||
<string name="autocomplete_signature_help_documentation_desc">Show documentation alongside signature help.</string>
|
||||
<string name="autocomplete_signature_help_multi_line">Multiline Signature Help</string>
|
||||
<string name="autocomplete_signature_help_multi_line_desc">Allow signature help to use multiple lines.</string>
|
||||
<string name="autocomplete_suggestion_documentation">Suggestion Documentation</string>
|
||||
<string name="autocomplete_suggestion_documentation_desc">Show documentation alongside completion suggestions.</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight">Syntax Highlight Suggestions</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight_desc">Apply syntax highlighting to completion suggestions.</string>
|
||||
<string name="debugger_fetch_globals">Fetch Global Variables</string>
|
||||
<string name="debugger_fetch_globals_desc">Request global variables while debugging.</string>
|
||||
<string name="debugger_fetch_registers">Fetch Registers</string>
|
||||
<string name="debugger_fetch_registers_desc">Request processor registers while debugging.</string>
|
||||
<string name="debugger_load_vscode_launch_config">Load VS Code Launch Configuration</string>
|
||||
<string name="debugger_load_vscode_launch_config_desc">Load compatible launch configurations from .vscode/launch.json.</string>
|
||||
<string name="debugger_silent">Silent Debugger Logs</string>
|
||||
<string name="debugger_silent_desc">Hide non-critical debugger log messages.</string>
|
||||
<string name="discordrpc_application_id">Discord Application ID</string>
|
||||
<string name="discordrpc_application_id_desc">Discord application identifier used for Rich Presence.</string>
|
||||
<string name="discordrpc_git_integration">Git Integration</string>
|
||||
<string name="discordrpc_git_integration_desc">Include repository information in Rich Presence.</string>
|
||||
<string name="discordrpc_icon_bindings">Language Icon Bindings</string>
|
||||
<string name="discordrpc_icon_bindings_desc">JSON object mapping language identifiers to Discord image assets.</string>
|
||||
<string name="discordrpc_language_icons">Language Icons</string>
|
||||
<string name="discordrpc_language_icons_desc">Display an icon for the active document language.</string>
|
||||
<string name="formatter_auto_format_on_save">Format on Save</string>
|
||||
<string name="formatter_auto_format_on_save_desc">Automatically format supported documents when saving.</string>
|
||||
<string name="git_filetree_highlight_changes">Highlight File Tree Changes</string>
|
||||
<string name="git_filetree_highlight_changes_desc">Highlight files with Git changes in the file tree.</string>
|
||||
<string name="git_filetree_highlight_style_color">File Tree Highlight Color</string>
|
||||
<string name="git_filetree_highlight_style_color_desc">CSS color used to highlight changed files.</string>
|
||||
<string name="git_silent">Silent Git Logs</string>
|
||||
<string name="git_silent_desc">Hide non-critical Git plugin log messages.</string>
|
||||
<string name="git_status_recurse_submodules">Recurse into Submodules</string>
|
||||
<string name="git_status_recurse_submodules_desc">Include submodule changes when collecting repository status.</string>
|
||||
<string name="git_statusbar_display_branch">Show Branch in Status Bar</string>
|
||||
<string name="git_statusbar_display_branch_desc">Display the current Git branch in the status bar.</string>
|
||||
<string name="git_statusbar_display_modifications">Show Modifications in Status Bar</string>
|
||||
<string name="git_statusbar_display_modifications_desc">Display repository modification counts in the status bar.</string>
|
||||
<string name="git_ui_refresh_frequency">Refresh Frequency</string>
|
||||
<string name="git_ui_refresh_frequency_desc">How often Git information in the interface is refreshed.</string>
|
||||
<string name="linter_delay_time">Lint Delay</string>
|
||||
<string name="linter_delay_time_desc">Time to wait before linting after an edit.</string>
|
||||
<string name="linter_disable_languages">Disable Linter Languages</string>
|
||||
<string name="linter_disable_languages_desc">Comma-separated language identifiers where linters are disabled.</string>
|
||||
<string name="linter_disable_lsp_languages">Disable LSP Diagnostic Languages</string>
|
||||
<string name="linter_disable_lsp_languages_desc">Comma-separated language identifiers where LSP diagnostics are disabled.</string>
|
||||
<string name="linter_enable_error_lens">Error Lens</string>
|
||||
<string name="linter_enable_error_lens_desc">Display diagnostic messages inline in the editor.</string>
|
||||
<string name="linter_enable_lsp_diagnostics">Language Server Diagnostics</string>
|
||||
<string name="linter_enable_lsp_diagnostics_desc">Display diagnostics reported by language servers.</string>
|
||||
<string name="linter_goto_ignore_warnings">Ignore Warnings When Navigating</string>
|
||||
<string name="linter_goto_ignore_warnings_desc">Skip warnings when navigating between diagnostics.</string>
|
||||
<string name="spellchecker_delay_time">Spell Check Delay</string>
|
||||
<string name="spellchecker_delay_time_desc">Time to wait before checking spelling after an edit.</string>
|
||||
<string name="xmltools_auto_edit_match">Edit Matching Tags</string>
|
||||
<string name="xmltools_auto_edit_match_desc">Update the matching tag automatically while editing.</string>
|
||||
<string name="xmltools_highlight_match">Highlight Matching Tags</string>
|
||||
<string name="xmltools_highlight_match_desc">Highlight the matching XML or HTML tag at the cursor.</string>
|
||||
</resources>
|
||||
|
||||
+108
-3
@@ -31,7 +31,6 @@ This operation cannot be reverted!</string>
|
||||
<string name="author">Author</string>
|
||||
<string name="auto_close_brackets_and_tags">Auto-Close Brackets & Tags</string>
|
||||
<string name="auto_close_xml_tags">Auto Close XML Tags</string>
|
||||
<string name="auto_close_brackets_and_tags">Auto-Close Brackets & Tags</string>
|
||||
<string name="auto_detect_indent_type_and_width">Auto Detect Indent Type & Width</string>
|
||||
<string name="autoreload_on_disk_change">Auto-Reload on Disk Change</string>
|
||||
<string name="back_quotes">Back Quotes ``</string>
|
||||
@@ -251,6 +250,8 @@ Do you want to download it now?</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="edit_build">Edit Build</string>
|
||||
<string name="edit_custom_output_parser">Edit Selected Custom Output Parser</string>
|
||||
<string name="edit_settings_json">Edit Settings JSON</string>
|
||||
<string name="edit_settings_json_desc">Open the complete plugin configuration file.</string>
|
||||
<string name="editor_font_and_size_ellipsis">Editor Font & Size...</string>
|
||||
<string name="editor_font_features">Editor Font Features</string>
|
||||
<string name="ui_font_features">UI Font Features</string>
|
||||
@@ -263,7 +264,6 @@ Do you want to download it now?</string>
|
||||
<string name="discretionary_ligatures">Discretionary Ligatures (dlig)</string>
|
||||
<string name="discretionary_ligatures_desc">Optional decorative or stylistic ligatures provided by the font.</string>
|
||||
<string name="editor_font_size">Editor Font Size</string>
|
||||
<string name="editor_font_features">Editor Font Features</string>
|
||||
<string name="editor_go_back">Editor Go Back</string>
|
||||
<string name="editor_go_forward">Editor Go Forward</string>
|
||||
<string name="empty_file_name">You must set a name to the file.</string>
|
||||
@@ -470,6 +470,22 @@ Be aware that many of the core keybindings can be found there.</string>
|
||||
<string name="lsp_memory_usage">Lsp Memory Usage</string>
|
||||
<string name="lsp_plugin_restart">Lsp Plugin Restart</string>
|
||||
<string name="lsp_refresh_semantic_highlighting">Lsp Refresh Semantic Highlighting</string>
|
||||
<string name="lsp_breadcrumb_navigation">Breadcrumb Navigation</string>
|
||||
<string name="lsp_breadcrumb_navigation_desc">Display language-aware breadcrumb navigation above the editor.</string>
|
||||
<string name="lsp_breadcrumb_height">Breadcrumb Height</string>
|
||||
<string name="lsp_breadcrumb_height_desc">Height of the editor breadcrumb using a CSS length.</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang">Disable Semantic Highlighting Languages</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang_desc">Comma-separated language identifiers where semantic highlighting is disabled.</string>
|
||||
<string name="lsp_hover_delay">Hover Delay</string>
|
||||
<string name="lsp_hover_delay_desc">Time to wait before showing language server information while hovering.</string>
|
||||
<string name="lsp_semantic_highlighting">Semantic Highlighting</string>
|
||||
<string name="lsp_semantic_highlighting_desc">Use semantic tokens provided by language servers when available.</string>
|
||||
<string name="lsp_server_close_after_idle_time">Server Close After Idle Time</string>
|
||||
<string name="lsp_server_close_after_idle_time_desc">Time to keep an unused language server running before closing it.</string>
|
||||
<string name="lsp_silent">Silent Language Server Logs</string>
|
||||
<string name="lsp_silent_desc">Hide non-critical language server log messages.</string>
|
||||
<string name="lsp_trim_logs">Trim Language Server Logs</string>
|
||||
<string name="lsp_trim_logs_desc">Limit each language server log line to 1 KiB.</string>
|
||||
<string name="lsp_rename_symbol_under_cursor">Lsp Rename Symbol Under Cursor</string>
|
||||
<string name="lsp_restart_lsp_client">Restart LSP Client</string>
|
||||
<string name="lsp_show_document_symbols">Lsp Show Document Symbols</string>
|
||||
@@ -591,6 +607,7 @@ controls whether a new window is created or not.</string>
|
||||
<string name="pick_widget">Pick Widget</string>
|
||||
<string name="please_enter_file_url_ellipsis">Please enter the file URL...</string>
|
||||
<string name="plugin_manager">Plugins Manager</string>
|
||||
<string name="plugins">Plugins</string>
|
||||
<string name="plugin_manager_open">Plugin Manager Open</string>
|
||||
<string name="pluginsmodel_description">Description</string>
|
||||
<string name="pluginsmodel_enabled">Enabled</string>
|
||||
@@ -828,7 +845,6 @@ the directory tree and in file dialogs to open a folder or file.</string>
|
||||
<string name="type_to_locate">Type to Locate</string>
|
||||
<string name="ui_font_and_size_ellipsis">UI Font & Size...</string>
|
||||
<string name="ui_font_size">Ui Font Size</string>
|
||||
<string name="ui_font_features">UI Font Features</string>
|
||||
<string name="ui_language">UI Language</string>
|
||||
<string name="ui_multisamples_level">Multisample Anti-Aliasing Level</string>
|
||||
<string name="ui_panel_font_size">Ui Panel Font Size</string>
|
||||
@@ -1090,4 +1106,93 @@ Restart ecode to see the changes.</string>
|
||||
<string name="vsync_desc">Synchronize rendering with the display refresh rate. Restart required.</string>
|
||||
<string name="warn_before_closing_tab">Warn Before Closing Tab</string>
|
||||
<string name="warn_before_closing_tab_tooltip">Ask before closing a terminal while a program is running.</string>
|
||||
<string name="aiassistant_api_key_anthropic">Anthropic API Key</string>
|
||||
<string name="aiassistant_api_key_deepseek">DeepSeek API Key</string>
|
||||
<string name="aiassistant_api_key_desc">Credential used to access this model provider.</string>
|
||||
<string name="aiassistant_api_key_github">GitHub Models API Key</string>
|
||||
<string name="aiassistant_api_key_google">Google AI API Key</string>
|
||||
<string name="aiassistant_api_key_mistral">Mistral API Key</string>
|
||||
<string name="aiassistant_api_key_moonshotai">Moonshot AI API Key</string>
|
||||
<string name="aiassistant_api_key_nvidia">NVIDIA API Key</string>
|
||||
<string name="aiassistant_api_key_openai">OpenAI API Key</string>
|
||||
<string name="aiassistant_api_key_openrouter">OpenRouter API Key</string>
|
||||
<string name="aiassistant_api_key_perplexity">Perplexity API Key</string>
|
||||
<string name="aiassistant_api_key_togetherai">Together AI API Key</string>
|
||||
<string name="aiassistant_api_key_xai">xAI API Key</string>
|
||||
<string name="aiassistant_api_key_xiaomi">Xiaomi MiMo API Key</string>
|
||||
<string name="aiassistant_api_keys">API Keys</string>
|
||||
<string name="aiassistant_display_reasoning">Display Reasoning</string>
|
||||
<string name="aiassistant_display_reasoning_desc">Display reasoning content returned by supported models.</string>
|
||||
<string name="aiassistant_model_catalog_enabled">Enable Model Catalog</string>
|
||||
<string name="aiassistant_model_catalog_enabled_desc">Download model metadata from the configured catalog.</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours">Model Catalog Refresh Interval</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours_desc">Hours between model catalog refreshes.</string>
|
||||
<string name="aiassistant_model_catalog_url">Model Catalog URL</string>
|
||||
<string name="aiassistant_model_catalog_url_desc">URL used to download model catalog metadata.</string>
|
||||
<string name="autocomplete_load_vscode_snippets">Load VS Code Snippets</string>
|
||||
<string name="autocomplete_load_vscode_snippets_desc">Load compatible snippets installed for VS Code.</string>
|
||||
<string name="autocomplete_max_label_characters">Maximum Label Characters</string>
|
||||
<string name="autocomplete_max_label_characters_desc">Maximum number of characters shown in a suggestion label.</string>
|
||||
<string name="autocomplete_max_signature_helper_width">Maximum Signature Help Width</string>
|
||||
<string name="autocomplete_max_signature_helper_width_desc">Maximum signature help popup width as a CSS length.</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width">Maximum Suggestion Documentation Width</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width_desc">Maximum documentation popup width as a CSS length.</string>
|
||||
<string name="autocomplete_signature_help_documentation">Signature Help Documentation</string>
|
||||
<string name="autocomplete_signature_help_documentation_desc">Show documentation alongside signature help.</string>
|
||||
<string name="autocomplete_signature_help_multi_line">Multiline Signature Help</string>
|
||||
<string name="autocomplete_signature_help_multi_line_desc">Allow signature help to use multiple lines.</string>
|
||||
<string name="autocomplete_suggestion_documentation">Suggestion Documentation</string>
|
||||
<string name="autocomplete_suggestion_documentation_desc">Show documentation alongside completion suggestions.</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight">Syntax Highlight Suggestions</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight_desc">Apply syntax highlighting to completion suggestions.</string>
|
||||
<string name="debugger_fetch_globals">Fetch Global Variables</string>
|
||||
<string name="debugger_fetch_globals_desc">Request global variables while debugging.</string>
|
||||
<string name="debugger_fetch_registers">Fetch Registers</string>
|
||||
<string name="debugger_fetch_registers_desc">Request processor registers while debugging.</string>
|
||||
<string name="debugger_load_vscode_launch_config">Load VS Code Launch Configuration</string>
|
||||
<string name="debugger_load_vscode_launch_config_desc">Load compatible launch configurations from .vscode/launch.json.</string>
|
||||
<string name="debugger_silent">Silent Debugger Logs</string>
|
||||
<string name="debugger_silent_desc">Hide non-critical debugger log messages.</string>
|
||||
<string name="discordrpc_application_id">Discord Application ID</string>
|
||||
<string name="discordrpc_application_id_desc">Discord application identifier used for Rich Presence.</string>
|
||||
<string name="discordrpc_git_integration">Git Integration</string>
|
||||
<string name="discordrpc_git_integration_desc">Include repository information in Rich Presence.</string>
|
||||
<string name="discordrpc_icon_bindings">Language Icon Bindings</string>
|
||||
<string name="discordrpc_icon_bindings_desc">JSON object mapping language identifiers to Discord image assets.</string>
|
||||
<string name="discordrpc_language_icons">Language Icons</string>
|
||||
<string name="discordrpc_language_icons_desc">Display an icon for the active document language.</string>
|
||||
<string name="formatter_auto_format_on_save">Format on Save</string>
|
||||
<string name="formatter_auto_format_on_save_desc">Automatically format supported documents when saving.</string>
|
||||
<string name="git_filetree_highlight_changes">Highlight File Tree Changes</string>
|
||||
<string name="git_filetree_highlight_changes_desc">Highlight files with Git changes in the file tree.</string>
|
||||
<string name="git_filetree_highlight_style_color">File Tree Highlight Color</string>
|
||||
<string name="git_filetree_highlight_style_color_desc">CSS color used to highlight changed files.</string>
|
||||
<string name="git_silent">Silent Git Logs</string>
|
||||
<string name="git_silent_desc">Hide non-critical Git plugin log messages.</string>
|
||||
<string name="git_status_recurse_submodules">Recurse into Submodules</string>
|
||||
<string name="git_status_recurse_submodules_desc">Include submodule changes when collecting repository status.</string>
|
||||
<string name="git_statusbar_display_branch">Show Branch in Status Bar</string>
|
||||
<string name="git_statusbar_display_branch_desc">Display the current Git branch in the status bar.</string>
|
||||
<string name="git_statusbar_display_modifications">Show Modifications in Status Bar</string>
|
||||
<string name="git_statusbar_display_modifications_desc">Display repository modification counts in the status bar.</string>
|
||||
<string name="git_ui_refresh_frequency">Refresh Frequency</string>
|
||||
<string name="git_ui_refresh_frequency_desc">How often Git information in the interface is refreshed.</string>
|
||||
<string name="linter_delay_time">Lint Delay</string>
|
||||
<string name="linter_delay_time_desc">Time to wait before linting after an edit.</string>
|
||||
<string name="linter_disable_languages">Disable Linter Languages</string>
|
||||
<string name="linter_disable_languages_desc">Comma-separated language identifiers where linters are disabled.</string>
|
||||
<string name="linter_disable_lsp_languages">Disable LSP Diagnostic Languages</string>
|
||||
<string name="linter_disable_lsp_languages_desc">Comma-separated language identifiers where LSP diagnostics are disabled.</string>
|
||||
<string name="linter_enable_error_lens">Error Lens</string>
|
||||
<string name="linter_enable_error_lens_desc">Display diagnostic messages inline in the editor.</string>
|
||||
<string name="linter_enable_lsp_diagnostics">Language Server Diagnostics</string>
|
||||
<string name="linter_enable_lsp_diagnostics_desc">Display diagnostics reported by language servers.</string>
|
||||
<string name="linter_goto_ignore_warnings">Ignore Warnings When Navigating</string>
|
||||
<string name="linter_goto_ignore_warnings_desc">Skip warnings when navigating between diagnostics.</string>
|
||||
<string name="spellchecker_delay_time">Spell Check Delay</string>
|
||||
<string name="spellchecker_delay_time_desc">Time to wait before checking spelling after an edit.</string>
|
||||
<string name="xmltools_auto_edit_match">Edit Matching Tags</string>
|
||||
<string name="xmltools_auto_edit_match_desc">Update the matching tag automatically while editing.</string>
|
||||
<string name="xmltools_highlight_match">Highlight Matching Tags</string>
|
||||
<string name="xmltools_highlight_match_desc">Highlight the matching XML or HTML tag at the cursor.</string>
|
||||
</resources>
|
||||
|
||||
+108
-3
@@ -32,7 +32,6 @@ Cette opération est irréversible !</string>
|
||||
<string name="author">Auteur</string>
|
||||
<string name="auto_close_brackets_and_tags">Fermeture automatique des crochets et des balises</string>
|
||||
<string name="auto_close_xml_tags">Fermeture automatique des balises XML</string>
|
||||
<string name="auto_close_brackets_and_tags">Fermeture automatique des crochets et des balises</string>
|
||||
<string name="auto_detect_indent_type_and_width">Détection automatique du type et de la taille de l'indentation</string>
|
||||
<string name="autoreload_on_disk_change">Rechargement automatique en cas de modification du disque</string>
|
||||
<string name="back_quotes">Guillemets inversés ``</string>
|
||||
@@ -252,6 +251,8 @@ Voulez-vous le télécharger maintenant ?</string>
|
||||
<string name="edit">Modifier</string>
|
||||
<string name="edit_build">Modifier la construction</string>
|
||||
<string name="edit_custom_output_parser">Modifier l'analyseur de sortie personnalisé sélectionné</string>
|
||||
<string name="edit_settings_json">Modifier les paramètres JSON</string>
|
||||
<string name="edit_settings_json_desc">Ouvrir le fichier de configuration complet du plugin.</string>
|
||||
<string name="editor_font_and_size_ellipsis">Police et taille de l'éditeur...</string>
|
||||
<string name="editor_font_features">Fonctionnalités de la police de l'éditeur</string>
|
||||
<string name="ui_font_features">Fonctionnalités de la police de l'interface</string>
|
||||
@@ -264,7 +265,6 @@ Voulez-vous le télécharger maintenant ?</string>
|
||||
<string name="discretionary_ligatures">Ligatures discrétionnaires (dlig)</string>
|
||||
<string name="discretionary_ligatures_desc">Ligatures décoratives ou stylistiques facultatives fournies par la police.</string>
|
||||
<string name="editor_font_size">Taille de la police de l'éditeur</string>
|
||||
<string name="editor_font_features">Fonctionnalités de la police de l'éditeur</string>
|
||||
<string name="editor_go_back">Éditeur : retour en arrière</string>
|
||||
<string name="editor_go_forward">Éditeur : avancer</string>
|
||||
<string name="empty_file_name">Vous devez définir un nom pour le fichier.</string>
|
||||
@@ -469,6 +469,22 @@ La mémoire de discussion ne pourra être supprimée manuellement que dans l'his
|
||||
<string name="lsp_memory_usage">LSP : utilisation de la mémoire</string>
|
||||
<string name="lsp_plugin_restart">LSP : redémarrer le plugin</string>
|
||||
<string name="lsp_refresh_semantic_highlighting">LSP : actualiser la mise en évidence sémantique</string>
|
||||
<string name="lsp_breadcrumb_navigation">Navigation par fil d’Ariane</string>
|
||||
<string name="lsp_breadcrumb_navigation_desc">Afficher la navigation contextuelle par fil d’Ariane au-dessus de l’éditeur.</string>
|
||||
<string name="lsp_breadcrumb_height">Hauteur du fil d’Ariane</string>
|
||||
<string name="lsp_breadcrumb_height_desc">Hauteur du fil d’Ariane de l’éditeur exprimée comme une longueur CSS.</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang">Désactiver la coloration sémantique pour certaines langues</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang_desc">Identifiants de langues séparés par des virgules pour lesquels la coloration sémantique est désactivée.</string>
|
||||
<string name="lsp_hover_delay">Délai de survol</string>
|
||||
<string name="lsp_hover_delay_desc">Temps d’attente avant d’afficher les informations du serveur de langage lors du survol.</string>
|
||||
<string name="lsp_semantic_highlighting">Coloration sémantique</string>
|
||||
<string name="lsp_semantic_highlighting_desc">Utiliser les jetons sémantiques fournis par les serveurs de langage lorsqu’ils sont disponibles.</string>
|
||||
<string name="lsp_server_close_after_idle_time">Fermeture du serveur après inactivité</string>
|
||||
<string name="lsp_server_close_after_idle_time_desc">Durée pendant laquelle un serveur de langage inutilisé reste actif avant sa fermeture.</string>
|
||||
<string name="lsp_silent">Masquer les journaux des serveurs de langage</string>
|
||||
<string name="lsp_silent_desc">Masquer les messages non critiques des serveurs de langage.</string>
|
||||
<string name="lsp_trim_logs">Tronquer les journaux des serveurs de langage</string>
|
||||
<string name="lsp_trim_logs_desc">Limiter chaque ligne de journal d’un serveur de langage à 1 Kio.</string>
|
||||
<string name="lsp_rename_symbol_under_cursor">LSP : renommer le symbole sous le curseur</string>
|
||||
<string name="lsp_restart_lsp_client">LSP : redémarrer le client</string>
|
||||
<string name="lsp_show_document_symbols">LSP : afficher les symboles du document</string>
|
||||
@@ -590,6 +606,7 @@ détermine si une nouvelle fenêtre est créée ou non.</string>
|
||||
<string name="pick_widget">Choisir une widget</string>
|
||||
<string name="please_enter_file_url_ellipsis">Veuillez saisir l'URL du fichier...</string>
|
||||
<string name="plugin_manager">Gestionnaire de plugins</string>
|
||||
<string name="plugins">Plugins</string>
|
||||
<string name="plugin_manager_open">Gestionnaire de plugins ouvert</string>
|
||||
<string name="pluginsmodel_description">Description</string>
|
||||
<string name="pluginsmodel_enabled">Activé</string>
|
||||
@@ -822,7 +839,6 @@ dans l'arborescence de répertoires ainsi que dans les boites de dialogues de s
|
||||
<string name="type_to_locate">Type à localiser</string>
|
||||
<string name="ui_font_and_size_ellipsis">Police et taille de l'interface utilisateur...</string>
|
||||
<string name="ui_font_size">Interface utilisateur : taille de la police</string>
|
||||
<string name="ui_font_features">Fonctionnalités de la police de l'interface</string>
|
||||
<string name="ui_language">Interface utilisateur : langue</string>
|
||||
<string name="ui_multisamples_level">Interface utilisateur : niveau d'anti-aliasing multiéchantillon</string>
|
||||
<string name="ui_panel_font_size">Interface utilisateur : taille de police des panneaux</string>
|
||||
@@ -1089,4 +1105,93 @@ Redémarrer ecode pour voir les changements.</string>
|
||||
<string name="vsync_desc">Synchronise le rendu avec la fréquence de l'écran. Redémarrage requis.</string>
|
||||
<string name="warn_before_closing_tab">Avertir avant de fermer l'onglet</string>
|
||||
<string name="warn_before_closing_tab_tooltip">Demande confirmation avant de fermer un terminal exécutant un programme.</string>
|
||||
<string name="aiassistant_api_key_anthropic">Anthropic API Key</string>
|
||||
<string name="aiassistant_api_key_deepseek">DeepSeek API Key</string>
|
||||
<string name="aiassistant_api_key_desc">Credential used to access this model provider.</string>
|
||||
<string name="aiassistant_api_key_github">GitHub Models API Key</string>
|
||||
<string name="aiassistant_api_key_google">Google AI API Key</string>
|
||||
<string name="aiassistant_api_key_mistral">Mistral API Key</string>
|
||||
<string name="aiassistant_api_key_moonshotai">Moonshot AI API Key</string>
|
||||
<string name="aiassistant_api_key_nvidia">NVIDIA API Key</string>
|
||||
<string name="aiassistant_api_key_openai">OpenAI API Key</string>
|
||||
<string name="aiassistant_api_key_openrouter">OpenRouter API Key</string>
|
||||
<string name="aiassistant_api_key_perplexity">Perplexity API Key</string>
|
||||
<string name="aiassistant_api_key_togetherai">Together AI API Key</string>
|
||||
<string name="aiassistant_api_key_xai">xAI API Key</string>
|
||||
<string name="aiassistant_api_key_xiaomi">Xiaomi MiMo API Key</string>
|
||||
<string name="aiassistant_api_keys">API Keys</string>
|
||||
<string name="aiassistant_display_reasoning">Display Reasoning</string>
|
||||
<string name="aiassistant_display_reasoning_desc">Display reasoning content returned by supported models.</string>
|
||||
<string name="aiassistant_model_catalog_enabled">Enable Model Catalog</string>
|
||||
<string name="aiassistant_model_catalog_enabled_desc">Download model metadata from the configured catalog.</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours">Model Catalog Refresh Interval</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours_desc">Hours between model catalog refreshes.</string>
|
||||
<string name="aiassistant_model_catalog_url">Model Catalog URL</string>
|
||||
<string name="aiassistant_model_catalog_url_desc">URL used to download model catalog metadata.</string>
|
||||
<string name="autocomplete_load_vscode_snippets">Load VS Code Snippets</string>
|
||||
<string name="autocomplete_load_vscode_snippets_desc">Load compatible snippets installed for VS Code.</string>
|
||||
<string name="autocomplete_max_label_characters">Maximum Label Characters</string>
|
||||
<string name="autocomplete_max_label_characters_desc">Maximum number of characters shown in a suggestion label.</string>
|
||||
<string name="autocomplete_max_signature_helper_width">Maximum Signature Help Width</string>
|
||||
<string name="autocomplete_max_signature_helper_width_desc">Maximum signature help popup width as a CSS length.</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width">Maximum Suggestion Documentation Width</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width_desc">Maximum documentation popup width as a CSS length.</string>
|
||||
<string name="autocomplete_signature_help_documentation">Signature Help Documentation</string>
|
||||
<string name="autocomplete_signature_help_documentation_desc">Show documentation alongside signature help.</string>
|
||||
<string name="autocomplete_signature_help_multi_line">Multiline Signature Help</string>
|
||||
<string name="autocomplete_signature_help_multi_line_desc">Allow signature help to use multiple lines.</string>
|
||||
<string name="autocomplete_suggestion_documentation">Suggestion Documentation</string>
|
||||
<string name="autocomplete_suggestion_documentation_desc">Show documentation alongside completion suggestions.</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight">Syntax Highlight Suggestions</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight_desc">Apply syntax highlighting to completion suggestions.</string>
|
||||
<string name="debugger_fetch_globals">Fetch Global Variables</string>
|
||||
<string name="debugger_fetch_globals_desc">Request global variables while debugging.</string>
|
||||
<string name="debugger_fetch_registers">Fetch Registers</string>
|
||||
<string name="debugger_fetch_registers_desc">Request processor registers while debugging.</string>
|
||||
<string name="debugger_load_vscode_launch_config">Load VS Code Launch Configuration</string>
|
||||
<string name="debugger_load_vscode_launch_config_desc">Load compatible launch configurations from .vscode/launch.json.</string>
|
||||
<string name="debugger_silent">Silent Debugger Logs</string>
|
||||
<string name="debugger_silent_desc">Hide non-critical debugger log messages.</string>
|
||||
<string name="discordrpc_application_id">Discord Application ID</string>
|
||||
<string name="discordrpc_application_id_desc">Discord application identifier used for Rich Presence.</string>
|
||||
<string name="discordrpc_git_integration">Git Integration</string>
|
||||
<string name="discordrpc_git_integration_desc">Include repository information in Rich Presence.</string>
|
||||
<string name="discordrpc_icon_bindings">Language Icon Bindings</string>
|
||||
<string name="discordrpc_icon_bindings_desc">JSON object mapping language identifiers to Discord image assets.</string>
|
||||
<string name="discordrpc_language_icons">Language Icons</string>
|
||||
<string name="discordrpc_language_icons_desc">Display an icon for the active document language.</string>
|
||||
<string name="formatter_auto_format_on_save">Format on Save</string>
|
||||
<string name="formatter_auto_format_on_save_desc">Automatically format supported documents when saving.</string>
|
||||
<string name="git_filetree_highlight_changes">Highlight File Tree Changes</string>
|
||||
<string name="git_filetree_highlight_changes_desc">Highlight files with Git changes in the file tree.</string>
|
||||
<string name="git_filetree_highlight_style_color">File Tree Highlight Color</string>
|
||||
<string name="git_filetree_highlight_style_color_desc">CSS color used to highlight changed files.</string>
|
||||
<string name="git_silent">Silent Git Logs</string>
|
||||
<string name="git_silent_desc">Hide non-critical Git plugin log messages.</string>
|
||||
<string name="git_status_recurse_submodules">Recurse into Submodules</string>
|
||||
<string name="git_status_recurse_submodules_desc">Include submodule changes when collecting repository status.</string>
|
||||
<string name="git_statusbar_display_branch">Show Branch in Status Bar</string>
|
||||
<string name="git_statusbar_display_branch_desc">Display the current Git branch in the status bar.</string>
|
||||
<string name="git_statusbar_display_modifications">Show Modifications in Status Bar</string>
|
||||
<string name="git_statusbar_display_modifications_desc">Display repository modification counts in the status bar.</string>
|
||||
<string name="git_ui_refresh_frequency">Refresh Frequency</string>
|
||||
<string name="git_ui_refresh_frequency_desc">How often Git information in the interface is refreshed.</string>
|
||||
<string name="linter_delay_time">Lint Delay</string>
|
||||
<string name="linter_delay_time_desc">Time to wait before linting after an edit.</string>
|
||||
<string name="linter_disable_languages">Disable Linter Languages</string>
|
||||
<string name="linter_disable_languages_desc">Comma-separated language identifiers where linters are disabled.</string>
|
||||
<string name="linter_disable_lsp_languages">Disable LSP Diagnostic Languages</string>
|
||||
<string name="linter_disable_lsp_languages_desc">Comma-separated language identifiers where LSP diagnostics are disabled.</string>
|
||||
<string name="linter_enable_error_lens">Error Lens</string>
|
||||
<string name="linter_enable_error_lens_desc">Display diagnostic messages inline in the editor.</string>
|
||||
<string name="linter_enable_lsp_diagnostics">Language Server Diagnostics</string>
|
||||
<string name="linter_enable_lsp_diagnostics_desc">Display diagnostics reported by language servers.</string>
|
||||
<string name="linter_goto_ignore_warnings">Ignore Warnings When Navigating</string>
|
||||
<string name="linter_goto_ignore_warnings_desc">Skip warnings when navigating between diagnostics.</string>
|
||||
<string name="spellchecker_delay_time">Spell Check Delay</string>
|
||||
<string name="spellchecker_delay_time_desc">Time to wait before checking spelling after an edit.</string>
|
||||
<string name="xmltools_auto_edit_match">Edit Matching Tags</string>
|
||||
<string name="xmltools_auto_edit_match_desc">Update the matching tag automatically while editing.</string>
|
||||
<string name="xmltools_highlight_match">Highlight Matching Tags</string>
|
||||
<string name="xmltools_highlight_match_desc">Highlight the matching XML or HTML tag at the cursor.</string>
|
||||
</resources>
|
||||
|
||||
+108
-3
@@ -31,7 +31,6 @@
|
||||
<string name="arguments">参数</string>
|
||||
<string name="ask_close_tab">关闭标签页?</string>
|
||||
<string name="author">作者</string>
|
||||
<string name="auto_close_brackets_and_tags">Auto-Close Brackets & Tags</string>
|
||||
<string name="auto_close_xml_tags">自动关闭XML标签</string>
|
||||
<string name="auto_close_brackets_and_tags">自动闭合括号和标签</string>
|
||||
<string name="auto_detect_indent_type_and_width">Auto Detect Indent Type & Width</string>
|
||||
@@ -186,6 +185,8 @@
|
||||
<string name="edit">编辑</string>
|
||||
<string name="edit_build">编辑构建</string>
|
||||
<string name="edit_custom_output_parser">编辑已选的自定义输出解析器</string>
|
||||
<string name="edit_settings_json">编辑设置 JSON</string>
|
||||
<string name="edit_settings_json_desc">打开完整的插件配置文件。</string>
|
||||
<string name="editor_font_and_size_ellipsis">编辑器字体和大小...</string>
|
||||
<string name="editor_font_features">编辑器字体特性</string>
|
||||
<string name="ui_font_features">界面字体特性</string>
|
||||
@@ -198,7 +199,6 @@
|
||||
<string name="discretionary_ligatures">任意连字 (dlig)</string>
|
||||
<string name="discretionary_ligatures_desc">字体提供的可选装饰性或风格化连字。</string>
|
||||
<string name="editor_font_size">编辑器字体大小</string>
|
||||
<string name="editor_font_features">编辑器字体特性</string>
|
||||
<string name="editor_go_back">编辑器撤销</string>
|
||||
<string name="editor_go_forward">编辑器重做</string>
|
||||
<string name="enable_color_picker">开启颜色选择器</string>
|
||||
@@ -371,6 +371,22 @@ Name your stash (optional):</string>
|
||||
<string name="lsp_memory_usage">Lsp Memory Usage</string>
|
||||
<string name="lsp_plugin_restart">Lsp Plugin Restart</string>
|
||||
<string name="lsp_refresh_semantic_highlighting">Lsp Refresh Semantic Highlighting</string>
|
||||
<string name="lsp_breadcrumb_navigation">面包屑导航</string>
|
||||
<string name="lsp_breadcrumb_navigation_desc">在编辑器上方显示语言感知的面包屑导航。</string>
|
||||
<string name="lsp_breadcrumb_height">面包屑高度</string>
|
||||
<string name="lsp_breadcrumb_height_desc">使用 CSS 长度设置编辑器面包屑的高度。</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang">禁用语义高亮的语言</string>
|
||||
<string name="lsp_disable_semantic_highlighting_lang_desc">以逗号分隔要禁用语义高亮的语言标识符。</string>
|
||||
<string name="lsp_hover_delay">悬停延迟</string>
|
||||
<string name="lsp_hover_delay_desc">悬停时显示语言服务器信息前的等待时间。</string>
|
||||
<string name="lsp_semantic_highlighting">语义高亮</string>
|
||||
<string name="lsp_semantic_highlighting_desc">在可用时使用语言服务器提供的语义标记。</string>
|
||||
<string name="lsp_server_close_after_idle_time">服务器空闲关闭时间</string>
|
||||
<string name="lsp_server_close_after_idle_time_desc">关闭未使用的语言服务器前保持其运行的时间。</string>
|
||||
<string name="lsp_silent">隐藏语言服务器日志</string>
|
||||
<string name="lsp_silent_desc">隐藏非关键的语言服务器日志消息。</string>
|
||||
<string name="lsp_trim_logs">截断语言服务器日志</string>
|
||||
<string name="lsp_trim_logs_desc">将每行语言服务器日志限制为 1 KiB。</string>
|
||||
<string name="lsp_rename_symbol_under_cursor">Lsp Rename Symbol Under Cursor</string>
|
||||
<string name="lsp_restart_lsp_client">Restart LSP Client</string>
|
||||
<string name="lsp_switch_header_source">Lsp Switch Header Source</string>
|
||||
@@ -462,6 +478,7 @@ Restart ecode to see the changes.</string>
|
||||
<string name="pick_widget">选择组件</string>
|
||||
<string name="please_enter_file_url_ellipsis">请输入文件URL...</string>
|
||||
<string name="plugin_manager">插件管理器</string>
|
||||
<string name="plugins">插件</string>
|
||||
<string name="plugin_manager_open">打开插件管理器</string>
|
||||
<string name="pluginsmodel_description">描述</string>
|
||||
<string name="pluginsmodel_enabled">已开启</string>
|
||||
@@ -622,7 +639,6 @@ file in the directory tree.</string>
|
||||
<string name="type_to_locate">Type to Locate</string>
|
||||
<string name="ui_font_and_size_ellipsis">界面字体和大小...</string>
|
||||
<string name="ui_font_size">Ui字体大小</string>
|
||||
<string name="ui_font_features">界面字体特性</string>
|
||||
<string name="ui_language">界面语言</string>
|
||||
<string name="ui_multisamples_level">多重采样抗锯齿级别</string>
|
||||
<string name="ui_panel_font_size">界面面板字体大小</string>
|
||||
@@ -894,4 +910,93 @@ file in the directory tree.</string>
|
||||
<string name="wrap_letter">按字符换行</string>
|
||||
<string name="wrap_type">换行依据</string>
|
||||
<string name="wrap_word">按单词换行</string>
|
||||
<string name="aiassistant_api_key_anthropic">Anthropic API Key</string>
|
||||
<string name="aiassistant_api_key_deepseek">DeepSeek API Key</string>
|
||||
<string name="aiassistant_api_key_desc">Credential used to access this model provider.</string>
|
||||
<string name="aiassistant_api_key_github">GitHub Models API Key</string>
|
||||
<string name="aiassistant_api_key_google">Google AI API Key</string>
|
||||
<string name="aiassistant_api_key_mistral">Mistral API Key</string>
|
||||
<string name="aiassistant_api_key_moonshotai">Moonshot AI API Key</string>
|
||||
<string name="aiassistant_api_key_nvidia">NVIDIA API Key</string>
|
||||
<string name="aiassistant_api_key_openai">OpenAI API Key</string>
|
||||
<string name="aiassistant_api_key_openrouter">OpenRouter API Key</string>
|
||||
<string name="aiassistant_api_key_perplexity">Perplexity API Key</string>
|
||||
<string name="aiassistant_api_key_togetherai">Together AI API Key</string>
|
||||
<string name="aiassistant_api_key_xai">xAI API Key</string>
|
||||
<string name="aiassistant_api_key_xiaomi">Xiaomi MiMo API Key</string>
|
||||
<string name="aiassistant_api_keys">API Keys</string>
|
||||
<string name="aiassistant_display_reasoning">Display Reasoning</string>
|
||||
<string name="aiassistant_display_reasoning_desc">Display reasoning content returned by supported models.</string>
|
||||
<string name="aiassistant_model_catalog_enabled">Enable Model Catalog</string>
|
||||
<string name="aiassistant_model_catalog_enabled_desc">Download model metadata from the configured catalog.</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours">Model Catalog Refresh Interval</string>
|
||||
<string name="aiassistant_model_catalog_refresh_hours_desc">Hours between model catalog refreshes.</string>
|
||||
<string name="aiassistant_model_catalog_url">Model Catalog URL</string>
|
||||
<string name="aiassistant_model_catalog_url_desc">URL used to download model catalog metadata.</string>
|
||||
<string name="autocomplete_load_vscode_snippets">Load VS Code Snippets</string>
|
||||
<string name="autocomplete_load_vscode_snippets_desc">Load compatible snippets installed for VS Code.</string>
|
||||
<string name="autocomplete_max_label_characters">Maximum Label Characters</string>
|
||||
<string name="autocomplete_max_label_characters_desc">Maximum number of characters shown in a suggestion label.</string>
|
||||
<string name="autocomplete_max_signature_helper_width">Maximum Signature Help Width</string>
|
||||
<string name="autocomplete_max_signature_helper_width_desc">Maximum signature help popup width as a CSS length.</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width">Maximum Suggestion Documentation Width</string>
|
||||
<string name="autocomplete_max_suggestion_documentation_width_desc">Maximum documentation popup width as a CSS length.</string>
|
||||
<string name="autocomplete_signature_help_documentation">Signature Help Documentation</string>
|
||||
<string name="autocomplete_signature_help_documentation_desc">Show documentation alongside signature help.</string>
|
||||
<string name="autocomplete_signature_help_multi_line">Multiline Signature Help</string>
|
||||
<string name="autocomplete_signature_help_multi_line_desc">Allow signature help to use multiple lines.</string>
|
||||
<string name="autocomplete_suggestion_documentation">Suggestion Documentation</string>
|
||||
<string name="autocomplete_suggestion_documentation_desc">Show documentation alongside completion suggestions.</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight">Syntax Highlight Suggestions</string>
|
||||
<string name="autocomplete_suggestions_syntax_highlight_desc">Apply syntax highlighting to completion suggestions.</string>
|
||||
<string name="debugger_fetch_globals">Fetch Global Variables</string>
|
||||
<string name="debugger_fetch_globals_desc">Request global variables while debugging.</string>
|
||||
<string name="debugger_fetch_registers">Fetch Registers</string>
|
||||
<string name="debugger_fetch_registers_desc">Request processor registers while debugging.</string>
|
||||
<string name="debugger_load_vscode_launch_config">Load VS Code Launch Configuration</string>
|
||||
<string name="debugger_load_vscode_launch_config_desc">Load compatible launch configurations from .vscode/launch.json.</string>
|
||||
<string name="debugger_silent">Silent Debugger Logs</string>
|
||||
<string name="debugger_silent_desc">Hide non-critical debugger log messages.</string>
|
||||
<string name="discordrpc_application_id">Discord Application ID</string>
|
||||
<string name="discordrpc_application_id_desc">Discord application identifier used for Rich Presence.</string>
|
||||
<string name="discordrpc_git_integration">Git Integration</string>
|
||||
<string name="discordrpc_git_integration_desc">Include repository information in Rich Presence.</string>
|
||||
<string name="discordrpc_icon_bindings">Language Icon Bindings</string>
|
||||
<string name="discordrpc_icon_bindings_desc">JSON object mapping language identifiers to Discord image assets.</string>
|
||||
<string name="discordrpc_language_icons">Language Icons</string>
|
||||
<string name="discordrpc_language_icons_desc">Display an icon for the active document language.</string>
|
||||
<string name="formatter_auto_format_on_save">Format on Save</string>
|
||||
<string name="formatter_auto_format_on_save_desc">Automatically format supported documents when saving.</string>
|
||||
<string name="git_filetree_highlight_changes">Highlight File Tree Changes</string>
|
||||
<string name="git_filetree_highlight_changes_desc">Highlight files with Git changes in the file tree.</string>
|
||||
<string name="git_filetree_highlight_style_color">File Tree Highlight Color</string>
|
||||
<string name="git_filetree_highlight_style_color_desc">CSS color used to highlight changed files.</string>
|
||||
<string name="git_silent">Silent Git Logs</string>
|
||||
<string name="git_silent_desc">Hide non-critical Git plugin log messages.</string>
|
||||
<string name="git_status_recurse_submodules">Recurse into Submodules</string>
|
||||
<string name="git_status_recurse_submodules_desc">Include submodule changes when collecting repository status.</string>
|
||||
<string name="git_statusbar_display_branch">Show Branch in Status Bar</string>
|
||||
<string name="git_statusbar_display_branch_desc">Display the current Git branch in the status bar.</string>
|
||||
<string name="git_statusbar_display_modifications">Show Modifications in Status Bar</string>
|
||||
<string name="git_statusbar_display_modifications_desc">Display repository modification counts in the status bar.</string>
|
||||
<string name="git_ui_refresh_frequency">Refresh Frequency</string>
|
||||
<string name="git_ui_refresh_frequency_desc">How often Git information in the interface is refreshed.</string>
|
||||
<string name="linter_delay_time">Lint Delay</string>
|
||||
<string name="linter_delay_time_desc">Time to wait before linting after an edit.</string>
|
||||
<string name="linter_disable_languages">Disable Linter Languages</string>
|
||||
<string name="linter_disable_languages_desc">Comma-separated language identifiers where linters are disabled.</string>
|
||||
<string name="linter_disable_lsp_languages">Disable LSP Diagnostic Languages</string>
|
||||
<string name="linter_disable_lsp_languages_desc">Comma-separated language identifiers where LSP diagnostics are disabled.</string>
|
||||
<string name="linter_enable_error_lens">Error Lens</string>
|
||||
<string name="linter_enable_error_lens_desc">Display diagnostic messages inline in the editor.</string>
|
||||
<string name="linter_enable_lsp_diagnostics">Language Server Diagnostics</string>
|
||||
<string name="linter_enable_lsp_diagnostics_desc">Display diagnostics reported by language servers.</string>
|
||||
<string name="linter_goto_ignore_warnings">Ignore Warnings When Navigating</string>
|
||||
<string name="linter_goto_ignore_warnings_desc">Skip warnings when navigating between diagnostics.</string>
|
||||
<string name="spellchecker_delay_time">Spell Check Delay</string>
|
||||
<string name="spellchecker_delay_time_desc">Time to wait before checking spelling after an edit.</string>
|
||||
<string name="xmltools_auto_edit_match">Edit Matching Tags</string>
|
||||
<string name="xmltools_auto_edit_match_desc">Update the matching tag automatically while editing.</string>
|
||||
<string name="xmltools_highlight_match">Highlight Matching Tags</string>
|
||||
<string name="xmltools_highlight_match_desc">Highlight the matching XML or HTML tag at the cursor.</string>
|
||||
</resources>
|
||||
|
||||
@@ -29,7 +29,6 @@ class UIDocFindReplace;
|
||||
|
||||
class UIIcon;
|
||||
class UICodeEditor;
|
||||
class UIWindow;
|
||||
class UIScrollBar;
|
||||
class UILoader;
|
||||
class UIPopUpMenu;
|
||||
@@ -45,37 +44,57 @@ class UICodeEditorPlugin {
|
||||
public:
|
||||
typedef std::function<void( UICodeEditorPlugin*, const Uint32& )> OnReadyCb;
|
||||
virtual std::string getId() = 0;
|
||||
|
||||
virtual std::string getTitle() = 0;
|
||||
|
||||
virtual std::string getDescription() = 0;
|
||||
|
||||
virtual bool isReady() const = 0;
|
||||
virtual bool hasGUIConfig() { return false; }
|
||||
|
||||
virtual bool hasFileConfig() { return false; }
|
||||
virtual UIWindow* getGUIConfig() { return nullptr; }
|
||||
|
||||
virtual std::string getFileConfigPath() { return ""; }
|
||||
|
||||
virtual ~UICodeEditorPlugin() {}
|
||||
|
||||
virtual void onRegister( UICodeEditor* ) = 0;
|
||||
|
||||
virtual void onUnregister( UICodeEditor* ) = 0;
|
||||
|
||||
virtual bool onKeyDown( UICodeEditor*, const KeyEvent& ) { return false; }
|
||||
|
||||
virtual bool onKeyUp( UICodeEditor*, const KeyEvent& ) { return false; }
|
||||
|
||||
virtual bool onTextInput( UICodeEditor*, const TextInputEvent& ) { return false; }
|
||||
|
||||
virtual void update( UICodeEditor* ) {}
|
||||
|
||||
virtual void preDraw( UICodeEditor*, const Vector2f& /*startScroll*/,
|
||||
const Float& /*lineHeight*/, const TextPosition& /*cursor*/ ) {}
|
||||
|
||||
virtual void postDraw( UICodeEditor*, const Vector2f& /*startScroll*/,
|
||||
const Float& /*lineHeight*/, const TextPosition& /*cursor*/ ) {}
|
||||
|
||||
virtual void onFocus( UICodeEditor* ) {}
|
||||
|
||||
virtual void onFocusLoss( UICodeEditor* ) {}
|
||||
|
||||
virtual bool onMouseDown( UICodeEditor*, const Vector2i&, const Uint32& ) { return false; }
|
||||
|
||||
virtual bool onMouseMove( UICodeEditor*, const Vector2i&, const Uint32& ) { return false; }
|
||||
|
||||
virtual bool onMouseUp( UICodeEditor*, const Vector2i&, const Uint32& ) { return false; }
|
||||
|
||||
virtual bool onMouseClick( UICodeEditor*, const Vector2i&, const Uint32& ) { return false; }
|
||||
|
||||
virtual bool onMouseDoubleClick( UICodeEditor*, const Vector2i&, const Uint32& ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool onMouseOver( UICodeEditor*, const Vector2i&, const Uint32& ) { return false; }
|
||||
|
||||
virtual bool onMouseLeave( UICodeEditor*, const Vector2i&, const Uint32& ) { return false; }
|
||||
|
||||
virtual bool onCreateContextMenu( UICodeEditor*, UIPopUpMenu* /*menu*/,
|
||||
const Vector2i& /*position*/, const Uint32& /*flags*/ ) {
|
||||
return false;
|
||||
@@ -142,6 +161,7 @@ class EE_API DocEvent : public Event {
|
||||
public:
|
||||
DocEvent( Node* node, TextDocument* doc, const Uint32& eventType ) :
|
||||
Event( node, eventType ), doc( doc ) {}
|
||||
|
||||
TextDocument* getDoc() const { return doc; }
|
||||
|
||||
protected:
|
||||
@@ -165,7 +185,9 @@ class EE_API DocSyntaxDefEvent : public DocEvent {
|
||||
DocSyntaxDefEvent( Node* node, TextDocument* doc, const Uint32& eventType,
|
||||
const std::string& oldLang, const std::string& newLang ) :
|
||||
DocEvent( node, doc, eventType ), oldLang( oldLang ), newLang( newLang ) {}
|
||||
|
||||
const std::string& getOldLang() const { return oldLang; }
|
||||
|
||||
const std::string& getNewLang() const { return newLang; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -102,7 +102,7 @@ const char DOC_FIND_REPLACE_CSS[] = R"css(
|
||||
}
|
||||
.ce_find_replace_box .input-find.error,
|
||||
.ce_find_replace_box .input-replace.error {
|
||||
border-color: #ff4040;
|
||||
border-color: var(--theme-error);
|
||||
}
|
||||
)css";
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ StatusBar > #doc_info {
|
||||
}
|
||||
#search_find.error,
|
||||
#search_replace.error {
|
||||
border-color: #ff4040;
|
||||
border-color: var(--theme-error);
|
||||
}
|
||||
TableView#locate_bar_table > tableview::row > tableview::cell:nth-child(2),
|
||||
TableView#locate_bar_table > tableview::row > tableview::cell:nth-child(3) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "../../appconfig.hpp"
|
||||
#include "../../notificationcenter.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include "../../widgetcommandexecuter.hpp"
|
||||
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
@@ -13,6 +14,66 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void AIAssistantPlugin::registerSettings( SettingsPage& page ) {
|
||||
auto general = i18n( "general", "General" );
|
||||
page.addGroup( general );
|
||||
page.addBool( "display-reasoning", "/config/display_reasoning",
|
||||
i18n( "aiassistant_display_reasoning", "Display Reasoning" ),
|
||||
i18n( "aiassistant_display_reasoning_desc",
|
||||
"Display reasoning content returned by supported models." ),
|
||||
false, general );
|
||||
page.addBool( "model-catalog-enabled", "/config/model_catalog_enabled",
|
||||
i18n( "aiassistant_model_catalog_enabled", "Enable Model Catalog" ),
|
||||
i18n( "aiassistant_model_catalog_enabled_desc",
|
||||
"Download model metadata from the configured catalog." ),
|
||||
true, general );
|
||||
page.addText(
|
||||
"model-catalog-url", "/config/model_catalog_url",
|
||||
i18n( "aiassistant_model_catalog_url", "Model Catalog URL" ),
|
||||
i18n( "aiassistant_model_catalog_url_desc",
|
||||
"URL used to download model catalog metadata." ),
|
||||
"https://models.dev/api.json", []( const std::string& value ) { return !value.empty(); },
|
||||
false, general );
|
||||
page.addInteger(
|
||||
"model-catalog-refresh-hours", "/config/model_catalog_refresh_hours",
|
||||
i18n( "aiassistant_model_catalog_refresh_hours", "Model Catalog Refresh Interval" ),
|
||||
i18n( "aiassistant_model_catalog_refresh_hours_desc",
|
||||
"Hours between model catalog refreshes." ),
|
||||
1, 8760, 24, general );
|
||||
|
||||
auto apiKeys = i18n( "aiassistant_api_keys", "API Keys" );
|
||||
page.addGroup( apiKeys );
|
||||
struct Provider {
|
||||
const char* id;
|
||||
const char* name;
|
||||
const char* legacyKey;
|
||||
};
|
||||
static constexpr Provider providers[] = {
|
||||
{ "openai", "OpenAI", "openai_api_key" },
|
||||
{ "anthropic", "Anthropic", "anthropic_api_key" },
|
||||
{ "google", "Google AI", "google_ai_api_key" },
|
||||
{ "deepseek", "DeepSeek", "deepseek_api_key" },
|
||||
{ "mistral", "Mistral", "mistral_api_key" },
|
||||
{ "xai", "xAI", "xai_api_key" },
|
||||
{ "github", "GitHub Models", "github_api_key" },
|
||||
{ "perplexity", "Perplexity", "perplexity_api_key" },
|
||||
{ "openrouter", "OpenRouter", "openrouter_api_key" },
|
||||
{ "moonshotai", "Moonshot AI", "moonshot_api_key" },
|
||||
{ "nvidia", "NVIDIA", "nvidia_api_key" },
|
||||
{ "togetherai", "Together AI", "together_api_key" },
|
||||
{ "xiaomi", "Xiaomi MiMo", "mimo_api_key" },
|
||||
};
|
||||
for ( const auto& provider : providers ) {
|
||||
page.addSecret(
|
||||
std::string{ "api-key-" } + provider.id,
|
||||
std::string{ "/config/api_keys/" } + provider.id,
|
||||
i18n( std::string{ "aiassistant_api_key_" } + provider.id,
|
||||
String::fromUtf8( std::string_view{ provider.name } ) + " API Key" ),
|
||||
i18n( "aiassistant_api_key_desc", "Credential used to access this model provider." ),
|
||||
{}, apiKeys, std::string{ "/config/" } + provider.legacyKey );
|
||||
}
|
||||
}
|
||||
|
||||
static std::initializer_list<std::string> AIAssistantUnlockedCommandList = {
|
||||
|
||||
"new-ai-assistant"
|
||||
@@ -285,7 +346,7 @@ void AIAssistantPlugin::load( PluginManager* pluginManager ) {
|
||||
userConfig["model_catalog_url"].is_string() )
|
||||
catalogSettings.url = userConfig["model_catalog_url"].get<std::string>();
|
||||
if ( userConfig.contains( "model_catalog_refresh_hours" ) &&
|
||||
userConfig["model_catalog_refresh_hours"].is_number_unsigned() )
|
||||
userConfig["model_catalog_refresh_hours"].is_number_integer() )
|
||||
catalogSettings.refreshIntervalHours =
|
||||
userConfig["model_catalog_refresh_hours"].get<std::uint32_t>();
|
||||
}
|
||||
|
||||
@@ -40,7 +40,12 @@ class AIAssistantPlugin : public PluginBase {
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
const LLMProviders& getProviders() { return mProviders; }
|
||||
|
||||
const ACPAgents& getAgents() { return mAgents; }
|
||||
|
||||
std::string getPluginStatePath() const;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "autocompleteplugin.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include "../../universallocator.hpp"
|
||||
#include <eepp/graphics/primitives.hpp>
|
||||
#include <eepp/graphics/text.hpp>
|
||||
@@ -25,6 +26,55 @@ using namespace std::literals;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void AutoCompletePlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addBool(
|
||||
"suggestions-syntax-highlight", "/config/suggestions_syntax_highlight",
|
||||
i18n( "autocomplete_suggestions_syntax_highlight", "Syntax Highlight Suggestions" ),
|
||||
i18n( "autocomplete_suggestions_syntax_highlight_desc",
|
||||
"Apply syntax highlighting to completion suggestions." ),
|
||||
true );
|
||||
page.addInteger( "max-label-characters", "/config/max_label_characters",
|
||||
i18n( "autocomplete_max_label_characters", "Maximum Label Characters" ),
|
||||
i18n( "autocomplete_max_label_characters_desc",
|
||||
"Maximum number of characters shown in a suggestion label." ),
|
||||
1, 10000, 100 );
|
||||
auto cssLength = []( const std::string& text ) { return StyleSheetLength::isLength( text ); };
|
||||
page.addText( "max-suggestion-documentation-width",
|
||||
"/config/max_suggestion_documentation_width",
|
||||
i18n( "autocomplete_max_suggestion_documentation_width",
|
||||
"Maximum Suggestion Documentation Width" ),
|
||||
i18n( "autocomplete_max_suggestion_documentation_width_desc",
|
||||
"Maximum documentation popup width as a CSS length." ),
|
||||
"100%", cssLength );
|
||||
page.addText( "max-signature-helper-width", "/config/max_signature_helper_width",
|
||||
i18n( "autocomplete_max_signature_helper_width", "Maximum Signature Help Width" ),
|
||||
i18n( "autocomplete_max_signature_helper_width_desc",
|
||||
"Maximum signature help popup width as a CSS length." ),
|
||||
"90%", cssLength );
|
||||
page.addBool( "signature-help-multi-line", "/config/signature_help_multi_line",
|
||||
i18n( "autocomplete_signature_help_multi_line", "Multiline Signature Help" ),
|
||||
i18n( "autocomplete_signature_help_multi_line_desc",
|
||||
"Allow signature help to use multiple lines." ),
|
||||
true );
|
||||
page.addBool( "suggestion-documentation", "/config/suggestion_documentation",
|
||||
i18n( "autocomplete_suggestion_documentation", "Suggestion Documentation" ),
|
||||
i18n( "autocomplete_suggestion_documentation_desc",
|
||||
"Show documentation alongside completion suggestions." ),
|
||||
true );
|
||||
page.addBool(
|
||||
"signature-help-documentation", "/config/signature_help_documentation",
|
||||
i18n( "autocomplete_signature_help_documentation", "Signature Help Documentation" ),
|
||||
i18n( "autocomplete_signature_help_documentation_desc",
|
||||
"Show documentation alongside signature help." ),
|
||||
true );
|
||||
page.addBool( "load-vscode-snippets", "/config/load_vscode_snippets",
|
||||
i18n( "autocomplete_load_vscode_snippets", "Load VS Code Snippets" ),
|
||||
i18n( "autocomplete_load_vscode_snippets_desc",
|
||||
"Load compatible snippets installed for VS Code." ),
|
||||
true );
|
||||
}
|
||||
|
||||
class SnippetLocatorModel : public Model {
|
||||
public:
|
||||
struct Row {
|
||||
@@ -380,7 +430,7 @@ void AutoCompletePlugin::load( PluginManager* pluginManager ) {
|
||||
if ( config.contains( "signature_help_documentation" ) )
|
||||
mSignatureHelpDocumentation = config.value( "signature_help_documentation", true );
|
||||
else {
|
||||
config["suggestion_documentation"] = mSignatureHelpDocumentation;
|
||||
config["signature_help_documentation"] = mSignatureHelpDocumentation;
|
||||
updateConfigFile = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,21 +95,38 @@ class AutoCompletePlugin : public Plugin {
|
||||
|
||||
bool isReady() const override { return true; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
void onRegister( UICodeEditor* ) override;
|
||||
|
||||
void onUnregister( UICodeEditor* ) override;
|
||||
|
||||
bool onKeyDown( UICodeEditor*, const KeyEvent& ) override;
|
||||
|
||||
bool onTextInput( UICodeEditor*, const TextInputEvent& ) override;
|
||||
|
||||
void update( UICodeEditor* ) override;
|
||||
|
||||
void postDraw( UICodeEditor*, const Vector2f& startScroll, const Float& lineHeight,
|
||||
const TextPosition& cursor ) override;
|
||||
|
||||
void drawBeforeLineText( UICodeEditor*, const Int64&, Vector2f, const Float&,
|
||||
const Float& ) override;
|
||||
|
||||
bool onMouseDown( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
||||
|
||||
bool onMouseUp( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
||||
|
||||
bool onMouseDoubleClick( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
||||
|
||||
bool onMouseMove( UICodeEditor*, const Vector2i&, const Uint32& ) override;
|
||||
|
||||
void onFileSystemEvent( const FileEvent&, const FileInfo& ) override;
|
||||
|
||||
FileSystemListenerOptions getFileSystemListenerOptions() const override;
|
||||
|
||||
void onLoadProject( const std::string& projectFolder,
|
||||
const std::string& projectStatePath ) override;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "debuggerplugin.hpp"
|
||||
#include "../../jsonhelper.hpp"
|
||||
#include "../../notificationcenter.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include "../../terminalmanager.hpp"
|
||||
#include "../../uistatusbar.hpp"
|
||||
#include "../../widgetcommandexecuter.hpp"
|
||||
@@ -30,6 +31,27 @@ static constexpr auto REQUEST_TYPE_ATTACH = "attach";
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void DebuggerPlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addBool(
|
||||
"fetch-registers", "/config/fetch_registers",
|
||||
i18n( "debugger_fetch_registers", "Fetch Registers" ),
|
||||
i18n( "debugger_fetch_registers_desc", "Request processor registers while debugging." ),
|
||||
false );
|
||||
page.addBool(
|
||||
"fetch-globals", "/config/fetch_globals",
|
||||
i18n( "debugger_fetch_globals", "Fetch Global Variables" ),
|
||||
i18n( "debugger_fetch_globals_desc", "Request global variables while debugging." ), false );
|
||||
page.addBool( "silent", "/config/silent", i18n( "debugger_silent", "Silent Debugger Logs" ),
|
||||
i18n( "debugger_silent_desc", "Hide non-critical debugger log messages." ),
|
||||
true );
|
||||
page.addBool( "load-vscode-launch-config", "/config/load_vscode_launch_config",
|
||||
i18n( "debugger_load_vscode_launch_config", "Load VS Code Launch Configuration" ),
|
||||
i18n( "debugger_load_vscode_launch_config_desc",
|
||||
"Load compatible launch configurations from .vscode/launch.json." ),
|
||||
true );
|
||||
}
|
||||
|
||||
static constexpr auto INPUT_PATTERN = "%$%{input%:([%w_]+)%}"sv;
|
||||
static constexpr auto ENV_PATTERN = "%$%{env%:([%w_]+)%}"sv;
|
||||
static constexpr auto COMMAND_PATTERN = "%$%{command%:([%w_]+)%}"sv;
|
||||
|
||||
@@ -67,6 +67,10 @@ class DebuggerPlugin : public PluginBase {
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
void onSaveState( IniFile* state ) override;
|
||||
|
||||
void onSaveProject( const std::string& projectFolder, const std::string& projectStatePath,
|
||||
@@ -150,16 +154,27 @@ class DebuggerPlugin : public PluginBase {
|
||||
mDoc( doc ), mParent( parent ) {}
|
||||
|
||||
virtual void onDocumentTextChanged( const DocumentContentChange& ) {}
|
||||
|
||||
virtual void onDocumentUndoRedo( const TextDocument::UndoRedo& ) {}
|
||||
|
||||
virtual void onDocumentCursorChange( const TextPosition& ) {}
|
||||
|
||||
virtual void onDocumentSelectionChange( const TextRange& ) {}
|
||||
|
||||
virtual void onDocumentLineCountChange( const size_t&, const size_t& ) {}
|
||||
|
||||
virtual void onDocumentLineChanged( const Int64& ) {}
|
||||
|
||||
virtual void onDocumentSaved( TextDocument* ) {}
|
||||
|
||||
virtual void onDocumentClosed( TextDocument* doc ) { onDocumentReset( doc ); }
|
||||
|
||||
virtual void onDocumentDirtyOnFileSystem( TextDocument* ) {}
|
||||
|
||||
virtual void onDocumentMoved( TextDocument* ) {}
|
||||
|
||||
virtual void onDocumentReset( TextDocument* ) {}
|
||||
|
||||
Client::Type getTextDocumentClientType() { return TextDocument::Client::Auxiliary; }
|
||||
|
||||
virtual void onDocumentLineMove( const Int64& fromLine, const Int64& toLine,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "discordRPCplugin.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
@@ -6,6 +7,34 @@ namespace ecode {
|
||||
|
||||
static const auto DEFAULT_CLIENT_ID = "1339026777158455336";
|
||||
static const auto DebounceUniqueId = String::hash( "DiscordRPCplugin::debounce" );
|
||||
|
||||
void DiscordRPCplugin::registerSettings( SettingsPage& page ) {
|
||||
auto general = i18n( "general", "General" );
|
||||
page.addGroup( general );
|
||||
page.addText( "application-id", "/config/appID",
|
||||
i18n( "discordrpc_application_id", "Discord Application ID" ),
|
||||
i18n( "discordrpc_application_id_desc",
|
||||
"Discord application identifier used for Rich Presence." ),
|
||||
DEFAULT_CLIENT_ID, {}, false, general );
|
||||
page.addBool( "language-icons", "/config/doLanguageIcons",
|
||||
i18n( "discordrpc_language_icons", "Language Icons" ),
|
||||
i18n( "discordrpc_language_icons_desc",
|
||||
"Display an icon for the active document language." ),
|
||||
true, general );
|
||||
page.addBool( "git-integration", "/config/doGitIntegration",
|
||||
i18n( "discordrpc_git_integration", "Git Integration" ),
|
||||
i18n( "discordrpc_git_integration_desc",
|
||||
"Include repository information in Rich Presence." ),
|
||||
true, general );
|
||||
auto advanced = i18n( "advanced", "Advanced" );
|
||||
page.addGroup( advanced );
|
||||
page.addJsonObject( "icon-bindings", "/config/iconBindings",
|
||||
i18n( "discordrpc_icon_bindings", "Language Icon Bindings" ),
|
||||
i18n( "discordrpc_icon_bindings_desc",
|
||||
"JSON object mapping language identifiers to Discord image assets." ),
|
||||
nlohmann::json::object(), advanced );
|
||||
}
|
||||
|
||||
static const std::vector<std::string> DiscordRPCCommandList = { "discordrpc-reconnect" };
|
||||
|
||||
static const auto DISCORDRPC_DEFAULT_ICON =
|
||||
|
||||
@@ -43,6 +43,10 @@ class DiscordRPCplugin : public PluginBase {
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
protected:
|
||||
DiscordIPC mIPC;
|
||||
Mutex mDataMutex;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "formatterplugin.hpp"
|
||||
#include "../../notificationcenter.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/iostreamstring.hpp>
|
||||
#include <eepp/system/lock.hpp>
|
||||
@@ -18,6 +19,15 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void FormatterPlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addBool( "auto-format-on-save", "/config/auto_format_on_save",
|
||||
i18n( "formatter_auto_format_on_save", "Format on Save" ),
|
||||
i18n( "formatter_auto_format_on_save_desc",
|
||||
"Automatically format supported documents when saving." ),
|
||||
false );
|
||||
}
|
||||
|
||||
Plugin* FormatterPlugin::New( PluginManager* pluginManager ) {
|
||||
return eeNew( FormatterPlugin, ( pluginManager, false ) );
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ class FormatterPlugin : public Plugin {
|
||||
|
||||
std::string getDescription() { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
virtual String::HashType getConfigFileHash() { return mConfigHash; }
|
||||
|
||||
void onRegister( UICodeEditor* );
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "gitplugin.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include "gitbranchmodel.hpp"
|
||||
#include "gitstatusmodel.hpp"
|
||||
#include <eepp/graphics/image.hpp>
|
||||
@@ -33,6 +34,45 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void GitPlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addText( "ui-refresh-frequency", "/config/ui_refresh_frequency",
|
||||
i18n( "git_ui_refresh_frequency", "Refresh Frequency" ),
|
||||
i18n( "git_ui_refresh_frequency_desc",
|
||||
"How often Git information in the interface is refreshed." ),
|
||||
mRefreshFreq.toString(), []( const std::string& text ) {
|
||||
Time value;
|
||||
return SettingsPage::parseNonNegativeSettingsTime( text, value );
|
||||
} );
|
||||
page.addBool( "statusbar-display-branch", "/config/statusbar_display_branch",
|
||||
i18n( "git_statusbar_display_branch", "Show Branch in Status Bar" ),
|
||||
i18n( "git_statusbar_display_branch_desc",
|
||||
"Display the current Git branch in the status bar." ),
|
||||
true );
|
||||
page.addBool( "filetree-highlight-changes", "/config/filetree_highlight_changes",
|
||||
i18n( "git_filetree_highlight_changes", "Highlight File Tree Changes" ),
|
||||
i18n( "git_filetree_highlight_changes_desc",
|
||||
"Highlight files with Git changes in the file tree." ),
|
||||
true );
|
||||
page.addText( "filetree-highlight-style-color", "/config/filetree_highlight_style_color",
|
||||
i18n( "git_filetree_highlight_style_color", "File Tree Highlight Color" ),
|
||||
i18n( "git_filetree_highlight_style_color_desc",
|
||||
"CSS color used to highlight changed files." ),
|
||||
"var(--font-highlight)" );
|
||||
page.addBool( "statusbar-display-modifications", "/config/statusbar_display_modifications",
|
||||
i18n( "git_statusbar_display_modifications", "Show Modifications in Status Bar" ),
|
||||
i18n( "git_statusbar_display_modifications_desc",
|
||||
"Display repository modification counts in the status bar." ),
|
||||
true );
|
||||
page.addBool( "status-recurse-submodules", "/config/status_recurse_submodules",
|
||||
i18n( "git_status_recurse_submodules", "Recurse into Submodules" ),
|
||||
i18n( "git_status_recurse_submodules_desc",
|
||||
"Include submodule changes when collecting repository status." ),
|
||||
true );
|
||||
page.addBool( "silent", "/config/silent", i18n( "git_silent", "Silent Git Logs" ),
|
||||
i18n( "git_silent_desc", "Hide non-critical Git plugin log messages." ), true );
|
||||
}
|
||||
|
||||
static constexpr auto DEFAULT_HIGHLIGHT_COLOR = "var(--font-highlight)"sv;
|
||||
static constexpr auto GIT_STATUS_UPDATE_TAG = String::hash( "git::status-update" );
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ class GitPlugin : public PluginBase {
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
void onFileSystemEvent( const FileEvent& ev, const FileInfo& file ) override;
|
||||
|
||||
FileSystemListenerOptions getFileSystemListenerOptions() const override;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "linterplugin.hpp"
|
||||
#include "../../notificationcenter.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include <algorithm>
|
||||
#include <eepp/graphics/primitives.hpp>
|
||||
#include <eepp/graphics/text.hpp>
|
||||
@@ -30,6 +31,41 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void LinterPlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addText( "delay-time", "/config/delay_time", i18n( "linter_delay_time", "Lint Delay" ),
|
||||
i18n( "linter_delay_time_desc", "Time to wait before linting after an edit." ),
|
||||
getDelayTime().toString(), []( const std::string& text ) {
|
||||
Time value;
|
||||
return SettingsPage::parseNonNegativeSettingsTime( text, value );
|
||||
} );
|
||||
page.addBool( "enable-lsp-diagnostics", "/config/enable_lsp_diagnostics",
|
||||
i18n( "linter_enable_lsp_diagnostics", "Language Server Diagnostics" ),
|
||||
i18n( "linter_enable_lsp_diagnostics_desc",
|
||||
"Display diagnostics reported by language servers." ),
|
||||
true );
|
||||
page.addBool( "enable-error-lens", "/config/enable_error_lens",
|
||||
i18n( "linter_enable_error_lens", "Error Lens" ),
|
||||
i18n( "linter_enable_error_lens_desc",
|
||||
"Display diagnostic messages inline in the editor." ),
|
||||
true );
|
||||
page.addStringList(
|
||||
"disable-lsp-languages", "/config/disable_lsp_languages",
|
||||
i18n( "linter_disable_lsp_languages", "Disable LSP Diagnostic Languages" ),
|
||||
i18n( "linter_disable_lsp_languages_desc",
|
||||
"Comma-separated language identifiers where LSP diagnostics are disabled." ) );
|
||||
page.addStringList(
|
||||
"disable-languages", "/config/disable_languages",
|
||||
i18n( "linter_disable_languages", "Disable Linter Languages" ),
|
||||
i18n( "linter_disable_languages_desc",
|
||||
"Comma-separated language identifiers where linters are disabled." ) );
|
||||
page.addBool( "goto-ignore-warnings", "/config/goto_ignore_warnings",
|
||||
i18n( "linter_goto_ignore_warnings", "Ignore Warnings When Navigating" ),
|
||||
i18n( "linter_goto_ignore_warnings_desc",
|
||||
"Skip warnings when navigating between diagnostics." ),
|
||||
false );
|
||||
}
|
||||
|
||||
Plugin* LinterPlugin::New( PluginManager* pluginManager ) {
|
||||
return eeNew( LinterPlugin, ( pluginManager, false ) );
|
||||
}
|
||||
@@ -1145,9 +1181,8 @@ void LinterPlugin::drawAfterLineText( UICodeEditor* editor, const Int64& index,
|
||||
Color wcolor(
|
||||
editor->getColorScheme().getEditorSyntaxStyle( "warning"_sst ).color );
|
||||
if ( mLightbulbIcon == nullptr )
|
||||
mLightbulbIcon =
|
||||
editor->getUISceneNode()->getUIIconThemeManager()->findIcon(
|
||||
"lightbulb-autofix" );
|
||||
mLightbulbIcon = editor->getUISceneNode()->getUIIconThemeManager()->findIcon(
|
||||
"lightbulb-autofix" );
|
||||
if ( nullptr != mLightbulbIcon ) {
|
||||
const int iconSize = (int)eefloor( lineHeight );
|
||||
Drawable* drawable = mLightbulbIcon->getSource( iconSize ).get();
|
||||
|
||||
@@ -76,6 +76,10 @@ class LinterPlugin : public Plugin {
|
||||
|
||||
std::string getDescription() { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
virtual String::HashType getConfigFileHash() { return mConfigHash; }
|
||||
|
||||
void onRegister( UICodeEditor* );
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lspclientplugin.hpp"
|
||||
#include "../../notificationcenter.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include "../../version.hpp"
|
||||
#include <eepp/graphics/primitives.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
@@ -26,6 +27,52 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void LSPClientPlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addText( "hover-delay", "/config/hover_delay", i18n( "lsp_hover_delay", "Hover Delay" ),
|
||||
i18n( "lsp_hover_delay_desc",
|
||||
"Time to wait before showing language server information while hovering." ),
|
||||
mHoverDelay.toString(), []( const std::string& text ) {
|
||||
Time value;
|
||||
return SettingsPage::parseNonNegativeSettingsTime( text, value );
|
||||
} );
|
||||
page.addText( "server-close-after-idle-time", "/config/server_close_after_idle_time",
|
||||
i18n( "lsp_server_close_after_idle_time", "Server Close After Idle Time" ),
|
||||
i18n( "lsp_server_close_after_idle_time_desc",
|
||||
"Time to keep an unused language server running before closing it." ),
|
||||
mClientManager.getLSPDecayTime().toString(), []( const std::string& text ) {
|
||||
Time value;
|
||||
return SettingsPage::parseNonNegativeSettingsTime( text, value );
|
||||
} );
|
||||
page.addBool( "silent", "/config/silent", i18n( "lsp_silent", "Silent Language Server Logs" ),
|
||||
i18n( "lsp_silent_desc", "Hide non-critical language server log messages." ),
|
||||
mSilence );
|
||||
page.addBool(
|
||||
"trim-logs", "/config/trim_logs", i18n( "lsp_trim_logs", "Trim Language Server Logs" ),
|
||||
i18n( "lsp_trim_logs_desc", "Limit each language server log line to 1 KiB." ), mTrimLogs );
|
||||
page.addBool( "semantic-highlighting", "/config/semantic_highlighting",
|
||||
i18n( "lsp_semantic_highlighting", "Semantic Highlighting" ),
|
||||
i18n( "lsp_semantic_highlighting_desc",
|
||||
"Use semantic tokens provided by language servers when available." ),
|
||||
mSemanticHighlighting );
|
||||
page.addStringList(
|
||||
"disable-semantic-highlighting-lang", "/config/disable_semantic_highlighting_lang",
|
||||
i18n( "lsp_disable_semantic_highlighting_lang", "Disable Semantic Highlighting Languages" ),
|
||||
i18n( "lsp_disable_semantic_highlighting_lang_desc",
|
||||
"Comma-separated language identifiers where semantic highlighting is disabled." ) );
|
||||
page.addBool( "breadcrumb-navigation", "/config/breadcrumb_navigation",
|
||||
i18n( "lsp_breadcrumb_navigation", "Breadcrumb Navigation" ),
|
||||
i18n( "lsp_breadcrumb_navigation_desc",
|
||||
"Display language-aware breadcrumb navigation above the editor." ),
|
||||
mBreadcrumb );
|
||||
page.addText(
|
||||
"breadcrumb-height", "/config/breadcrumb_height",
|
||||
i18n( "lsp_breadcrumb_height", "Breadcrumb Height" ),
|
||||
i18n( "lsp_breadcrumb_height_desc", "Height of the editor breadcrumb using a CSS length." ),
|
||||
mBreadcrumbHeight.toString(),
|
||||
[]( const std::string& text ) { return StyleSheetLength::isLength( text ); } );
|
||||
}
|
||||
|
||||
static Action::UniqueID getMouseMoveHash( UICodeEditor* editor ) {
|
||||
return hashCombine( String::hash( "LSPClientPlugin::onMouseMove-" ),
|
||||
reinterpret_cast<Action::UniqueID>( editor ) );
|
||||
@@ -1982,8 +2029,8 @@ void LSPClientPlugin::drawTop( UICodeEditor* editor, const Vector2f& screenStart
|
||||
Vector2f iconPos( { pos.x, screenStart.y + textOffsetY +
|
||||
eefloor( ( textHeight - iconHeight ) * 0.5f ) } );
|
||||
separatorDrawable->draw( iconPos );
|
||||
pos.x +=
|
||||
separatorDrawable->getPixelsSize().getWidth() + eefloor( PixelDensity::dpToPx( 8 ) );
|
||||
pos.x += separatorDrawable->getPixelsSize().getWidth() +
|
||||
eefloor( PixelDensity::dpToPx( 8 ) );
|
||||
separatorDrawable->setColor( c );
|
||||
} else {
|
||||
pos.x += eefloor( PixelDensity::dpToPx( 16 ) );
|
||||
|
||||
@@ -46,6 +46,10 @@ class LSPClientPlugin : public Plugin {
|
||||
|
||||
virtual String::HashType getConfigFileHash() { return mConfigHash; }
|
||||
|
||||
bool hasSettingsPage() const { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page );
|
||||
|
||||
void onRegister( UICodeEditor* );
|
||||
|
||||
void onUnregister( UICodeEditor* );
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace ecode {
|
||||
|
||||
class PluginManager;
|
||||
class PluginContextProvider;
|
||||
class SettingsPage;
|
||||
|
||||
class Plugin : public UICodeEditorPlugin {
|
||||
public:
|
||||
@@ -45,6 +46,10 @@ class Plugin : public UICodeEditorPlugin {
|
||||
|
||||
virtual std::string getFileConfigPath();
|
||||
|
||||
virtual bool hasSettingsPage() const { return false; }
|
||||
|
||||
virtual void registerSettings( SettingsPage& ) {}
|
||||
|
||||
PluginManager* getManager() const;
|
||||
|
||||
PluginContextProvider* getPluginContext() const;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "spellcheckerplugin.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include "eepp/ui/abstract/uiabstractview.hpp"
|
||||
#include "eepp/ui/models/itemlistmodel.hpp"
|
||||
#include "eepp/window/engine.hpp"
|
||||
@@ -15,6 +16,18 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void SpellCheckerPlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addText( "delay-time", "/config/delay_time",
|
||||
i18n( "spellchecker_delay_time", "Spell Check Delay" ),
|
||||
i18n( "spellchecker_delay_time_desc",
|
||||
"Time to wait before checking spelling after an edit." ),
|
||||
getDelayTime().toString(), []( const std::string& text ) {
|
||||
Time value;
|
||||
return SettingsPage::parseNonNegativeSettingsTime( text, value );
|
||||
} );
|
||||
}
|
||||
|
||||
static constexpr auto SPELL_CHECKER_CMD = "typos";
|
||||
static constexpr auto SPELL_CHECKER_ARGS = "--format=brief";
|
||||
|
||||
|
||||
@@ -39,6 +39,10 @@ class SpellCheckerPlugin : public PluginBase {
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
void drawAfterLineText( UICodeEditor* editor, const Int64& index, Vector2f position,
|
||||
const Float& fontSize, const Float& lineHeight ) override;
|
||||
|
||||
@@ -98,7 +102,8 @@ class SpellCheckerPlugin : public PluginBase {
|
||||
|
||||
void invalidateEditors( TextDocument* doc );
|
||||
|
||||
std::optional<SpellCheckerMatch> getMatchFromTextPosition( UICodeEditor* editor, TextPosition pos );
|
||||
std::optional<SpellCheckerMatch> getMatchFromTextPosition( UICodeEditor* editor,
|
||||
TextPosition pos );
|
||||
|
||||
std::optional<SpellCheckerMatch> getMatchFromScreenPos( UICodeEditor* editor, Vector2f pos );
|
||||
|
||||
@@ -109,7 +114,6 @@ class SpellCheckerPlugin : public PluginBase {
|
||||
void goToNextError( UICodeEditor* editor );
|
||||
|
||||
void goToPrevError( UICodeEditor* editor );
|
||||
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "xmltoolsplugin.hpp"
|
||||
#include "../../settingspage.hpp"
|
||||
#include <eepp/graphics/primitives.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/scopedop.hpp>
|
||||
@@ -8,6 +9,20 @@ using json = nlohmann::json;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
void XMLToolsPlugin::registerSettings( SettingsPage& page ) {
|
||||
page.addGroup( i18n( "general", "General" ) );
|
||||
page.addBool( "highlight-match", "/config/highlight_match",
|
||||
i18n( "xmltools_highlight_match", "Highlight Matching Tags" ),
|
||||
i18n( "xmltools_highlight_match_desc",
|
||||
"Highlight the matching XML or HTML tag at the cursor." ),
|
||||
true );
|
||||
page.addBool( "auto-edit-match", "/config/auto_edit_match",
|
||||
i18n( "xmltools_auto_edit_match", "Edit Matching Tags" ),
|
||||
i18n( "xmltools_auto_edit_match_desc",
|
||||
"Update the matching tag automatically while editing." ),
|
||||
true );
|
||||
}
|
||||
|
||||
Plugin* XMLToolsPlugin::New( PluginManager* pluginManager ) {
|
||||
return eeNew( XMLToolsPlugin, ( pluginManager, false ) );
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ class XMLToolsPlugin : public PluginBase {
|
||||
|
||||
std::string getDescription() override { return Definition().description; }
|
||||
|
||||
bool hasSettingsPage() const override { return true; }
|
||||
|
||||
void registerSettings( SettingsPage& page ) override;
|
||||
|
||||
bool getHighlightMatch() const;
|
||||
|
||||
bool getAutoEditMatch() const;
|
||||
@@ -73,17 +77,29 @@ class XMLToolsPlugin : public PluginBase {
|
||||
mDoc( doc ), mParent( parent ) {}
|
||||
|
||||
virtual void onDocumentTextChanged( const DocumentContentChange& );
|
||||
|
||||
virtual void onDocumentUndoRedo( const TextDocument::UndoRedo& ) {}
|
||||
|
||||
virtual void onDocumentCursorChange( const TextPosition& ) {}
|
||||
|
||||
virtual void onDocumentInterestingCursorChange( const TextPosition& ) {}
|
||||
|
||||
virtual void onDocumentSelectionChange( const TextRange& );
|
||||
|
||||
virtual void onDocumentLineCountChange( const size_t&, const size_t& ) {}
|
||||
|
||||
virtual void onDocumentLineChanged( const Int64& ) {}
|
||||
|
||||
virtual void onDocumentSaved( TextDocument* ) {}
|
||||
|
||||
virtual void onDocumentClosed( TextDocument* doc ) { onDocumentReset( doc ); }
|
||||
|
||||
virtual void onDocumentDirtyOnFileSystem( TextDocument* ) {}
|
||||
|
||||
virtual void onDocumentMoved( TextDocument* ) {};
|
||||
|
||||
virtual void onDocumentReset( TextDocument* ) { mSelections.clear(); }
|
||||
|
||||
Client::Type getTextDocumentClientType() { return TextDocument::Client::Auxiliary; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "settingsdocument.hpp"
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
|
||||
using namespace EE::System;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
SettingsDocument::SettingsDocument( std::string path, nlohmann::json data ) :
|
||||
mPath( std::move( path ) ), mOriginal( data ), mData( std::move( data ) ) {}
|
||||
|
||||
std::shared_ptr<SettingsDocument> SettingsDocument::load( std::string path, std::string& error ) {
|
||||
std::string contents;
|
||||
if ( !FileSystem::fileGet( path, contents ) ) {
|
||||
error = "Unable to read settings file";
|
||||
return {};
|
||||
}
|
||||
try {
|
||||
auto data = nlohmann::json::parse( contents, nullptr, true, true );
|
||||
if ( !data.is_object() ) {
|
||||
error = "Settings file root must be an object";
|
||||
return {};
|
||||
}
|
||||
return std::shared_ptr<SettingsDocument>(
|
||||
new SettingsDocument( std::move( path ), std::move( data ) ) );
|
||||
} catch ( const nlohmann::json::exception& exception ) {
|
||||
error = exception.what();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingsDocument::save() {
|
||||
if ( !mDirty )
|
||||
return true;
|
||||
if ( !FileSystem::fileWrite( mPath, mData.dump( 2 ) ) )
|
||||
return false;
|
||||
mOriginal = mData;
|
||||
mDirty = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
nlohmann::json SettingsDocument::getValue( const std::string& pointer,
|
||||
nlohmann::json fallback ) const {
|
||||
try {
|
||||
const auto path = nlohmann::json::json_pointer( pointer );
|
||||
if ( mData.contains( path ) )
|
||||
return mData.at( path );
|
||||
} catch ( const nlohmann::json::exception& ) {
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
bool SettingsDocument::setValue( const std::string& pointer, nlohmann::json value ) {
|
||||
try {
|
||||
const auto path = nlohmann::json::json_pointer( pointer );
|
||||
if ( mData.contains( path ) && mData.at( path ) == value )
|
||||
return false;
|
||||
mData[path] = std::move( value );
|
||||
mDirty = true;
|
||||
return true;
|
||||
} catch ( const nlohmann::json::exception& ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingsDocument::contains( const std::string& pointer ) const {
|
||||
try {
|
||||
return mData.contains( nlohmann::json::json_pointer( pointer ) );
|
||||
} catch ( const nlohmann::json::exception& ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDocument::discard() {
|
||||
mData = mOriginal;
|
||||
mDirty = false;
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef ECODE_SETTINGSDOCUMENT_HPP
|
||||
#define ECODE_SETTINGSDOCUMENT_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace ecode {
|
||||
|
||||
class SettingsDocument {
|
||||
public:
|
||||
static std::shared_ptr<SettingsDocument> load( std::string path, std::string& error );
|
||||
|
||||
template <typename T> T get( const std::string& pointer, T fallback ) const {
|
||||
try {
|
||||
const auto path = nlohmann::json::json_pointer( pointer );
|
||||
if ( mData.contains( path ) )
|
||||
return mData.at( path ).get<T>();
|
||||
} catch ( const nlohmann::json::exception& ) {
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
template <typename T> bool set( const std::string& pointer, T value ) {
|
||||
try {
|
||||
const auto path = nlohmann::json::json_pointer( pointer );
|
||||
if ( mData.contains( path ) && mData.at( path ) == value )
|
||||
return false;
|
||||
mData[path] = std::move( value );
|
||||
mDirty = true;
|
||||
return true;
|
||||
} catch ( const nlohmann::json::exception& ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json getValue( const std::string& pointer, nlohmann::json fallback ) const;
|
||||
|
||||
bool setValue( const std::string& pointer, nlohmann::json value );
|
||||
|
||||
bool contains( const std::string& pointer ) const;
|
||||
|
||||
bool save();
|
||||
|
||||
void discard();
|
||||
|
||||
bool isDirty() const { return mDirty; }
|
||||
|
||||
const std::string& path() const { return mPath; }
|
||||
|
||||
private:
|
||||
SettingsDocument( std::string path, nlohmann::json data );
|
||||
|
||||
std::string mPath;
|
||||
nlohmann::json mOriginal;
|
||||
nlohmann::json mData;
|
||||
bool mDirty{ false };
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
#endif
|
||||
@@ -52,6 +52,7 @@ struct TextSetting {
|
||||
std::function<std::string()> get;
|
||||
std::function<bool( const std::string& )> set;
|
||||
bool commitOnFocusLoss{ false };
|
||||
bool password{ false };
|
||||
};
|
||||
|
||||
struct FloatSetting {
|
||||
@@ -129,8 +130,11 @@ class SettingsModel {
|
||||
}
|
||||
|
||||
const std::vector<SettingsCategory>& categories() const { return mCategories; }
|
||||
|
||||
const std::vector<SettingsGroup>& groups() const { return mGroups; }
|
||||
|
||||
std::vector<SettingDefinition>& settings() { return mSettings; }
|
||||
|
||||
const std::vector<SettingDefinition>& settings() const { return mSettings; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
#include "settingspage.hpp"
|
||||
|
||||
namespace ecode {
|
||||
|
||||
bool SettingsPage::parseNonNegativeSettingsTime( const std::string& text, Time& time ) {
|
||||
auto parts = String::split( text, " " );
|
||||
bool hasValue = false;
|
||||
for ( auto& part : parts ) {
|
||||
String::trimInPlace( part );
|
||||
if ( part.empty() )
|
||||
continue;
|
||||
size_t suffixLength =
|
||||
String::endsWith( part, "ms" )
|
||||
? 2
|
||||
: ( String::endsWith( part, "s" ) || String::endsWith( part, "m" ) ? 1 : 0 );
|
||||
std::string number = part.substr( 0, part.size() - suffixLength );
|
||||
double value;
|
||||
if ( number.empty() || !String::fromString( value, number ) || value < 0 )
|
||||
return false;
|
||||
hasValue = true;
|
||||
}
|
||||
if ( !hasValue )
|
||||
return false;
|
||||
time = Time::fromString( text );
|
||||
return true;
|
||||
}
|
||||
|
||||
SettingsPage::SettingsPage( SettingsModel& model, std::shared_ptr<SettingsDocument> document,
|
||||
std::string category, std::string idPrefix ) :
|
||||
mModel( model ),
|
||||
mDocument( std::move( document ) ),
|
||||
mCategory( std::move( category ) ),
|
||||
mIdPrefix( std::move( idPrefix ) ) {}
|
||||
|
||||
bool SettingsPage::addGroup( String name ) {
|
||||
return mModel.addGroup( { mCategory, std::move( name ), mModel.settings().size() } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addBool( std::string id, std::string jsonPointer, String name,
|
||||
String description, bool defaultValue, String group ) {
|
||||
if ( !mDocument )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting( { { mIdPrefix + "." + id, mCategory, std::move( name ),
|
||||
std::move( description ), std::move( group ) },
|
||||
BoolSetting{ [document, jsonPointer, defaultValue] {
|
||||
return document->get<bool>( jsonPointer,
|
||||
defaultValue );
|
||||
},
|
||||
[document, jsonPointer]( bool value ) {
|
||||
document->set( jsonPointer, value );
|
||||
} } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addChoice( std::string id, std::string jsonPointer, String name,
|
||||
String description, std::vector<String> choices,
|
||||
std::vector<nlohmann::json> values, nlohmann::json defaultValue,
|
||||
std::vector<String> choiceDescriptions, String group ) {
|
||||
if ( !mDocument || choices.empty() || choices.size() != values.size() )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
auto mappedValues = std::make_shared<const std::vector<nlohmann::json>>( std::move( values ) );
|
||||
return mModel.addSetting(
|
||||
{ { mIdPrefix + "." + id, mCategory, std::move( name ), std::move( description ),
|
||||
std::move( group ) },
|
||||
ChoiceSetting{
|
||||
std::move( choices ), std::move( choiceDescriptions ),
|
||||
[document, jsonPointer, mappedValues, defaultValue = std::move( defaultValue )] {
|
||||
const auto current = document->getValue( jsonPointer, defaultValue );
|
||||
auto found = std::find( mappedValues->begin(), mappedValues->end(), current );
|
||||
return found == mappedValues->end()
|
||||
? size_t{ 0 }
|
||||
: static_cast<size_t>( std::distance( mappedValues->begin(), found ) );
|
||||
},
|
||||
[document, jsonPointer, mappedValues]( size_t selected ) {
|
||||
if ( selected < mappedValues->size() )
|
||||
document->setValue( jsonPointer, ( *mappedValues )[selected] );
|
||||
} } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addEditableChoice( std::string id, std::string jsonPointer, String name,
|
||||
String description, std::vector<String> choices,
|
||||
std::string defaultValue,
|
||||
std::function<bool( const std::string& )> validate,
|
||||
String group ) {
|
||||
if ( !mDocument )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting(
|
||||
{ { mIdPrefix + "." + id, mCategory, std::move( name ), std::move( description ),
|
||||
std::move( group ) },
|
||||
EditableChoiceSetting{
|
||||
std::move( choices ),
|
||||
[document, jsonPointer, defaultValue = std::move( defaultValue )] {
|
||||
return String::fromUtf8(
|
||||
document->get<std::string>( jsonPointer, defaultValue ) );
|
||||
},
|
||||
[document, jsonPointer, validate = std::move( validate )]( const String& value ) {
|
||||
const std::string text = value.toUtf8();
|
||||
if ( validate && !validate( text ) )
|
||||
return false;
|
||||
document->set( jsonPointer, text );
|
||||
return true;
|
||||
} } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addInteger( std::string id, std::string jsonPointer, String name,
|
||||
String description, int min, int max, int defaultValue,
|
||||
String group ) {
|
||||
if ( !mDocument || min > max )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting( { { mIdPrefix + "." + id, mCategory, std::move( name ),
|
||||
std::move( description ), std::move( group ) },
|
||||
IntegerSetting{ min, max,
|
||||
[document, jsonPointer, defaultValue] {
|
||||
return document->get<int>( jsonPointer,
|
||||
defaultValue );
|
||||
},
|
||||
[document, jsonPointer]( int value ) {
|
||||
document->set( jsonPointer, value );
|
||||
} } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addText( std::string id, std::string jsonPointer, String name,
|
||||
String description, std::string defaultValue,
|
||||
std::function<bool( const std::string& )> validate,
|
||||
bool commitOnFocusLoss, String group ) {
|
||||
if ( !mDocument )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting(
|
||||
{ { mIdPrefix + "." + id, mCategory, std::move( name ), std::move( description ),
|
||||
std::move( group ) },
|
||||
TextSetting{ [document, jsonPointer, defaultValue = std::move( defaultValue )] {
|
||||
return document->get<std::string>( jsonPointer, defaultValue );
|
||||
},
|
||||
[document, jsonPointer,
|
||||
validate = std::move( validate )]( const std::string& value ) {
|
||||
if ( validate && !validate( value ) )
|
||||
return false;
|
||||
document->set( jsonPointer, value );
|
||||
return true;
|
||||
},
|
||||
commitOnFocusLoss } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addSecret( std::string id, std::string jsonPointer, String name,
|
||||
String description, std::string defaultValue, String group,
|
||||
std::string legacyJsonPointer ) {
|
||||
if ( !mDocument )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting(
|
||||
{ { mIdPrefix + "." + id, mCategory, std::move( name ), std::move( description ),
|
||||
std::move( group ) },
|
||||
TextSetting{
|
||||
[document, jsonPointer, legacyJsonPointer, defaultValue = std::move( defaultValue )] {
|
||||
if ( !legacyJsonPointer.empty() && !document->contains( jsonPointer ) )
|
||||
return document->get<std::string>( legacyJsonPointer, defaultValue );
|
||||
return document->get<std::string>( jsonPointer, defaultValue );
|
||||
},
|
||||
[document, jsonPointer]( const std::string& value ) {
|
||||
document->set( jsonPointer, value );
|
||||
return true;
|
||||
},
|
||||
true, true } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addJsonObject( std::string id, std::string jsonPointer, String name,
|
||||
String description, nlohmann::json defaultValue, String group ) {
|
||||
if ( !mDocument || !defaultValue.is_object() )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting(
|
||||
{ { mIdPrefix + "." + id, mCategory, std::move( name ), std::move( description ),
|
||||
std::move( group ) },
|
||||
TextSetting{ [document, jsonPointer, defaultValue = std::move( defaultValue )] {
|
||||
return document->getValue( jsonPointer, defaultValue ).dump();
|
||||
},
|
||||
[document, jsonPointer]( const std::string& value ) {
|
||||
auto parsed = nlohmann::json::parse( value, nullptr, false );
|
||||
if ( !parsed.is_object() )
|
||||
return false;
|
||||
document->setValue( jsonPointer, std::move( parsed ) );
|
||||
return true;
|
||||
},
|
||||
true } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addStringList( std::string id, std::string jsonPointer, String name,
|
||||
String description, std::vector<std::string> defaultValue,
|
||||
String group ) {
|
||||
if ( !mDocument )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting(
|
||||
{ { mIdPrefix + "." + id, mCategory, std::move( name ), std::move( description ),
|
||||
std::move( group ) },
|
||||
TextSetting{ [document, jsonPointer, defaultValue = std::move( defaultValue )] {
|
||||
return String::join(
|
||||
document->get<std::vector<std::string>>( jsonPointer, defaultValue ),
|
||||
',' );
|
||||
},
|
||||
[document, jsonPointer]( const std::string& value ) {
|
||||
std::vector<std::string> values;
|
||||
for ( auto& item : String::split( value, "," ) ) {
|
||||
String::trimInPlace( item );
|
||||
if ( !item.empty() )
|
||||
values.emplace_back( std::move( item ) );
|
||||
}
|
||||
document->set( jsonPointer, std::move( values ) );
|
||||
return true;
|
||||
},
|
||||
true } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addFloat( std::string id, std::string jsonPointer, String name,
|
||||
String description, double min, double max, double step,
|
||||
double defaultValue, String group ) {
|
||||
if ( !mDocument || min > max || step <= 0 )
|
||||
return false;
|
||||
auto document = mDocument;
|
||||
return mModel.addSetting( { { mIdPrefix + "." + id, mCategory, std::move( name ),
|
||||
std::move( description ), std::move( group ) },
|
||||
FloatSetting{ min, max, step,
|
||||
[document, jsonPointer, defaultValue] {
|
||||
return document->get<double>( jsonPointer,
|
||||
defaultValue );
|
||||
},
|
||||
[document, jsonPointer]( double value ) {
|
||||
document->set( jsonPointer, value );
|
||||
} } } );
|
||||
}
|
||||
|
||||
bool SettingsPage::addAction( std::string id, String name, String description, String buttonText,
|
||||
std::function<void()> action, String group ) {
|
||||
if ( !action )
|
||||
return false;
|
||||
return mModel.addSetting( { { mIdPrefix + "." + id, mCategory, std::move( name ),
|
||||
std::move( description ), std::move( group ) },
|
||||
ActionSetting{ std::move( buttonText ), std::move( action ) } } );
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef ECODE_SETTINGSPAGE_HPP
|
||||
#define ECODE_SETTINGSPAGE_HPP
|
||||
|
||||
#include "settingsdocument.hpp"
|
||||
#include "settingsmodel.hpp"
|
||||
|
||||
namespace ecode {
|
||||
|
||||
class SettingsPage {
|
||||
public:
|
||||
static bool parseNonNegativeSettingsTime( const std::string& text, Time& time );
|
||||
|
||||
SettingsPage( SettingsModel& model, std::shared_ptr<SettingsDocument> document,
|
||||
std::string category, std::string idPrefix );
|
||||
|
||||
bool addGroup( String name );
|
||||
|
||||
bool addBool( std::string id, std::string jsonPointer, String name, String description,
|
||||
bool defaultValue, String group = {} );
|
||||
|
||||
bool addChoice( std::string id, std::string jsonPointer, String name, String description,
|
||||
std::vector<String> choices, std::vector<nlohmann::json> values,
|
||||
nlohmann::json defaultValue, std::vector<String> choiceDescriptions = {},
|
||||
String group = {} );
|
||||
|
||||
bool addEditableChoice( std::string id, std::string jsonPointer, String name,
|
||||
String description, std::vector<String> choices,
|
||||
std::string defaultValue,
|
||||
std::function<bool( const std::string& )> validate = {},
|
||||
String group = {} );
|
||||
|
||||
bool addInteger( std::string id, std::string jsonPointer, String name, String description,
|
||||
int min, int max, int defaultValue, String group = {} );
|
||||
|
||||
bool addText( std::string id, std::string jsonPointer, String name, String description,
|
||||
std::string defaultValue, std::function<bool( const std::string& )> validate = {},
|
||||
bool commitOnFocusLoss = false, String group = {} );
|
||||
|
||||
bool addSecret( std::string id, std::string jsonPointer, String name, String description,
|
||||
std::string defaultValue = {}, String group = {},
|
||||
std::string legacyJsonPointer = {} );
|
||||
|
||||
bool addJsonObject( std::string id, std::string jsonPointer, String name, String description,
|
||||
nlohmann::json defaultValue = nlohmann::json::object(), String group = {} );
|
||||
|
||||
bool addStringList( std::string id, std::string jsonPointer, String name, String description,
|
||||
std::vector<std::string> defaultValue = {}, String group = {} );
|
||||
|
||||
bool addFloat( std::string id, std::string jsonPointer, String name, String description,
|
||||
double min, double max, double step, double defaultValue, String group = {} );
|
||||
|
||||
bool addAction( std::string id, String name, String description, String buttonText,
|
||||
std::function<void()> action, String group = {} );
|
||||
|
||||
private:
|
||||
SettingsModel& mModel;
|
||||
std::shared_ptr<SettingsDocument> mDocument;
|
||||
std::string mCategory;
|
||||
std::string mIdPrefix;
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "settingspanel.hpp"
|
||||
#include "datetimecontroller.hpp"
|
||||
#include "ecode.hpp"
|
||||
#include "plugins/plugin.hpp"
|
||||
#include "plugins/pluginmanager.hpp"
|
||||
#include "settingsdocument.hpp"
|
||||
#include "settingspage.hpp"
|
||||
#include "uitreeviewfs.hpp"
|
||||
#include <deque>
|
||||
#include <limits>
|
||||
@@ -220,6 +224,9 @@ static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml(
|
||||
layout-width: 210dp;
|
||||
layout-height: wrap_content;
|
||||
}
|
||||
.settings_panel .settings_text.error {
|
||||
border-color: var(--theme-error);
|
||||
}
|
||||
.settings_panel .settings_integer {
|
||||
layout-width: 110dp;
|
||||
layout-height: wrap_content;
|
||||
@@ -230,7 +237,7 @@ static constexpr const char* SETTINGS_PANEL_LAYOUT = R"xml(
|
||||
<Splitter id="settings_splitter" lw="mp" lh="mp" orientation="horizontal" splitter-partition="220dp">
|
||||
<vbox id="settings_sidebar" lw="0" lh="0" min-width="160dp">
|
||||
<TextInput id="settings_filter" lw="mp" lh="wc" hint="@string(search_settings, Search settings...)" />
|
||||
<TreeView id="settings_categories" lw="mp" lh="mp" />
|
||||
<TreeView id="settings_categories" lw="mp" lh="o" lw8="1" />
|
||||
</vbox>
|
||||
<ScrollView id="settings_scroll" lw="0" lw8="1" lh="mp" focusable="false">
|
||||
<vbox id="settings_rows" lw="mp" lh="wc">
|
||||
@@ -327,6 +334,7 @@ void SettingsPanel::PanelState::reset() {
|
||||
materializedCategories.clear();
|
||||
subcategoryHeadings.clear();
|
||||
model.clear();
|
||||
documents.clear();
|
||||
settingViews.clear();
|
||||
selectedCategory.clear();
|
||||
categoryFilter.clear();
|
||||
@@ -426,10 +434,12 @@ void SettingsPanel::create( Scope scope ) {
|
||||
panel.window->getKeyBindings().addKeybind(
|
||||
{ KEY_E, KeyMod::getDefaultModifier() | KEYMOD_SHIFT }, "focusSettingsCategories" );
|
||||
panel.settings->beginAttributesTransaction();
|
||||
if ( scope == Scope::User )
|
||||
if ( scope == Scope::User ) {
|
||||
addUserSettings( panel );
|
||||
else
|
||||
addPluginSettings( panel );
|
||||
} else {
|
||||
addProjectSettings( panel );
|
||||
}
|
||||
materializeCategory( panel, panel.selectedCategory );
|
||||
setupCategories( panel );
|
||||
panel.settings->endAttributesTransaction();
|
||||
@@ -459,6 +469,10 @@ void SettingsPanel::create( Scope scope ) {
|
||||
} );
|
||||
panel.connections +=
|
||||
panel.window->connect( Event::OnWindowClose, [this, &panel, scope]( const Event* ) {
|
||||
for ( const auto& document : panel.documents ) {
|
||||
if ( !document->save() )
|
||||
Log::error( "Could not save settings document: %s", document->path() );
|
||||
}
|
||||
if ( scope == Scope::User )
|
||||
mApp->saveConfig();
|
||||
else
|
||||
@@ -501,7 +515,6 @@ void SettingsPanel::addCategory( PanelState& panel, const std::string& id, const
|
||||
void SettingsPanel::addSubcategoryHeading( PanelState& panel, const std::string& category,
|
||||
const String& name ) {
|
||||
panel.model.addGroup( { category, name, panel.model.settings().size() } );
|
||||
panel.subcategoryHeadings.push_back( { category, name, nullptr } );
|
||||
}
|
||||
|
||||
void SettingsPanel::setupCategories( PanelState& panel ) {
|
||||
@@ -636,14 +649,7 @@ void SettingsPanel::materializeCategory( PanelState& panel, const std::string& c
|
||||
->loadLayoutFromString( SETTINGS_SUBCATEGORY_HEADING_LAYOUT, container->second )
|
||||
->asType<UITextView>();
|
||||
heading->setText( group.name );
|
||||
auto subcategory =
|
||||
std::find_if( panel.subcategoryHeadings.begin(), panel.subcategoryHeadings.end(),
|
||||
[&group]( const auto& item ) {
|
||||
return item.category == group.category &&
|
||||
item.name == group.name && !item.heading;
|
||||
} );
|
||||
if ( subcategory != panel.subcategoryHeadings.end() )
|
||||
subcategory->heading = heading;
|
||||
panel.subcategoryHeadings.push_back( { group.category, group.name, heading } );
|
||||
}
|
||||
auto& view = panel.settingViews[i];
|
||||
if ( auto* value = std::get_if<BoolPointerSetting>( &setting.value ) ) {
|
||||
@@ -712,6 +718,8 @@ void SettingsPanel::materializeCategory( PanelState& panel, const std::string& c
|
||||
} else if ( auto* value = std::get_if<TextSetting>( &setting.value ) ) {
|
||||
auto* row = createRow( panel, setting, view, SETTINGS_TEXT_ROW_LAYOUT.root() );
|
||||
auto* input = row->find<UITextInput>( "setting_control_widget" );
|
||||
if ( value->password )
|
||||
input->setMode( UITextInput::TextInputMode::Password );
|
||||
input->setText( String::fromUtf8( value->get() ) );
|
||||
auto commit = [input, value]( const Event* ) {
|
||||
if ( !value->set( input->getText().toUtf8() ) ) {
|
||||
@@ -787,29 +795,6 @@ static void setNodeTreeEnabled( Node* node, bool enabled ) {
|
||||
setNodeTreeEnabled( child, enabled );
|
||||
}
|
||||
|
||||
static bool parseNonNegativeTime( const std::string& text, Time& time ) {
|
||||
auto parts = String::split( text, " " );
|
||||
bool hasValue = false;
|
||||
for ( auto& part : parts ) {
|
||||
String::trimInPlace( part );
|
||||
if ( part.empty() )
|
||||
continue;
|
||||
size_t suffixLength =
|
||||
String::endsWith( part, "ms" )
|
||||
? 2
|
||||
: ( String::endsWith( part, "s" ) || String::endsWith( part, "m" ) ? 1 : 0 );
|
||||
std::string number = part.substr( 0, part.size() - suffixLength );
|
||||
double value;
|
||||
if ( number.empty() || !String::fromString( value, number ) || value < 0 )
|
||||
return false;
|
||||
hasValue = true;
|
||||
}
|
||||
if ( !hasValue )
|
||||
return false;
|
||||
time = Time::fromString( text );
|
||||
return true;
|
||||
}
|
||||
|
||||
void SettingsPanel::setCategoryEnabled( PanelState& panel, const std::string& category,
|
||||
bool enabled, const std::string& excludedSetting ) {
|
||||
auto& settings = panel.model.settings();
|
||||
@@ -1633,7 +1618,7 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
||||
[this] { return mApp->getConfig().editor.cursorBlinkingTime.toString(); },
|
||||
[this]( const std::string& text ) {
|
||||
Time value;
|
||||
if ( !parseNonNegativeTime( text, value ) )
|
||||
if ( !SettingsPage::parseNonNegativeSettingsTime( text, value ) )
|
||||
return false;
|
||||
mApp->getConfig().editor.cursorBlinkingTime = value;
|
||||
mApp->getSplitter()->forEachEditor(
|
||||
@@ -1695,7 +1680,8 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
||||
[this] { return mApp->getConfig().editor.codeFoldingRefreshFreq.toString(); },
|
||||
[this]( const std::string& text ) {
|
||||
Time value;
|
||||
if ( !parseNonNegativeTime( text, value ) || value < Seconds( 1 ) )
|
||||
if ( !SettingsPage::parseNonNegativeSettingsTime( text, value ) ||
|
||||
value < Seconds( 1 ) )
|
||||
return false;
|
||||
mApp->getConfig().editor.codeFoldingRefreshFreq = value;
|
||||
mApp->getSplitter()->forEachEditor(
|
||||
@@ -2036,6 +2022,42 @@ void SettingsPanel::addUserSettings( PanelState& panel ) {
|
||||
"Keep the terminal scrollbar hidden." ) } );
|
||||
}
|
||||
|
||||
void SettingsPanel::addPluginSettings( PanelState& panel ) {
|
||||
auto* manager = mApp->getPluginManager();
|
||||
if ( !manager )
|
||||
return;
|
||||
manager->forEachPlugin( [this, &panel]( Plugin* plugin ) {
|
||||
if ( !plugin || !plugin->isReady() || !plugin->hasSettingsPage() ||
|
||||
!plugin->hasFileConfig() )
|
||||
return;
|
||||
std::string error;
|
||||
auto document = SettingsDocument::load( plugin->getFileConfigPath(), error );
|
||||
if ( !document ) {
|
||||
Log::warning( "Could not load settings for plugin %s: %s", plugin->getId(), error );
|
||||
return;
|
||||
}
|
||||
const std::string category = "plugins." + plugin->getId();
|
||||
addCategory( panel, category, mApp->i18n( "plugins", "Plugins" ), plugin->getTitle() );
|
||||
SettingsPage page( panel.model, document, category, plugin->getId() );
|
||||
plugin->registerSettings( page );
|
||||
const std::string path = document->path();
|
||||
addAction( panel,
|
||||
{ plugin->getId() + ".edit-json", category,
|
||||
mApp->i18n( "edit_settings_json", "Edit Settings JSON" ),
|
||||
mApp->i18n( "edit_settings_json_desc",
|
||||
"Open the complete plugin configuration file." ) },
|
||||
mApp->i18n( "open_file_ellipsis", "Open File..." ), [this, &panel, path] {
|
||||
auto* window = panel.window;
|
||||
window->runOnMainThread( [this, window, path] {
|
||||
window->closeWindow();
|
||||
mApp->getUISceneNode()->runOnMainThread(
|
||||
[this, path] { mApp->focusOrLoadFile( path ); } );
|
||||
} );
|
||||
} );
|
||||
panel.documents.emplace_back( std::move( document ) );
|
||||
} );
|
||||
}
|
||||
|
||||
void SettingsPanel::addProjectSettings( PanelState& panel ) {
|
||||
addCategory( panel, "editor.document", mApp->i18n( "editor", "Editor" ),
|
||||
mApp->i18n( "document", "Document" ) );
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace ecode {
|
||||
|
||||
class App;
|
||||
class SettingsDocument;
|
||||
|
||||
class SettingsPanel {
|
||||
public:
|
||||
@@ -40,6 +41,7 @@ class SettingsPanel {
|
||||
std::shared_ptr<Model> categoryModel;
|
||||
UIBindingGroup bindingGroup;
|
||||
SettingsModel model;
|
||||
std::vector<std::shared_ptr<SettingsDocument>> documents;
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>> categoryItems;
|
||||
UnorderedMap<std::string, std::string> categoryIds;
|
||||
UnorderedMap<std::string, String> categorySearchText;
|
||||
@@ -61,42 +63,65 @@ class SettingsPanel {
|
||||
PanelState mProject;
|
||||
|
||||
PanelState& state( Scope scope );
|
||||
|
||||
void create( Scope scope );
|
||||
|
||||
void selectCategory( PanelState& state, const std::string& category );
|
||||
|
||||
void addUserSettings( PanelState& state );
|
||||
|
||||
void addPluginSettings( PanelState& state );
|
||||
|
||||
void addProjectSettings( PanelState& state );
|
||||
|
||||
void addCategory( PanelState& state, const std::string& id, const String& parent,
|
||||
const String& name );
|
||||
|
||||
void addSubcategoryHeading( PanelState& state, const std::string& category,
|
||||
const String& name );
|
||||
|
||||
void setupCategories( PanelState& state );
|
||||
|
||||
void addBool( PanelState& state, SettingDescriptor binding, bool* value,
|
||||
std::function<void( bool )> apply = {} );
|
||||
|
||||
void addBool( PanelState& state, SettingDescriptor binding, std::function<bool()> get,
|
||||
std::function<void( bool )> set );
|
||||
|
||||
void addChoice( PanelState& state, SettingDescriptor binding,
|
||||
const std::vector<String>& choices, std::function<size_t()> get,
|
||||
std::function<void( size_t )> set,
|
||||
std::vector<String> choiceDescriptions = {} );
|
||||
|
||||
void addEditableChoice( PanelState& state, SettingDescriptor binding,
|
||||
const std::vector<String>& choices, std::function<String()> get,
|
||||
std::function<bool( const String& )> set );
|
||||
|
||||
void addInteger( PanelState& state, SettingDescriptor binding, int min, int max,
|
||||
std::function<int()> get, std::function<void( int )> set );
|
||||
|
||||
void addText( PanelState& state, SettingDescriptor binding, std::function<std::string()> get,
|
||||
std::function<bool( const std::string& )> set, bool commitOnFocusLoss = false );
|
||||
|
||||
void addFloat( PanelState& state, SettingDescriptor binding, double min, double max,
|
||||
double step, std::function<double()> get, std::function<void( double )> set );
|
||||
|
||||
void addAction( PanelState& state, SettingDescriptor binding, const String& buttonText,
|
||||
std::function<void()> action );
|
||||
|
||||
UIWidget* createRow( PanelState& state, SettingDefinition& setting, SettingView& view,
|
||||
pugi::xml_node layout );
|
||||
|
||||
UICheckBox* createBoolControl( PanelState& state, SettingDefinition& setting,
|
||||
SettingView& view );
|
||||
|
||||
void materializeCategory( PanelState& state, const std::string& category );
|
||||
|
||||
void materializeVisibleSettings( PanelState& state, const String& query );
|
||||
|
||||
void setCategoryEnabled( PanelState& state, const std::string& category, bool enabled,
|
||||
const std::string& excludedSetting = {} );
|
||||
|
||||
void filter( PanelState& state );
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user