158 lines
2.9 KiB
Go
Raw Normal View History

2023-08-17 23:10:09 +00:00
package editor
import (
2023-08-18 11:17:46 +00:00
"os"
2023-08-18 15:01:42 +00:00
"git.akyoto.dev/cli/dash/core"
2023-08-17 23:10:09 +00:00
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
2023-08-18 15:01:42 +00:00
type Editor struct {
Pages *tview.Pages
Source *tview.TextArea
Result *tview.TextView
FilePath string
IsDirty bool
}
2023-08-18 11:17:46 +00:00
2023-08-18 15:01:42 +00:00
func New(app *tview.Application, filePath string) *Editor {
e := &Editor{
FilePath: filePath,
2023-08-18 11:17:46 +00:00
}
2023-08-18 15:01:42 +00:00
e.Pages = tview.NewPages()
e.Pages.SetBackgroundColor(tcell.ColorDefault)
2023-08-18 11:17:46 +00:00
2023-08-18 15:01:42 +00:00
source := e.newSourceEditor()
result := e.newResult()
e.Pages.AddPage("Source", source, true, false)
e.Pages.AddPage("Result", result, true, true)
return e
}
func (e *Editor) toggle() {
front, _ := e.Pages.GetFrontPage()
switch front {
case "Source":
e.Pages.SwitchToPage("Result")
case "Result":
e.Pages.SwitchToPage("Source")
2023-08-18 11:17:46 +00:00
}
2023-08-18 15:01:42 +00:00
}
2023-08-18 11:17:46 +00:00
2023-08-18 15:01:42 +00:00
func (e *Editor) newSourceEditor() *tview.TextArea {
e.Source = tview.NewTextArea()
e.Source.SetBackgroundColor(tcell.ColorDefault)
e.Source.SetTextStyle(tcell.StyleDefault)
e.Source.SetBorderPadding(0, 0, 1, 1)
e.load()
2023-08-18 11:17:46 +00:00
2023-08-18 15:01:42 +00:00
e.Source.SetChangedFunc(func() {
e.setDirty(true)
2023-08-18 11:17:46 +00:00
})
2023-08-18 15:01:42 +00:00
e.Source.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyESC {
e.updateResult()
e.toggle()
return nil
}
2023-08-18 11:17:46 +00:00
if event.Key() == tcell.KeyCtrlS {
2023-08-18 15:01:42 +00:00
e.save()
e.updateResult()
e.toggle()
return nil
}
return event
})
return e.Source
}
func (e *Editor) newResult() *tview.TextView {
e.Result = tview.NewTextView()
e.Result.SetBackgroundColor(tcell.ColorDefault)
e.Result.SetTextStyle(tcell.StyleDefault)
e.Result.SetBorderPadding(0, 0, 1, 1)
2023-08-18 15:26:50 +00:00
e.Result.SetDynamicColors(true)
2023-08-18 15:01:42 +00:00
e.Result.SetMouseCapture(func(action tview.MouseAction, event *tcell.EventMouse) (tview.MouseAction, *tcell.EventMouse) {
if action == tview.MouseLeftClick {
e.toggle()
}
return action, event
})
2023-08-18 11:17:46 +00:00
2023-08-18 15:01:42 +00:00
e.Result.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyEnter:
e.toggle()
return nil
case tcell.KeyRune:
if event.Rune() == 'i' {
e.toggle()
return nil
2023-08-18 11:17:46 +00:00
}
2023-08-18 15:01:42 +00:00
case tcell.KeyCtrlS:
e.save()
2023-08-18 11:17:46 +00:00
return nil
}
return event
})
2023-08-18 15:01:42 +00:00
e.updateResult()
return e.Result
}
func (e *Editor) updateResult() {
source := e.Source.GetText()
result := core.Process(source)
e.Result.SetText(result)
2023-08-17 23:10:09 +00:00
}
2023-08-18 11:17:46 +00:00
2023-08-18 15:01:42 +00:00
func (e *Editor) setDirty(dirty bool) {
e.IsDirty = dirty
2023-08-18 11:17:46 +00:00
if dirty {
2023-08-18 15:01:42 +00:00
e.Source.SetBackgroundColor(tcell.ColorRed)
2023-08-18 11:17:46 +00:00
} else {
2023-08-18 15:01:42 +00:00
e.Source.SetBackgroundColor(tcell.ColorDefault)
}
}
func (e *Editor) load() {
2023-08-18 15:26:50 +00:00
source := "Press [lime]Enter[-] to edit.\nPress [lime]Esc[-] to preview.\nPress [lime]Ctrl S[-] to save.\n\n{whoami}@{hostname}"
2023-08-18 15:01:42 +00:00
data, err := os.ReadFile(e.FilePath)
if err == nil {
source = string(data)
}
e.Source.SetText(source, true)
}
func (e *Editor) save() {
if !e.IsDirty {
return
2023-08-18 11:17:46 +00:00
}
2023-08-18 15:01:42 +00:00
source := e.Source.GetText()
err := os.WriteFile(e.FilePath, []byte(source), 0600)
if err != nil {
panic(err)
}
e.setDirty(false)
2023-08-18 11:17:46 +00:00
}