Add support for editing message in external editor
Closes #313 Fixes #311
This commit is contained in:
parent
6525f9ec66
commit
b2ca5ed37e
@ -146,6 +146,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
|||||||
"redact": cmdRedact,
|
"redact": cmdRedact,
|
||||||
"react": cmdReact,
|
"react": cmdReact,
|
||||||
"edit": cmdEdit,
|
"edit": cmdEdit,
|
||||||
|
"external": cmdExternalEditor,
|
||||||
"download": cmdDownload,
|
"download": cmdDownload,
|
||||||
"upload": cmdUpload,
|
"upload": cmdUpload,
|
||||||
"open": cmdOpen,
|
"open": cmdOpen,
|
||||||
|
@ -17,12 +17,14 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -177,6 +179,75 @@ func cmdEdit(cmd *Command) {
|
|||||||
cmd.Room.StartSelecting(SelectEdit, "")
|
cmd.Room.StartSelecting(SelectEdit, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findEditorExecutable() (string, string, error) {
|
||||||
|
if editor := os.Getenv("VISUAL"); len(editor) > 0 {
|
||||||
|
if path, err := exec.LookPath(editor); err != nil {
|
||||||
|
return "", "", fmt.Errorf("$VISUAL ('%s') not found in $PATH", editor)
|
||||||
|
} else {
|
||||||
|
return editor, path, nil
|
||||||
|
}
|
||||||
|
} else if editor = os.Getenv("EDITOR"); len(editor) > 0 {
|
||||||
|
if path, err := exec.LookPath(editor); err != nil {
|
||||||
|
return "", "", fmt.Errorf("$EDITOR ('%s') not found in $PATH", editor)
|
||||||
|
} else {
|
||||||
|
return editor, path, nil
|
||||||
|
}
|
||||||
|
} else if path, _ := exec.LookPath("nano"); len(path) > 0 {
|
||||||
|
return "nano", path, nil
|
||||||
|
} else if path, _ = exec.LookPath("vi"); len(path) > 0 {
|
||||||
|
return "vi", path, nil
|
||||||
|
} else {
|
||||||
|
return "", "", fmt.Errorf("$VISUAL and $EDITOR not set, nano and vi not found in $PATH")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdExternalEditor(cmd *Command) {
|
||||||
|
var file *os.File
|
||||||
|
defer func() {
|
||||||
|
if file != nil {
|
||||||
|
_ = file.Close()
|
||||||
|
_ = os.Remove(file.Name())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
fileExtension := "md"
|
||||||
|
if cmd.Config.Preferences.DisableMarkdown {
|
||||||
|
if cmd.Config.Preferences.DisableHTML {
|
||||||
|
fileExtension = "txt"
|
||||||
|
} else {
|
||||||
|
fileExtension = "html"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if editorName, executablePath, err := findEditorExecutable(); err != nil {
|
||||||
|
cmd.Reply("Couldn't find editor to use: %v", err)
|
||||||
|
return
|
||||||
|
} else if file, err = os.CreateTemp("", fmt.Sprintf("gomuks-draft-*.%s", fileExtension)); err != nil {
|
||||||
|
cmd.Reply("Failed to create temp file: %v", err)
|
||||||
|
return
|
||||||
|
} else if _, err = file.WriteString(cmd.RawArgs); err != nil {
|
||||||
|
cmd.Reply("Failed to write to temp file: %v", err)
|
||||||
|
} else if err = file.Close(); err != nil {
|
||||||
|
cmd.Reply("Failed to close temp file: %v", err)
|
||||||
|
} else if err = cmd.UI.RunExternal(executablePath, file.Name()); err != nil {
|
||||||
|
var exitErr *exec.ExitError
|
||||||
|
if isExit := errors.As(err, &exitErr); isExit {
|
||||||
|
cmd.Reply("%s exited with non-zero status %d", editorName, exitErr.ExitCode())
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Failed to run %s: %v", editorName, err)
|
||||||
|
}
|
||||||
|
} else if data, err := os.ReadFile(file.Name()); err != nil {
|
||||||
|
cmd.Reply("Failed to read temp file: %v", err)
|
||||||
|
} else if len(bytes.TrimSpace(data)) > 0 {
|
||||||
|
cmd.Room.InputSubmit(string(data))
|
||||||
|
} else {
|
||||||
|
cmd.Reply("Temp file was blank, sending cancelled")
|
||||||
|
if cmd.Room.editing != nil {
|
||||||
|
cmd.Room.SetEditing(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func cmdRedact(cmd *Command) {
|
func cmdRedact(cmd *Command) {
|
||||||
cmd.Room.StartSelecting(SelectRedact, strings.Join(cmd.Args, " "))
|
cmd.Room.StartSelecting(SelectRedact, strings.Join(cmd.Args, " "))
|
||||||
}
|
}
|
||||||
|
14
ui/ui.go
14
ui/ui.go
@ -18,6 +18,7 @@ package ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
"github.com/zyedidia/clipboard"
|
"github.com/zyedidia/clipboard"
|
||||||
|
|
||||||
@ -119,3 +120,16 @@ func (ui *GomuksUI) SetView(name View) {
|
|||||||
func (ui *GomuksUI) MainView() ifc.MainView {
|
func (ui *GomuksUI) MainView() ifc.MainView {
|
||||||
return ui.mainView
|
return ui.mainView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ui *GomuksUI) RunExternal(executablePath string, args ...string) error {
|
||||||
|
var err error
|
||||||
|
ui.app.Suspend(func() {
|
||||||
|
cmd := exec.Command(executablePath, args...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
err = cmd.Run()
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user