mirror of
https://github.com/Hopiu/micro.git
synced 2026-03-20 07:50:25 +00:00
Terminal plugin callback support
This commit is contained in:
parent
199d65017f
commit
b68461cf72
10 changed files with 115 additions and 11 deletions
|
|
@ -85,6 +85,8 @@ func luaImportMicroShell() *lua.LTable {
|
||||||
ulua.L.SetField(pkg, "JobSpawn", luar.New(ulua.L, shell.JobSpawn))
|
ulua.L.SetField(pkg, "JobSpawn", luar.New(ulua.L, shell.JobSpawn))
|
||||||
ulua.L.SetField(pkg, "JobStop", luar.New(ulua.L, shell.JobStop))
|
ulua.L.SetField(pkg, "JobStop", luar.New(ulua.L, shell.JobStop))
|
||||||
ulua.L.SetField(pkg, "JobSend", luar.New(ulua.L, shell.JobSend))
|
ulua.L.SetField(pkg, "JobSend", luar.New(ulua.L, shell.JobSend))
|
||||||
|
ulua.L.SetField(pkg, "RunTermEmulator", luar.New(ulua.L, action.RunTermEmulator))
|
||||||
|
ulua.L.SetField(pkg, "TermEmuSupported", luar.New(ulua.L, action.TermEmuSupported))
|
||||||
|
|
||||||
return pkg
|
return pkg
|
||||||
}
|
}
|
||||||
|
|
@ -106,6 +108,9 @@ func luaImportMicroBuffer() *lua.LTable {
|
||||||
ulua.L.SetField(pkg, "BTScratch", luar.New(ulua.L, buffer.BTScratch.Kind))
|
ulua.L.SetField(pkg, "BTScratch", luar.New(ulua.L, buffer.BTScratch.Kind))
|
||||||
ulua.L.SetField(pkg, "BTRaw", luar.New(ulua.L, buffer.BTRaw.Kind))
|
ulua.L.SetField(pkg, "BTRaw", luar.New(ulua.L, buffer.BTRaw.Kind))
|
||||||
ulua.L.SetField(pkg, "BTInfo", luar.New(ulua.L, buffer.BTInfo.Kind))
|
ulua.L.SetField(pkg, "BTInfo", luar.New(ulua.L, buffer.BTInfo.Kind))
|
||||||
|
ulua.L.SetField(pkg, "NewBufferFromFile", luar.New(ulua.L, func(path string) (*buffer.Buffer, error) {
|
||||||
|
return buffer.NewBufferFromFile(path, buffer.BTDefault)
|
||||||
|
}))
|
||||||
|
|
||||||
return pkg
|
return pkg
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,7 @@ func main() {
|
||||||
for _, b := range buffer.OpenBuffers {
|
for _, b := range buffer.OpenBuffers {
|
||||||
b.Save()
|
b.Save()
|
||||||
}
|
}
|
||||||
|
case <-shell.CloseTerms:
|
||||||
case event = <-events:
|
case event = <-events:
|
||||||
case <-screen.DrawChan:
|
case <-screen.DrawChan:
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,14 @@ func init() {
|
||||||
|
|
||||||
func LuaAction(fn string) func(*BufPane) bool {
|
func LuaAction(fn string) func(*BufPane) bool {
|
||||||
luaFn := strings.Split(fn, ".")
|
luaFn := strings.Split(fn, ".")
|
||||||
|
if len(luaFn) <= 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
plName, plFn := luaFn[0], luaFn[1]
|
plName, plFn := luaFn[0], luaFn[1]
|
||||||
pl := config.FindPlugin(plName)
|
pl := config.FindPlugin(plName)
|
||||||
|
if pl == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return func(h *BufPane) bool {
|
return func(h *BufPane) bool {
|
||||||
val, err := pl.Call(plFn, luar.New(ulua.L, h))
|
val, err := pl.Call(plFn, luar.New(ulua.L, h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,14 @@ func LuaMakeCommand(name, function string, completer buffer.Completer) {
|
||||||
// so that a command can be bound to a lua function
|
// so that a command can be bound to a lua function
|
||||||
func LuaFunctionCommand(fn string) func(*BufPane, []string) {
|
func LuaFunctionCommand(fn string) func(*BufPane, []string) {
|
||||||
luaFn := strings.Split(fn, ".")
|
luaFn := strings.Split(fn, ".")
|
||||||
|
if len(luaFn) <= 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
plName, plFn := luaFn[0], luaFn[1]
|
plName, plFn := luaFn[0], luaFn[1]
|
||||||
pl := config.FindPlugin(plName)
|
pl := config.FindPlugin(plName)
|
||||||
|
if pl == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return func(bp *BufPane, args []string) {
|
return func(bp *BufPane, args []string) {
|
||||||
var luaArgs []lua.LValue
|
var luaArgs []lua.LValue
|
||||||
luaArgs = append(luaArgs, luar.New(ulua.L, bp))
|
luaArgs = append(luaArgs, luar.New(ulua.L, bp))
|
||||||
|
|
@ -872,9 +878,8 @@ func (h *BufPane) TermCmd(args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
term := func(i int, newtab bool) {
|
term := func(i int, newtab bool) {
|
||||||
|
|
||||||
t := new(shell.Terminal)
|
t := new(shell.Terminal)
|
||||||
t.Start(args, false, true)
|
t.Start(args, false, true, "", nil)
|
||||||
|
|
||||||
id := h.ID()
|
id := h.ID()
|
||||||
if newtab {
|
if newtab {
|
||||||
|
|
|
||||||
30
internal/action/terminal_supported.go
Normal file
30
internal/action/terminal_supported.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// +build linux darwin dragonfly openbsd_amd64 freebsd
|
||||||
|
|
||||||
|
package action
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/zyedidia/micro/internal/shell"
|
||||||
|
"github.com/zyedidia/micro/pkg/shellwords"
|
||||||
|
)
|
||||||
|
|
||||||
|
const TermEmuSupported = true
|
||||||
|
|
||||||
|
func RunTermEmulator(h *BufPane, input string, wait bool, getOutput bool, callback string, userargs []interface{}) error {
|
||||||
|
args, err := shellwords.Split(input)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t := new(shell.Terminal)
|
||||||
|
t.Start(args, getOutput, wait, callback, userargs)
|
||||||
|
|
||||||
|
id := h.ID()
|
||||||
|
h.AddTab()
|
||||||
|
id = MainTab().Panes[0].ID()
|
||||||
|
|
||||||
|
v := h.GetView()
|
||||||
|
MainTab().Panes[0] = NewTermPane(v.X, v.Y, v.Width, v.Height, t, id)
|
||||||
|
MainTab().SetActive(0)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
11
internal/action/terminal_unsupported.go
Normal file
11
internal/action/terminal_unsupported.go
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// +build !linux,!darwin,!freebsd,!dragonfly,!openbsd_amd64
|
||||||
|
|
||||||
|
package action
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
const TermEmuSupported = false
|
||||||
|
|
||||||
|
func RunTermEmulator(input string, wait bool, getOutput bool, callback string, userargs []interface{}) error {
|
||||||
|
return errors.New("Unsupported operating system")
|
||||||
|
}
|
||||||
|
|
@ -80,9 +80,9 @@ func (t *TermPane) HandleEvent(event tcell.Event) {
|
||||||
} else if t.Status != shell.TTDone {
|
} else if t.Status != shell.TTDone {
|
||||||
t.WriteString(event.EscSeq())
|
t.WriteString(event.EscSeq())
|
||||||
}
|
}
|
||||||
} else if e, ok := event.(*tcell.EventMouse); !ok || t.State.Mode(terminal.ModeMouseMask) {
|
} else if e, ok := event.(*tcell.EventMouse); e != nil && (!ok || t.State.Mode(terminal.ModeMouseMask)) {
|
||||||
t.WriteString(event.EscSeq())
|
t.WriteString(event.EscSeq())
|
||||||
} else {
|
} else if e != nil {
|
||||||
x, y := e.Position()
|
x, y := e.Position()
|
||||||
v := t.GetView()
|
v := t.GetView()
|
||||||
x -= v.X
|
x -= v.X
|
||||||
|
|
@ -109,6 +109,10 @@ func (t *TermPane) HandleEvent(event tcell.Event) {
|
||||||
t.mouseReleased = true
|
t.mouseReleased = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.Status == shell.TTClose {
|
||||||
|
t.Quit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TermPane) HandleCommand(input string) {
|
func (t *TermPane) HandleCommand(input string) {
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,14 @@ var statusInfo = map[string]func(*buffer.Buffer) string{
|
||||||
|
|
||||||
func SetStatusInfoFnLua(s string, fn string) {
|
func SetStatusInfoFnLua(s string, fn string) {
|
||||||
luaFn := strings.Split(fn, ".")
|
luaFn := strings.Split(fn, ".")
|
||||||
|
if len(luaFn) <= 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
plName, plFn := luaFn[0], luaFn[1]
|
plName, plFn := luaFn[0], luaFn[1]
|
||||||
pl := config.FindPlugin(plName)
|
pl := config.FindPlugin(plName)
|
||||||
|
if pl == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
statusInfo[s] = func(b *buffer.Buffer) string {
|
statusInfo[s] = func(b *buffer.Buffer) string {
|
||||||
if pl == nil || !pl.IsEnabled() {
|
if pl == nil || !pl.IsEnabled() {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,14 @@ func JobSend(cmd *exec.Cmd, data string) {
|
||||||
// to the lua function
|
// to the lua function
|
||||||
func luaFunctionJob(fn string) func(string, ...interface{}) {
|
func luaFunctionJob(fn string) func(string, ...interface{}) {
|
||||||
luaFn := strings.Split(fn, ".")
|
luaFn := strings.Split(fn, ".")
|
||||||
|
if len(luaFn) <= 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
plName, plFn := luaFn[0], luaFn[1]
|
plName, plFn := luaFn[0], luaFn[1]
|
||||||
pl := config.FindPlugin(plName)
|
pl := config.FindPlugin(plName)
|
||||||
|
if pl == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return func(output string, args ...interface{}) {
|
return func(output string, args ...interface{}) {
|
||||||
var luaArgs []lua.LValue
|
var luaArgs []lua.LValue
|
||||||
luaArgs = append(luaArgs, luar.New(ulua.L, output))
|
luaArgs = append(luaArgs, luar.New(ulua.L, output))
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,19 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
lua "github.com/yuin/gopher-lua"
|
||||||
"github.com/zyedidia/micro/internal/buffer"
|
"github.com/zyedidia/micro/internal/buffer"
|
||||||
|
"github.com/zyedidia/micro/internal/config"
|
||||||
|
ulua "github.com/zyedidia/micro/internal/lua"
|
||||||
"github.com/zyedidia/micro/internal/screen"
|
"github.com/zyedidia/micro/internal/screen"
|
||||||
"github.com/zyedidia/terminal"
|
"github.com/zyedidia/terminal"
|
||||||
|
luar "layeh.com/gopher-luar"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TermType int
|
type TermType int
|
||||||
|
type CallbackFunc func(string)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TTClose = iota // Should be closed
|
TTClose = iota // Should be closed
|
||||||
|
|
@ -20,6 +26,12 @@ const (
|
||||||
TTDone // Finished running a command
|
TTDone // Finished running a command
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var CloseTerms chan bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
CloseTerms = make(chan bool)
|
||||||
|
}
|
||||||
|
|
||||||
// A Terminal holds information for the terminal emulator
|
// A Terminal holds information for the terminal emulator
|
||||||
type Terminal struct {
|
type Terminal struct {
|
||||||
State terminal.State
|
State terminal.State
|
||||||
|
|
@ -30,7 +42,7 @@ type Terminal struct {
|
||||||
wait bool
|
wait bool
|
||||||
getOutput bool
|
getOutput bool
|
||||||
output *bytes.Buffer
|
output *bytes.Buffer
|
||||||
callback string
|
callback CallbackFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasSelection returns whether this terminal has a valid selection
|
// HasSelection returns whether this terminal has a valid selection
|
||||||
|
|
@ -64,7 +76,7 @@ func (t *Terminal) GetSelection(width int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start begins a new command in this terminal with a given view
|
// Start begins a new command in this terminal with a given view
|
||||||
func (t *Terminal) Start(execCmd []string, getOutput bool, wait bool) error {
|
func (t *Terminal) Start(execCmd []string, getOutput bool, wait bool, callback string, userargs []interface{}) error {
|
||||||
if len(execCmd) <= 0 {
|
if len(execCmd) <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -84,6 +96,25 @@ func (t *Terminal) Start(execCmd []string, getOutput bool, wait bool) error {
|
||||||
t.title = execCmd[0] + ":" + strconv.Itoa(cmd.Process.Pid)
|
t.title = execCmd[0] + ":" + strconv.Itoa(cmd.Process.Pid)
|
||||||
t.wait = wait
|
t.wait = wait
|
||||||
|
|
||||||
|
luaFn := strings.Split(callback, ".")
|
||||||
|
if len(luaFn) >= 2 {
|
||||||
|
plName, plFn := luaFn[0], luaFn[1]
|
||||||
|
pl := config.FindPlugin(plName)
|
||||||
|
if pl != nil {
|
||||||
|
t.callback = func(out string) {
|
||||||
|
var luaArgs []lua.LValue
|
||||||
|
luaArgs = append(luaArgs, luar.New(ulua.L, out))
|
||||||
|
for _, v := range userargs {
|
||||||
|
luaArgs = append(luaArgs, luar.New(ulua.L, v))
|
||||||
|
}
|
||||||
|
_, err := pl.Call(plFn, luaArgs...)
|
||||||
|
if err != nil {
|
||||||
|
screen.TermMessage(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
err := Term.Parse()
|
err := Term.Parse()
|
||||||
|
|
@ -108,6 +139,7 @@ func (t *Terminal) Stop() {
|
||||||
t.Status = TTDone
|
t.Status = TTDone
|
||||||
} else {
|
} else {
|
||||||
t.Close()
|
t.Close()
|
||||||
|
CloseTerms <- true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,11 +149,9 @@ func (t *Terminal) Close() {
|
||||||
t.Status = TTClose
|
t.Status = TTClose
|
||||||
// call the lua function that the user has given as a callback
|
// call the lua function that the user has given as a callback
|
||||||
if t.getOutput {
|
if t.getOutput {
|
||||||
// TODO: plugin callback on Term emulator
|
if t.callback != nil {
|
||||||
// _, err := Call(t.callback, t.output.String())
|
t.callback(t.output.String())
|
||||||
// if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
|
}
|
||||||
// TermMessage(err)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue