157 lines
2.8 KiB
Go
157 lines
2.8 KiB
Go
package editor
|
|
|
|
import (
|
|
"os"
|
|
|
|
"git.akyoto.dev/cli/dash/core"
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/rivo/tview"
|
|
)
|
|
|
|
type Editor struct {
|
|
Pages *tview.Pages
|
|
Source *tview.TextArea
|
|
Result *tview.TextView
|
|
FilePath string
|
|
IsDirty bool
|
|
}
|
|
|
|
func New(app *tview.Application, filePath string) *Editor {
|
|
e := &Editor{
|
|
FilePath: filePath,
|
|
}
|
|
|
|
e.Pages = tview.NewPages()
|
|
e.Pages.SetBackgroundColor(tcell.ColorDefault)
|
|
|
|
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")
|
|
}
|
|
}
|
|
|
|
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()
|
|
|
|
e.Source.SetChangedFunc(func() {
|
|
e.setDirty(true)
|
|
})
|
|
|
|
e.Source.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
|
if event.Key() == tcell.KeyESC {
|
|
e.updateResult()
|
|
e.toggle()
|
|
return nil
|
|
}
|
|
|
|
if event.Key() == tcell.KeyCtrlS {
|
|
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)
|
|
|
|
e.Result.SetMouseCapture(func(action tview.MouseAction, event *tcell.EventMouse) (tview.MouseAction, *tcell.EventMouse) {
|
|
if action == tview.MouseLeftClick {
|
|
e.toggle()
|
|
}
|
|
|
|
return action, event
|
|
})
|
|
|
|
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
|
|
}
|
|
|
|
case tcell.KeyCtrlS:
|
|
e.save()
|
|
return nil
|
|
}
|
|
|
|
return event
|
|
})
|
|
|
|
e.updateResult()
|
|
return e.Result
|
|
}
|
|
|
|
func (e *Editor) updateResult() {
|
|
source := e.Source.GetText()
|
|
result := core.Process(source)
|
|
e.Result.SetText(result)
|
|
}
|
|
|
|
func (e *Editor) setDirty(dirty bool) {
|
|
e.IsDirty = dirty
|
|
|
|
if dirty {
|
|
e.Source.SetBackgroundColor(tcell.ColorRed)
|
|
} else {
|
|
e.Source.SetBackgroundColor(tcell.ColorDefault)
|
|
}
|
|
}
|
|
|
|
func (e *Editor) load() {
|
|
source := "Press Enter to edit.\nPress Esc to preview.\nPress Ctrl + S to save.\n\n{whoami}@{hostname}"
|
|
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
|
|
}
|
|
|
|
source := e.Source.GetText()
|
|
err := os.WriteFile(e.FilePath, []byte(source), 0600)
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
e.setDirty(false)
|
|
}
|