133 lines
3.2 KiB
Go
133 lines
3.2 KiB
Go
package main
|
||
|
||
import (
|
||
"flag"
|
||
"fmt"
|
||
"os"
|
||
|
||
tea "github.com/charmbracelet/bubbletea"
|
||
)
|
||
|
||
func main() {
|
||
var filePath string
|
||
var configPath string
|
||
var writeConfig bool
|
||
|
||
flag.StringVar(&filePath, "f", "", "File to edit")
|
||
flag.StringVar(&configPath, "config", "", "Path to config file (overrides auto-search)")
|
||
flag.BoolVar(&writeConfig, "write-config", false, "Write default config to standard location and exit")
|
||
flag.Parse()
|
||
|
||
// Позиционный аргумент: grimoir file.txt или grimoir https://...
|
||
if filePath == "" && flag.NArg() > 0 {
|
||
filePath = flag.Arg(0)
|
||
}
|
||
|
||
// Загружаем конфиг
|
||
var cfg Config
|
||
if configPath != "" {
|
||
data, err := os.ReadFile(configPath)
|
||
if err != nil {
|
||
fmt.Fprintf(os.Stderr, "Error reading config %s: %v\n", configPath, err)
|
||
os.Exit(1)
|
||
}
|
||
cfg = DefaultConfig()
|
||
if err := parseConfig(data, &cfg); err != nil {
|
||
fmt.Fprintf(os.Stderr, "Error parsing config %s: %v\n", configPath, err)
|
||
os.Exit(1)
|
||
}
|
||
cfg.LoadedFrom = configPath
|
||
} else {
|
||
cfg = LoadConfig()
|
||
}
|
||
|
||
// --write-config
|
||
if writeConfig {
|
||
paths := ConfigPaths()
|
||
target := ""
|
||
for _, p := range paths {
|
||
if p != paths[0] {
|
||
target = p
|
||
break
|
||
}
|
||
}
|
||
if target == "" {
|
||
target = "grimoir.conf"
|
||
}
|
||
if err := WriteDefaultConfig(target); err != nil {
|
||
fmt.Fprintf(os.Stderr, "Error writing config: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
fmt.Printf("Default config written to: %s\n", target)
|
||
os.Exit(0)
|
||
}
|
||
|
||
// === Если файл не передан — показываем стартовое меню ===
|
||
if filePath == "" {
|
||
result := RunMenu()
|
||
if result == nil {
|
||
// Пользователь закрыл меню без выбора
|
||
os.Exit(0)
|
||
}
|
||
|
||
switch result.Action {
|
||
case menuQuit:
|
||
os.Exit(0)
|
||
|
||
case menuHelp:
|
||
// Открываем редактор с пустым файлом и сразу показываем help
|
||
runEditor("untitled.md", cfg, true)
|
||
return
|
||
|
||
case menuNewFile:
|
||
filePath = "untitled.md"
|
||
|
||
case menuOpenFile:
|
||
filePath = result.FilePath
|
||
|
||
case menuFetchURL:
|
||
filePath = result.URL
|
||
}
|
||
}
|
||
|
||
// === URL — скачиваем и конвертируем ===
|
||
if IsURL(filePath) {
|
||
fmt.Fprintf(os.Stderr, "Fetching: %s\n", filePath)
|
||
result, err := FetchAndConvert(filePath)
|
||
if err != nil {
|
||
fmt.Fprintf(os.Stderr, "Error fetching URL: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
savedPath, err := SaveFetchResult(result, "")
|
||
if err != nil {
|
||
fmt.Fprintf(os.Stderr, "Error saving file: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
fmt.Fprintf(os.Stderr, "Saved as: %s\n", savedPath)
|
||
filePath = savedPath
|
||
}
|
||
|
||
runEditor(filePath, cfg, false)
|
||
}
|
||
|
||
// runEditor загружает файл и запускает редактор.
|
||
// showHelp=true открывает справку сразу при старте.
|
||
func runEditor(filePath string, cfg Config, showHelp bool) {
|
||
content, err := LoadFile(filePath)
|
||
if err != nil && !os.IsNotExist(err) {
|
||
fmt.Fprintf(os.Stderr, "Error loading file: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
fileType := DetectFileType(filePath)
|
||
model := NewEditor(filePath, fileType, content, cfg)
|
||
if showHelp {
|
||
model.showHelp = true
|
||
}
|
||
|
||
p := tea.NewProgram(model, tea.WithAltScreen())
|
||
if _, err := p.Run(); err != nil {
|
||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
}
|