mirror of
https://github.com/hashicorp/terraform.git
synced 2026-02-19 02:39:17 -05:00
103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
// Copyright IBM Corp. 2014, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
//go:build !solaris
|
|
// +build !solaris
|
|
|
|
// The readline library we use doesn't currently support solaris so
|
|
// we just build tag it off.
|
|
|
|
package command
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/chzyer/readline"
|
|
"github.com/hashicorp/cli"
|
|
|
|
"github.com/hashicorp/terraform/internal/repl"
|
|
)
|
|
|
|
func (c *ConsoleCommand) modeInteractive(session *repl.Session, ui cli.Ui) int {
|
|
// Configure input
|
|
l, err := readline.NewEx(&readline.Config{
|
|
Prompt: "> ",
|
|
InterruptPrompt: "^C",
|
|
EOFPrompt: "exit",
|
|
HistorySearchFold: true,
|
|
Stdin: os.Stdin,
|
|
Stdout: os.Stdout,
|
|
Stderr: os.Stderr,
|
|
})
|
|
if err != nil {
|
|
c.Ui.Error(fmt.Sprintf(
|
|
"Error initializing console: %s",
|
|
err))
|
|
return 1
|
|
}
|
|
defer l.Close()
|
|
|
|
// TODO: Currently we're handling multi-line input largely _in spite of_
|
|
// the readline library, because it doesn't support that. This means that
|
|
// in particular the history treats each line as a separate history entry,
|
|
// and doesn't allow editing of previous lines after the user's already
|
|
// pressed enter.
|
|
//
|
|
// Hopefully we can do better than this one day, but having some basic
|
|
// support for multi-line input is at least better than none at all:
|
|
// this is mainly helpful when pasting in expressions from elsewhere that
|
|
// already have newline characters in them, to avoid pre-editing it.
|
|
|
|
lines := make([]string, 0, 4)
|
|
for {
|
|
// Read a line
|
|
if len(lines) == 0 {
|
|
l.SetPrompt("> ")
|
|
} else {
|
|
l.SetPrompt(": ")
|
|
}
|
|
line, err := l.Readline()
|
|
if err == readline.ErrInterrupt {
|
|
if len(lines) == 0 && line == "" {
|
|
break
|
|
} else if line != "" {
|
|
continue
|
|
} else {
|
|
// Reset the entry buffer to start a new expression
|
|
lines = lines[:0]
|
|
ui.Output("(multi-line entry canceled)")
|
|
continue
|
|
}
|
|
} else if err == io.EOF {
|
|
break
|
|
}
|
|
lines = append(lines, line)
|
|
// The following implements a heuristic for deciding if it seems likely
|
|
// that the user was intending to continue entering more expression
|
|
// characters on a subsequent line. This should get the right answer
|
|
// for any valid expression, but might get confused by invalid input.
|
|
// The user can always hit enter one more time (entering a blank line)
|
|
// to break out of a multi-line sequence and force interpretation of
|
|
// what was already entered.
|
|
if repl.ExpressionEntryCouldContinue(lines) {
|
|
continue
|
|
}
|
|
|
|
input := strings.Join(lines, "\n") + "\n"
|
|
lines = lines[:0] // reset for next iteration
|
|
out, exit, diags := session.Handle(input)
|
|
if diags.HasErrors() {
|
|
c.showDiagnostics(diags)
|
|
}
|
|
if exit {
|
|
break
|
|
}
|
|
|
|
ui.Output(out)
|
|
}
|
|
|
|
return 0
|
|
}
|