From c21af8508e3519121a17ac345eaf04cb0825e5a6 Mon Sep 17 00:00:00 2001 From: SpookyDervish <78246495+SpookyDervish@users.noreply.github.com> Date: Wed, 29 Oct 2025 21:06:34 +1100 Subject: [PATCH] starting work on actually saving settings --- assets/style.tcss | 2 +- assets/theme_mappings.py | 1 - main.py | 22 +++++++++++------- plugin_loader.py | 6 ++--- plugins/test-plugin/lua/main.lua | 3 --- plugins/test-plugin/plugin.json | 6 ----- settings.py | 21 +++++++++++------ settings_store.py | 40 ++++++++++++++++++++++++++++++++ 8 files changed, 72 insertions(+), 29 deletions(-) delete mode 100644 plugins/test-plugin/lua/main.lua delete mode 100644 plugins/test-plugin/plugin.json create mode 100644 settings_store.py diff --git a/assets/style.tcss b/assets/style.tcss index 5bf3f16..bd33fac 100644 --- a/assets/style.tcss +++ b/assets/style.tcss @@ -18,7 +18,7 @@ } } -ContentSwitcher Vertical { +#sidebar-switcher Vertical { padding: 1; Static { margin-bottom: 1; diff --git a/assets/theme_mappings.py b/assets/theme_mappings.py index 81f1d34..e5849d4 100644 --- a/assets/theme_mappings.py +++ b/assets/theme_mappings.py @@ -14,5 +14,4 @@ theme_mappings = { "yaml": "yaml", "md": "markdown", "gitignore": "markdown", - "lua": "lua" } \ No newline at end of file diff --git a/main.py b/main.py index 0c53e3a..6cf4397 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -from textual.app import App, ComposeResult +from textual.app import App, ComposeResult, SystemCommand from textual.widgets import Header, Footer, ContentSwitcher, DirectoryTree, Static, Button, TextArea, Tabs, Tab, RichLog, Input from textual.containers import HorizontalGroup, Vertical from textual.binding import Binding @@ -36,7 +36,8 @@ class Berry(App): Binding("ctrl+n", "new", "New File"), Binding("ctrl+s", "save", "Save"), Binding("ctrl+shift+s", "save_as", "Save As...", priority=True), - Binding("ctrl+f", "find", "Find", priority=True) + Binding("ctrl+f", "find", "Find", priority=True), + Binding("ctrl+f1", "settings", "Settings") ] def __init__(self, path: str): @@ -50,7 +51,7 @@ class Berry(App): yield Button("📂") yield Button("🔍") - with ContentSwitcher(initial="files"): + with ContentSwitcher(initial="files", id="sidebar-switcher"): with Vertical(id="files"): yield Static("EXPLORER") yield DirectoryTree(self.path, id="directory") @@ -63,7 +64,7 @@ class Berry(App): first_tab, id="file-tabs" ) - yield TextArea.code_editor(placeholder="This file is empty.", theme="css", id="code-editor", disabled=True) + yield TextArea.code_editor(placeholder="This file is empty.", theme="css", id="code-editor", disabled=True, soft_wrap=True) #if os.name == "nt": with Vertical(id="console-container"): @@ -75,6 +76,13 @@ class Berry(App): yield Footer() yield PluginLoader() + def action_settings(self): + self.push_screen(SettingsScreen()) + + def get_system_commands(self, screen): + yield from super().get_system_commands(screen) + yield SystemCommand("Settings", "Open the settings menu", self.action_settings) + def on_input_submitted(self, event: Input.Submitted): if event.input.id != "console-input": return @@ -301,8 +309,8 @@ class Berry(App): def done_saving(self, result): if result is None: return - with open(result, "wb") as f: - f.write(self.query_one("#code-editor").text.encode()) + with open(result, "w", encoding="utf-8") as f: + f.write(self.query_one("#code-editor").text) tabs: Tabs = self.query_one("#file-tabs") tabs.active_tab.label = os.path.basename(result) @@ -350,8 +358,6 @@ class Berry(App): #else: # self.query_one("#terminal").start() - self.push_screen(SettingsScreen()) - if __name__ == "__main__": app = Berry("./") app.run() \ No newline at end of file diff --git a/plugin_loader.py b/plugin_loader.py index 4054498..9b4eba3 100644 --- a/plugin_loader.py +++ b/plugin_loader.py @@ -51,8 +51,8 @@ class PluginLoader(Window): def create_widget(self, widget_type: str, *args): return getattr(textual.widgets, widget_type)(*args) - def run_on_event(self, event, function): - raise NotImplementedError("runOnEvent is not implemented yet.") + def run_on_message(self, event, function): + raise NotImplementedError("onMessage is not implemented yet.") def create_window(self, title: str, icon: str = "", show_title: bool = True, can_close: bool = True, can_maximize: bool = True, can_resize: bool = True, start_horizontal: str = "center", start_vertical: str = "middle"): new_window = Window( @@ -91,7 +91,7 @@ class PluginLoader(Window): "createWindow": self.create_window, "createWidget": self.create_widget, "app": self.app, - "runOnEvent": self.run_on_event + "onMessage": self.run_on_message }, } diff --git a/plugins/test-plugin/lua/main.lua b/plugins/test-plugin/lua/main.lua deleted file mode 100644 index 553c6e0..0000000 --- a/plugins/test-plugin/lua/main.lua +++ /dev/null @@ -1,3 +0,0 @@ -local plugin = {} - -return plugin \ No newline at end of file diff --git a/plugins/test-plugin/plugin.json b/plugins/test-plugin/plugin.json deleted file mode 100644 index 1b3fc6e..0000000 --- a/plugins/test-plugin/plugin.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": "0.0.1", - "name": "Test Plugin", - "author": "SpookyDervish", - "dependencies": [] -} \ No newline at end of file diff --git a/settings.py b/settings.py index 46daf9b..9a87610 100644 --- a/settings.py +++ b/settings.py @@ -1,5 +1,5 @@ from textual.screen import ModalScreen -from textual.widgets import Label, Select, TabbedContent, TabPane, Checkbox +from textual.widgets import Label, Select, TabbedContent, TabPane, Switch from textual.containers import Vertical, HorizontalGroup, VerticalGroup from textual.binding import Binding @@ -24,23 +24,25 @@ class SettingsScreen(ModalScreen): .setting { padding: 0 2; - background: red; + content-align: center middle; + .setting-name { text-style: bold; } + .setting-desc { text-style: dim; width: 100%; min-width: 30; } + VerticalGroup { width: 50%; min-width: 20; } Select { - width: 25; - padding: 0; + max-width: 30; } } } @@ -62,11 +64,16 @@ class SettingsScreen(ModalScreen): with VerticalGroup(): yield Label("Colour Theme", classes="setting-name") yield Label("Colour theme used for the entire Berry app.", classes="setting-desc") - yield Select.from_values(["theme 1", "theme 2", "theme 3"], allow_blank=False) + yield Select.from_values((theme_name for theme_name in self.app._registered_themes.keys() if theme_name != "textual-ansi"), allow_blank=False) with TabPane("Editor"): with HorizontalGroup(classes="setting"): with VerticalGroup(): yield Label("Word Wrap", classes="setting-name") yield Label("Enable word wrap in the code editor.", classes="setting-desc") - yield Checkbox(value=True) - yield TabPane("Plugins") + yield Switch(value=True) + with TabPane("Plugins"): + with HorizontalGroup(classes="setting"): + with VerticalGroup(): + yield Label("Plugins Enabled", classes="setting-name") + yield Label("Enable or disable Lua plugins. This requires a restart.", classes="setting-desc") + yield Switch(value=True) diff --git a/settings_store.py b/settings_store.py new file mode 100644 index 0000000..73067b1 --- /dev/null +++ b/settings_store.py @@ -0,0 +1,40 @@ +from pathlib import Path +import os, subprocess +import configparser + + +class ConfigHandler: + def __init__(self): + self.config = configparser.ConfigParser() + + self.config_dir = self.ensure_hidden_config_dir() + self.load_settings(self.config_dir) + + def ensure_hidden_config_dir(self): + config_dir = Path.home() / ".berry" + config_dir.mkdir(parents=True, exist_ok=True) + + # If Windows, apply hidden attribute + if os.name == "nt": + subprocess.run(["attrib", "+h", str(config_dir)], shell=True) + + return config_dir + + def load_settings(self): + if os.path.isfile(self.config_dir / "config.ini"): + with open(self.config_dir / "config.ini", "r") as configfile: + self.config.read(configfile) + return + + self.config["editor"] = { + "word_wrap": True + } + self.config["plugins"] = { + "enabled": True + } + self.config["appearance"] = { + "colour_theme": "textual-dark" + } + + with open(self.config_dir / "config.ini") as configfile: + self.config.write(configfile) \ No newline at end of file