Skip to content

Commit

Permalink
Solidify editor
Browse files Browse the repository at this point in the history
  • Loading branch information
cyx committed Apr 2, 2021
1 parent fbce21f commit e3785f7
Showing 1 changed file with 41 additions and 22 deletions.
63 changes: 41 additions & 22 deletions internal/prompt/editor.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package prompt

import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"

"github.com/kballard/go-shellquote"
)

const (
defaultEditor = "vim"
)

const defaultEditor = "vim"
var (
bom = []byte{0xef, 0xbb, 0xbf}
)

var defaultEditorPrompt = &editorPrompt{defaultEditor: defaultEditor}

Expand Down Expand Up @@ -37,28 +45,23 @@ func (p *editorPrompt) getPreferredEditor() string {
return editor
}

func (p *editorPrompt) resolveEditorArguments(executable string, filename string) []string {
args := []string{filename}

if strings.Contains(executable, "Visual Studio Code.app") {
args = append([]string{"--wait"}, args...)
}

// TODO(cyx): add other common editors

return args
}

// openFile opens filename in the preferred text editor, resolving the
// arguments with editor specific logic.
func (p *editorPrompt) openFile(filename string) error {
// Get the full executable path for the editor.
executable, err := exec.LookPath(p.getPreferredEditor())
editorCommand := p.getPreferredEditor()

args, err := shellquote.Split(editorCommand)
if err != nil {
return err
}
args = append(args, filename)

cmd := exec.Command(executable, p.resolveEditorArguments(executable, filename)...)
editorExe, err := exec.LookPath(args[0])
if err != nil {
return err
}

cmd := exec.Command(editorExe, args[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Expand All @@ -80,14 +83,29 @@ func (p *editorPrompt) captureInput(contents []byte, pattern string) ([]byte, er

filename := file.Name()

// Defer removal of the temporary file in case any of the next steps fail.
defer os.Remove(filename)

// write utf8 BOM header
// The reason why we do this is because notepad.exe on Windows determines the
// encoding of an "empty" text file by the locale, for example, GBK in China,
// while golang string only handles utf8 well. However, a text file with utf8
// BOM header is not considered "empty" on Windows, and the encoding will then
// be determined utf8 by notepad.exe, instead of GBK or other encodings.
if _, err := file.Write(bom); err != nil {
return nil, err
}

if len(contents) > 0 {
if err := os.WriteFile(filename, contents, 0644); err != nil {
if _, err := file.Write(contents); err != nil {
return nil, fmt.Errorf("Failed to write to file: %w", err)
}
}

// Defer removal of the temporary file in case any of the next steps fail.
defer os.Remove(filename)
// close the fd to allow the editor to save file
if err := file.Close(); err != nil {
return nil, err
}

if err = file.Close(); err != nil {
return nil, err
Expand All @@ -97,10 +115,11 @@ func (p *editorPrompt) captureInput(contents []byte, pattern string) ([]byte, er
return nil, err
}

bytes, err := os.ReadFile(filename)
raw, err := os.ReadFile(filename)
if err != nil {
return []byte{}, err
}

return bytes, nil
// strip BOM header
return bytes.TrimPrefix(raw, bom), nil
}

0 comments on commit e3785f7

Please sign in to comment.