diff --git a/Makefile b/Makefile index 05517a9..10dda7e 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ all: dev: (cd cmd/core-app && task dev) +pre-commit: + coderabbit review --prompt-only + development-docs: @echo "Running development documentation Website..." @(cd pkg/core/docs && mkdocs serve -w src) diff --git a/cmd/core-app/build/darwin/Info.dev.plist b/cmd/core-app/build/darwin/Info.dev.plist index c7d6ce4..6b23ec1 100644 --- a/cmd/core-app/build/darwin/Info.dev.plist +++ b/cmd/core-app/build/darwin/Info.dev.plist @@ -23,10 +23,25 @@ true NSHumanReadableCopyright © EUPL-1.2 Lethean Community + + NSAppTransportSecurity NSAllowsLocalNetworking + NSAllowsArbitraryLoads + + NSAllowsArbitraryLoadsInWebContent + + + + NSDownloadsFolderUsageDescription + This app needs access to your Downloads folder to save and load files. + NSDocumentsFolderUsageDescription + This app needs access to your Documents folder to save and load files. + NSDesktopFolderUsageDescription + This app needs access to your Desktop folder to save and load files. + - \ No newline at end of file + diff --git a/cmd/core/cmd/build.go b/cmd/core/cmd/build.go index eb27f87..3695d37 100644 --- a/cmd/core/cmd/build.go +++ b/cmd/core/cmd/build.go @@ -129,6 +129,12 @@ func updateFileSelect(msg tea.Msg, m model) (tea.Model, tea.Cmd) { m.fileCursor++ } case "enter": + // Guard against empty files or out-of-bounds cursor + if len(m.files) == 0 || m.fileCursor < 0 || m.fileCursor >= len(m.files) { + // If the guard fails, attempt to reload files for the current path + return m, loadFilesCmd(m.currentPath) + } + selectedEntry := m.files[m.fileCursor] fullPath := filepath.Join(m.currentPath, selectedEntry.Name()) if selectedEntry.IsDir() { @@ -136,9 +142,17 @@ func updateFileSelect(msg tea.Msg, m model) (tea.Model, tea.Cmd) { return m, loadFilesCmd(m.currentPath) } else { // User selected a file - m.selectedFile = fullPath - m.view = buildOutputState - return m, buildWailsCmd(m.selectedFile) + ext := strings.ToLower(filepath.Ext(selectedEntry.Name())) + if ext == ".html" || ext == ".htm" { + m.selectedFile = fullPath + m.view = buildOutputState + return m, buildWailsCmd(m.selectedFile) + } else { + // If not an HTML file, show an error and stay in file selection + m.buildLog = fmt.Sprintf("Error: Selected file '%s' is not an HTML file (.html or .htm).", selectedEntry.Name()) + m.view = buildOutputState // Temporarily show error in build output view + return m, nil + } } case "backspace", "h": parentPath := filepath.Dir(m.currentPath) @@ -182,6 +196,9 @@ func (m model) View() string { sb.WriteString(fmt.Sprintf("Select an HTML file for Wails build (Current: %s)\n\n", m.currentPath)) for i, entry := range m.files { cursor := " " + if entry.IsDir() { + cursor = "/" + } if m.fileCursor == i { cursor = ">" } @@ -232,8 +249,16 @@ func buildWailsCmd(htmlPath string) tea.Cmd { return errorMsg(fmt.Errorf("wails3 executable not found in PATH: %w", err)) } - // Assuming the Wails project is in cmd/core-app relative to the core CLI tool - wailsProjectDir := "../core-app" + var wailsProjectDir string + execPath, err := os.Executable() + if err != nil { + // If os.Executable fails, return an error as we cannot reliably locate the Wails project. + return errorMsg(fmt.Errorf("failed to determine executable path: %w. Cannot reliably locate Wails project directory.", err)) + } else { + execDir := filepath.Dir(execPath) + // Join execDir with "../core-app" and clean the path + wailsProjectDir = filepath.Clean(filepath.Join(execDir, "../core-app")) + } // Get the directory and base name of the selected HTML file assetDir := filepath.Dir(htmlPath) diff --git a/cmd/core/cmd/root.go b/cmd/core/cmd/root.go index c638e29..cd827f9 100644 --- a/cmd/core/cmd/root.go +++ b/cmd/core/cmd/root.go @@ -38,7 +38,7 @@ var ( Foreground(lipgloss.Color("#3b82f6")). // Tailwind blue-500 Underline(true) - taglineStyle = lipgloss.NewStyle(). + taglineStyle = lipgloss.NewNewStyle(). Foreground(lipgloss.Color("#e2e8f0")). PaddingTop(2).PaddingLeft(8).PaddingBottom(1). // vertical spacing around the tagline Align(lipgloss.Center) // centre it under the big words @@ -55,6 +55,9 @@ var rootCmd = &cobra.Command{ "managing various aspects of Core.Framework applications."), Run: func(cmd *cobra.Command, args []string) { // Default behaviour if no subcommand is given + if !cmd.HasSubCommands() && len(args) == 0 { + showBanner() + } err := cmd.Help() if err != nil { return @@ -70,11 +73,14 @@ func Execute() { } func init() { - // Here you can define global flags and configuration that apply to all commands. + // Here you can define global flags and command setup. if os.Getenv("CORE_DEV_TOOLS") == "true" { initDevTools() } +} +// showBanner generates and prints the ASCII art banner. +func showBanner() { coreFig := figure.NewFigure("Core", "big", true) frameworkFig := figure.NewFigure("Framework", "big", true) @@ -121,11 +127,8 @@ func initDevTools() { } return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true) } - // go-prompt will block, so we run it in a goroutine for this example - // In a real app, you'd likely manage its lifecycle more carefully. - // The prompt.New function returns a Prompt object, which then has a Run method. - // For a simple blocking run, you can call .Run() directly on the New object. - go prompt.New(executor, completer, prompt.OptionPrefix(">>> ")).Run() + // go-prompt will now run synchronously for the demo. + prompt.New(executor, completer, prompt.OptionPrefix(">>> ")).Run() // Example usage for lipgloss // Using the global descriptionStyle for consistency diff --git a/cmd/core/cmd/tview.go b/cmd/core/cmd/tview.go index 08ad04f..306b88c 100644 --- a/cmd/core/cmd/tview.go +++ b/cmd/core/cmd/tview.go @@ -17,7 +17,7 @@ var tviewCmd = &cobra.Command{ Short: "Runs a tview example to demonstrate its capabilities", Long: `This command launches a simple tview application to showcase its full-screen terminal UI features.`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Starting tview example...") + // Removed: fmt.Println("Starting tview example...") to prevent visual artifacts app := tview.NewApplication() box := tview.NewBox(). SetBorder(true).