mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-23 07:33:32 -06:00
131c2cadda
Signed-off-by: Andrew Hayes <andrew.hayes@harness.io>
102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package command
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
)
|
|
|
|
type consoleBracketState struct {
|
|
openNewLine int
|
|
brace int
|
|
bracket int
|
|
parentheses int
|
|
buffer []string
|
|
}
|
|
|
|
// commandInOpenState return an int to inform if brackets are open
|
|
// or if any escaped new lines
|
|
// in the console and we should hold off on processing the commands
|
|
// it returns 3 states:
|
|
// -1 is returned the is an incorrect amount of brackets.
|
|
// for example "())" has too many close brackets
|
|
// 0 is returned if the brackets are closed.
|
|
// for examples "()" or "" would be in a close bracket state
|
|
// >=1 is returned for the amount of open brackets.
|
|
// for example "({" would return 2. "({}" would return 1
|
|
func (c *consoleBracketState) commandInOpenState() int {
|
|
switch {
|
|
case c.brace < 0:
|
|
fallthrough
|
|
case c.bracket < 0:
|
|
fallthrough
|
|
case c.parentheses < 0:
|
|
return -1
|
|
}
|
|
|
|
// we calculate open brackets, braces and parentheses by the diff between each count
|
|
var total int
|
|
total += c.openNewLine
|
|
total += c.brace
|
|
total += c.bracket
|
|
total += c.parentheses
|
|
return total
|
|
}
|
|
|
|
// UpdateState updates the state of the console with the latest line data
|
|
func (c *consoleBracketState) UpdateState(line string) (string, int) {
|
|
defer c.checkStateAndClearBuffer()
|
|
// as new lines are a kind of "one off" we reset each update
|
|
c.openNewLine = 0
|
|
|
|
// escaped new lines are treated as a "one off" bracket
|
|
// the four \\\\ means we have a false positive for a new line, as it's just an escaped \..
|
|
if strings.HasSuffix(line, "\\") && !strings.HasSuffix(line, "\\\\") {
|
|
c.openNewLine++
|
|
}
|
|
|
|
line = strings.TrimSuffix(line, "\\")
|
|
if len(line) == 0 {
|
|
// we can skip empty lines
|
|
return c.getCommand(), c.commandInOpenState()
|
|
}
|
|
c.buffer = append(c.buffer, line)
|
|
|
|
tokens, _ := hclsyntax.LexConfig([]byte(line), "<console-input>", hcl.Pos{Line: 1, Column: 1})
|
|
for _, token := range tokens {
|
|
switch token.Type { //nolint:exhaustive // we only care about these specific types
|
|
case hclsyntax.TokenOBrace:
|
|
c.brace++
|
|
case hclsyntax.TokenCBrace:
|
|
c.brace--
|
|
case hclsyntax.TokenOBrack:
|
|
c.bracket++
|
|
case hclsyntax.TokenCBrack:
|
|
c.bracket--
|
|
case hclsyntax.TokenOParen:
|
|
c.parentheses++
|
|
case hclsyntax.TokenCParen:
|
|
c.parentheses--
|
|
}
|
|
}
|
|
return c.getCommand(), c.commandInOpenState()
|
|
}
|
|
|
|
// getCommand joins the buffer and returns it
|
|
func (c *consoleBracketState) getCommand() string {
|
|
output := strings.Join(c.buffer, "\n")
|
|
return output
|
|
}
|
|
|
|
func (c *consoleBracketState) checkStateAndClearBuffer() {
|
|
if c.commandInOpenState() <= 0 {
|
|
c.buffer = []string{}
|
|
}
|
|
}
|