fix: iris now reloads via signal handoff
This commit is contained in:
@@ -15,6 +15,7 @@ run:
|
|||||||
[linux, macos]
|
[linux, macos]
|
||||||
reload:
|
reload:
|
||||||
@go build -o iris main.go
|
@go build -o iris main.go
|
||||||
|
@if [ -n "${IRIS_PID:-}" ]; then kill -USR1 $IRIS_PID; fi
|
||||||
@if [ -z "${IRIS_FD:-}" ]; then ./iris; fi
|
@if [ -z "${IRIS_FD:-}" ]; then ./iris; fi
|
||||||
|
|
||||||
# update pkg
|
# update pkg
|
||||||
|
|||||||
+22
-42
@@ -14,13 +14,13 @@ import (
|
|||||||
|
|
||||||
"github.com/creack/pty"
|
"github.com/creack/pty"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/versenilvis/iris/commands/core"
|
||||||
_ "github.com/versenilvis/iris/commands/dev"
|
_ "github.com/versenilvis/iris/commands/dev"
|
||||||
_ "github.com/versenilvis/iris/commands/fs"
|
_ "github.com/versenilvis/iris/commands/fs"
|
||||||
_ "github.com/versenilvis/iris/commands/info"
|
_ "github.com/versenilvis/iris/commands/info"
|
||||||
_ "github.com/versenilvis/iris/commands/runner"
|
_ "github.com/versenilvis/iris/commands/runner"
|
||||||
_ "github.com/versenilvis/iris/commands/search"
|
_ "github.com/versenilvis/iris/commands/search"
|
||||||
_ "github.com/versenilvis/iris/commands/view"
|
_ "github.com/versenilvis/iris/commands/view"
|
||||||
"github.com/versenilvis/iris/commands/core"
|
|
||||||
"github.com/versenilvis/iris/integration"
|
"github.com/versenilvis/iris/integration"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
@@ -36,44 +36,17 @@ It works exactly like coding editor suggestion menu drop down.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
go watchSelf()
|
if os.Getenv("IRIS_RELOADED") == "true" {
|
||||||
|
fmt.Printf("\r\n\033[35m[IRIS] reloading...\033[0m\r\n")
|
||||||
|
os.Unsetenv("IRIS_RELOADED")
|
||||||
|
}
|
||||||
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func watchSelf() {
|
|
||||||
exe, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
startTime := time.Now()
|
|
||||||
|
|
||||||
for {
|
|
||||||
time.Sleep(500 * time.Millisecond)
|
|
||||||
info, err := os.Stat(exe)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.ModTime().After(startTime) {
|
|
||||||
// clean up terminal before exec
|
|
||||||
fmt.Printf("\r\n\033[35m[IRIS] binary updated, reloading...\033[0m\r\n")
|
|
||||||
// we need to be careful about raw mode but syscall.Exec will replace the process
|
|
||||||
// which is fine as the new iris will setup its own raw mode
|
|
||||||
// however, to be safe for the terminal state, we'd ideally restore then exec
|
|
||||||
// but since we're inside a PTY wrapper, it's more complex
|
|
||||||
// the simplest way: just exec, the new iris will handle the terminal
|
|
||||||
err := syscall.Exec(exe, os.Args, os.Environ())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Reload failed: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func runWrapper() {
|
func runWrapper() {
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -86,7 +59,7 @@ func runWrapper() {
|
|||||||
// fd 0, 1, 2 are stdin, stdout, stderr (handled by pty)
|
// fd 0, 1, 2 are stdin, stdout, stderr (handled by pty)
|
||||||
// fd 3 is our write pipe
|
// fd 3 is our write pipe
|
||||||
c.ExtraFiles = []*os.File{w}
|
c.ExtraFiles = []*os.File{w}
|
||||||
c.Env = append(os.Environ(), "IRIS_FD=3")
|
c.Env = append(os.Environ(), "IRIS_FD=3", fmt.Sprintf("IRIS_PID=%d", os.Getpid()))
|
||||||
|
|
||||||
ptmx, err := pty.Start(c)
|
ptmx, err := pty.Start(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -97,15 +70,22 @@ func runWrapper() {
|
|||||||
|
|
||||||
core.ShellPID = c.Process.Pid
|
core.ShellPID = c.Process.Pid
|
||||||
|
|
||||||
ch := make(chan os.Signal, 1)
|
// signal handling for resize and reload
|
||||||
signal.Notify(ch, syscall.SIGWINCH)
|
sigCh := make(chan os.Signal, 2)
|
||||||
|
signal.Notify(sigCh, syscall.SIGWINCH, syscall.SIGUSR1)
|
||||||
go func() {
|
go func() {
|
||||||
for range ch {
|
for s := range sigCh {
|
||||||
if err := pty.InheritSize(os.Stdin, ptmx); err != nil {
|
switch s {
|
||||||
|
case syscall.SIGWINCH:
|
||||||
|
_ = pty.InheritSize(os.Stdin, ptmx)
|
||||||
|
case syscall.SIGUSR1:
|
||||||
|
exe, _ := os.Executable()
|
||||||
|
os.Setenv("IRIS_RELOADED", "true")
|
||||||
|
_ = syscall.Exec(exe, os.Args, os.Environ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
ch <- syscall.SIGWINCH
|
sigCh <- syscall.SIGWINCH
|
||||||
|
|
||||||
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -234,12 +214,12 @@ func runWrapper() {
|
|||||||
selected := overlay.Items[overlay.Cursor].Cmd
|
selected := overlay.Items[overlay.Cursor].Cmd
|
||||||
|
|
||||||
TermWrite([]byte(overlay.ClearAndDisable()))
|
TermWrite([]byte(overlay.ClearAndDisable()))
|
||||||
|
|
||||||
// auto add space after tab for next suggestion in spec mode
|
// auto add space after tab for next suggestion in spec mode
|
||||||
if mode == "spec" || b == 0x09 {
|
if mode == "spec" || b == 0x09 {
|
||||||
selected += " "
|
selected += " "
|
||||||
}
|
}
|
||||||
|
|
||||||
// sync our naive buffer with the selected result
|
// sync our naive buffer with the selected result
|
||||||
naiveBuffer = selected
|
naiveBuffer = selected
|
||||||
mode = "spec" // reset to spec mode after selection
|
mode = "spec" // reset to spec mode after selection
|
||||||
@@ -247,7 +227,7 @@ func runWrapper() {
|
|||||||
// delete line (ctrl+u)
|
// delete line (ctrl+u)
|
||||||
ptmx.Write([]byte{0x15})
|
ptmx.Write([]byte{0x15})
|
||||||
ptmx.Write([]byte(selected))
|
ptmx.Write([]byte(selected))
|
||||||
|
|
||||||
if b == '\r' {
|
if b == '\r' {
|
||||||
ptmx.Write([]byte{'\r'})
|
ptmx.Write([]byte{'\r'})
|
||||||
naiveBuffer = ""
|
naiveBuffer = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user