/
alt3rmann
/
graphql-engine
Обзор
Документация
Войти
/
alt3rmann
/
graphql-engine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
cli/internal/metadataobject/actions/editor/editor.go
132 строки
3 KB
Mohd Bilal
cli: refactor `internal/metadataobject/actions/cli_extension` and `internal/metadataobject/actions/editor` packages to use `internal/errors`
15 ноя 2022, 11:24
15 ноя 2022, 11:24
3353d77
Код
Авторство
О чём код?
package editor import ( "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "runtime" "strings" "github.com/hasura/graphql-engine/cli/v2/internal/errors" ) const ( defaultEditor = "vi" defaultShell = "/bin/bash" windowsEditor = "notepad" windowsShell = "cmd" ) // PreferredEditorResolver is a function that returns an editor that the user // prefers to use, such as the configured `$EDITOR` environment variable. type PreferredEditorResolver func() ([]string, bool) // GetPreferredEditorFromEnvironment returns the user's editor as defined by the // `$EDITOR` environment variable, or the `DefaultEditor` if it is not set. func GetPreferredEditorFromEnvironment() ([]string, bool) { editor := os.Getenv("EDITOR") if len(editor) == 0 { editor = platformize(defaultEditor, windowsEditor) } if !strings.Contains(editor, " ") { return []string{editor}, false } if !strings.ContainsAny(editor, "\"'\\") { return strings.Split(editor, " "), false } shell := defaultEnvShell() return append(shell, editor), true } // OpenFileInEditor opens filename in a text editor. func OpenFileInEditor(filename string, resolveEditor PreferredEditorResolver) error { var op errors.Op = "editor.OpenFileInEditor" // Get the full executable path for the editor. args, shell := resolveEditor() if len(args) == 0 { return errors.E(op, fmt.Errorf("no editor defined, can't open %s", filename)) } abs, err := filepath.Abs(filename) if err != nil { return errors.E(op, err) } cmdArgs := make([]string, len(args)) copy(cmdArgs, args) if shell { last := cmdArgs[len(cmdArgs)-1] cmdArgs[len(cmdArgs)-1] = fmt.Sprintf("%s %q", last, abs) } else { cmdArgs = append(cmdArgs, abs) } cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { return errors.E(op, err) } return nil } // CaptureInputFromEditor opens a temporary file in a text editor and returns // the written bytes on success or an error on failure. It handles deletion // of the temporary file behind the scenes. func CaptureInputFromEditor(resolveEditor PreferredEditorResolver, text, extension string) ([]byte, error) { var op errors.Op = "editor.CaptureInputFromEditor" file, err := ioutil.TempFile(os.TempDir(), fmt.Sprintf("*.%s", extension)) if err != nil { return []byte{}, errors.E(op, err) } filename := file.Name() // Defer removal of the temporary file in case any of the next steps fail. defer os.Remove(filename) _, err = file.Write([]byte(text)) if err != nil { return []byte{}, errors.E(op, err) } if err = file.Close(); err != nil { return []byte{}, errors.E(op, err) } if err = OpenFileInEditor(filename, resolveEditor); err != nil { return []byte{}, errors.E(op, err) } bytes, err := ioutil.ReadFile(filename) if err != nil { return []byte{}, errors.E(op, err) } return bytes, nil } func defaultEnvShell() []string { shell := os.Getenv("SHELL") if len(shell) == 0 { shell = platformize(defaultShell, windowsShell) } flag := "-c" if shell == windowsShell { flag = "/C" } return []string{shell, flag} } func platformize(linux, windows string) string { if runtime.GOOS == "windows" { return windows } return linux }