cchat-gtk/internal/ui/service/session/server/commander/commander.go

154 lines
3.3 KiB
Go
Raw Normal View History

package commander
import (
"time"
"github.com/diamondburned/cchat"
"github.com/diamondburned/cchat-gtk/internal/gts"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/autoscroll"
2020-07-01 01:09:22 +00:00
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/completion"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/scrollinput"
2020-10-15 06:32:11 +00:00
"github.com/diamondburned/cchat/utils/split"
2020-07-01 01:09:22 +00:00
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
)
2020-07-01 01:09:22 +00:00
var monospace = primitives.PrepareCSS(`
* {
font-family: monospace;
border-radius: 0;
}
`)
type Session struct {
*gtk.Box
2020-07-01 01:09:22 +00:00
cmder cchat.Commander
2020-10-15 06:32:11 +00:00
cmplt *completion.Completer
buffer *Buffer
2020-07-01 01:09:22 +00:00
inputbuf *gtk.TextBuffer
// words []string
// index int
}
func SpawnDialog(buf *Buffer) {
2020-10-15 06:32:11 +00:00
s := NewSession(buf)
s.Show()
h, _ := gtk.HeaderBarNew()
h.SetShowCloseButton(true)
h.Show()
rm := buf.name.OnUpdate(func() {
h.SetTitle("Commander: " + buf.name.Label().Content)
})
h.Connect("destroy", rm)
d, _ := gts.NewEmptyModalDialog()
d.SetDefaultSize(450, 250)
d.SetTitlebar(h)
d.Add(s)
d.Show()
}
2020-10-15 06:32:11 +00:00
func NewSession(buf *Buffer) *Session {
2020-07-01 01:09:22 +00:00
view, _ := gtk.TextViewNewWithBuffer(buf.TextBuffer)
view.SetEditable(false)
view.SetProperty("monospace", true)
view.SetPixelsAboveLines(1)
view.SetWrapMode(gtk.WRAP_WORD_CHAR)
2020-10-15 06:32:11 +00:00
view.SetBorderWidth(8)
2020-07-01 01:09:22 +00:00
view.Show()
scroll := autoscroll.NewScrolledWindow()
scroll.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
scroll.Add(view)
scroll.Show()
input, _ := gtk.TextViewNew()
input.SetSizeRequest(-1, 35) // magic height 35px
2020-10-15 06:32:11 +00:00
input.SetBorderWidth(8)
2020-07-01 01:09:22 +00:00
primitives.AttachCSS(input, monospace)
input.Show()
2020-07-01 01:09:22 +00:00
inputbuf, _ := input.GetBuffer()
inputscroll := scrollinput.NewH(input)
inputscroll.Show()
sep, _ := gtk.SeparatorNew(gtk.ORIENTATION_HORIZONTAL)
sep.Show()
b, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
2020-07-01 01:09:22 +00:00
b.PackStart(scroll, true, true, 0)
b.PackStart(sep, false, false, 0)
b.PackStart(inputscroll, false, false, 0)
2020-10-15 06:32:11 +00:00
completer := completion.NewCompleter(input)
completer.Splitter = split.ArgsIndexed
completer.SetCompleter(buf.cmder.AsCompleter())
session := &Session{
2020-07-01 01:09:22 +00:00
Box: b,
2020-10-15 06:32:11 +00:00
cmder: buf.cmder,
cmplt: completer,
2020-07-01 01:09:22 +00:00
buffer: buf,
inputbuf: inputbuf,
}
2020-07-01 01:09:22 +00:00
input.Connect("key-press-event", session.inputActivate)
input.GrabFocus()
primitives.AddClass(b, "commander")
primitives.AddClass(view, "command-buffer")
primitives.AddClass(input, "command-input")
return session
}
2020-07-01 01:09:22 +00:00
func (s *Session) inputActivate(v *gtk.TextView, ev *gdk.Event) bool {
// If the keypress is not enter, then ignore.
if kev := gdk.EventKeyNewFromEvent(ev); kev.KeyVal() != gdk.KEY_Return {
return false
}
2020-10-15 06:32:11 +00:00
// Get the slice of words.
var words = s.cmplt.Content()
// If the input is empty, then ignore.
2020-10-15 06:32:11 +00:00
if len(words) == 0 {
2020-07-01 01:09:22 +00:00
return true
}
// Clear the entry.
2020-07-01 01:09:22 +00:00
s.inputbuf.Delete(s.inputbuf.GetBounds())
var then = time.Now()
2020-10-15 06:32:11 +00:00
s.buffer.Systemlnf("%s > %q", then.Format(time.Kitchen), words)
go func() {
2020-10-15 06:32:11 +00:00
out, err := s.cmder.Run(words)
gts.ExecAsync(func() {
2020-10-15 06:32:11 +00:00
if out != nil {
s.buffer.WriteOutput(out)
}
if err != nil {
2020-10-15 06:32:11 +00:00
s.buffer.WriteError(err)
}
var now = time.Now()
2020-10-15 06:32:11 +00:00
s.buffer.Systemlnf(
"%s: Finished running command, took %s.",
now.Format(time.Kitchen),
now.Sub(then).String(),
)
})
}()
2020-07-01 01:09:22 +00:00
return true
}