1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
package editor
import (
"fmt"
"io"
"os"
"os/exec"
"runtime"
"strings"
"github.com/la5nta/pat/internal/buildinfo"
)
func Executable() string {
if e := os.Getenv("EDITOR"); e != "" {
return e
} else if e := os.Getenv("VISUAL"); e != "" {
return e
}
switch runtime.GOOS {
case "windows":
return "notepad"
case "linux":
if path, err := exec.LookPath("editor"); err == nil {
return path
}
}
return "vi"
}
func Open(path string) error {
cmd := exec.Command(Executable(), path)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
return cmd.Run()
}
func EditText(template string) (string, error) {
f, err := os.CreateTemp("", strings.ToLower(buildinfo.AppName)+"_edit_*.txt")
if err != nil {
return template, fmt.Errorf("Unable to prepare temporary file for body: %w", err)
}
defer f.Close()
defer os.Remove(f.Name())
f.Write([]byte(template))
f.Sync()
// Windows fix: Avoid 'cannot access the file because it is being used by another process' error.
// Close the file before opening the editor.
f.Close()
// Fire up the editor
if err := Open(f.Name()); err != nil {
return template, fmt.Errorf("Unable to start text editor: %w", err)
}
// Read back the edited file
f, err = os.OpenFile(f.Name(), os.O_RDWR, 0o666)
if err != nil {
return template, fmt.Errorf("Unable to read temporary file from editor: %w", err)
}
defer f.Close()
defer os.Remove(f.Name())
body, err := io.ReadAll(f)
return string(body), err
}
|