Repository: TomWright/dasel
Pull request #248 (2022-09-28 09:51:27)

Twright/selector parsing


Patch:
diff --git a/selector.go b/selector.go
index 986f451..55ee289 100644
--- a/selector.go
+++ b/selector.go
@@ -2,6 +2,7 @@ package dasel
 
 import (
 	"errors"
+	"strings"
 )
 
 // ErrDynamicSelectorBracketMismatch is returned when the number of opening brackets doesn't equal that
@@ -85,6 +86,33 @@ type DynamicSelectorParts struct {
 	Value      string
 }
 
+var comparisons = []string{
+	"=",
+	"!=",
+	"<",
+	"<=",
+	">",
+	">=",
+}
+
+func isBuildingComparison(comparison string) bool {
+	for _, c := range comparisons {
+		if strings.HasPrefix(c, comparison) {
+			return true
+		}
+	}
+	return false
+}
+
+func isValidComparison(comparison string) bool {
+	for _, c := range comparisons {
+		if comparison == c {
+			return true
+		}
+	}
+	return false
+}
+
 // FindDynamicSelectorParts extracts the parts from the dynamic selector given.
 func FindDynamicSelectorParts(selector string) DynamicSelectorParts {
 	i := 0
@@ -110,8 +138,12 @@ func FindDynamicSelectorParts(selector string) DynamicSelectorParts {
 				parts.Value += string(v)
 			}
 
-		// Matches a comparison character
-		case i == 0 && (v == '<' || v == '>' || v == '=' || v == '!'):
+		// Matches a comparison operator
+		case i == 0 && isValidComparison(parts.Comparison+string(v)):
+			parts.Comparison += string(v)
+
+		// Is building a comparison character
+		case i == 0 && isBuildingComparison(parts.Comparison+string(v)):
 			parts.Comparison += string(v)
 
 		// Add to key or value based on comparison existence


Test patch:
diff --git a/internal/command/root_select_test.go b/internal/command/root_select_test.go
index bb74e65..900fcf9 100644
--- a/internal/command/root_select_test.go
+++ b/internal/command/root_select_test.go
@@ -650,6 +650,21 @@ spec:
 	t.Run("NullInput", selectTest(`null`, "yaml", `.`, newline("{}"), nil))
 	t.Run("EmptyDocument", selectTest(`---`, "yaml", `.`, newline("{}"), nil))
 	t.Run("BlankInput", selectTest(``, "yaml", `.`, newline("{}"), nil))
+
+	// https://github.com/TomWright/dasel/discussions/244
+	t.Run("DynamicSelectorContainingEqualsInValue", selectTest(`
+options:
+  k3s:
+    extraArgs:
+      - arg: --no-deploy=traefik
+        nodeFilters:
+          - server:*
+      - arg: --kube-apiserver-arg=feature-gates=HPAContainerMetrics=true
+        nodeFilters:
+          - server:*
+`, "yaml", `.options.k3s.extraArgs.(arg=--no-deploy=traefik)`, newline(`arg: --no-deploy=traefik
+nodeFilters:
+- server:*`), nil))
 }
 
 func TestRootCmd_Select_TOML(t *testing.T) {
diff --git a/node_test.go b/node_test.go
index 010d82d..96a787d 100644
--- a/node_test.go
+++ b/node_test.go
@@ -138,8 +138,8 @@ func TestParseSelector(t *testing.T) {
 		}
 	})
 	t.Run("InvalidDynamicComparison", func(t *testing.T) {
-		_, err := dasel.ParseSelector(".(x<=>2)")
-		exp := &dasel.UnknownComparisonOperatorErr{Operator: "<=>"}
+		_, err := dasel.ParseSelector(".(x@2)")
+		exp := &dasel.UnknownComparisonOperatorErr{Operator: ""}
 		if err == nil || err.Error() != exp.Error() {
 			t.Errorf("expected error %v, got %v", exp, err)
 		}
@@ -152,15 +152,15 @@ func TestParseSelector(t *testing.T) {
 		}
 	})
 	t.Run("UnknownComparisonOperator", func(t *testing.T) {
-		_, err := dasel.ParseSelector(".(a<=>b)")
-		exp := "unknown comparison operator: <=>"
+		_, err := dasel.ParseSelector(".(a@b)")
+		exp := "unknown comparison operator: "
 		if err == nil || err.Error() != exp {
 			t.Errorf("expected error %v, got %v", exp, err)
 		}
 	})
 	t.Run("UnknownSearchComparisonOperator", func(t *testing.T) {
-		_, err := dasel.ParseSelector(".(?:a<=>b)")
-		exp := "unknown comparison operator: <=>"
+		_, err := dasel.ParseSelector(".(?:a@b)")
+		exp := "unknown comparison operator: "
 		if err == nil || err.Error() != exp {
 			t.Errorf("expected error %v, got %v", exp, err)
 		}
diff --git a/selector_test.go b/selector_test.go
index a4816ef..5b62882 100644
--- a/selector_test.go
+++ b/selector_test.go
@@ -92,6 +92,11 @@ func TestFindDynamicSelectorParts(t *testing.T) {
 		Comparison: "=",
 		Value:      "b",
 	}))
+	t.Run("EqualWithEqualsInValue", testFindDynamicSelectorParts("a=b=c", dasel.DynamicSelectorParts{
+		Key:        "a",
+		Comparison: "=",
+		Value:      "b=c",
+	}))
 	t.Run("NotEqual", testFindDynamicSelectorParts("a!=b", dasel.DynamicSelectorParts{
 		Key:        "a",
 		Comparison: "!=",