Repository: TomWright/dasel
Pull request #160 (2021-08-30 15:10:46)

Fix an issue when parsing selectors containing unicode characters


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f32500..91f1dce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 - `-v`, `--value` flag to workaround [dash issue](https://github.com/TomWright/dasel/issues/117).
 
+### Fixed
+
+- Fixed an issue in which unicode characters could cause issues when parsing selectors.
+
 ## [v1.19.0] - 2021-08-14
 
 ### Added
diff --git a/selector.go b/selector.go
index 2c9182b..986f451 100644
--- a/selector.go
+++ b/selector.go
@@ -15,10 +15,12 @@ func ExtractNextSelector(input string) (string, int) {
 	i := 0
 	read := 0
 	for k, v := range input {
+		curRuneStr := string(v)
+		curRuneLength := len(curRuneStr)
 		if escapedIndex == k-1 && k != 0 {
 			// last character was escape character
-			res += string(v)
-			read++
+			res += curRuneStr
+			read += curRuneLength
 			continue
 		}
 
@@ -30,15 +32,15 @@ func ExtractNextSelector(input string) (string, int) {
 
 		if v == '\\' {
 			escapedIndex = k
-			read++
+			read += curRuneLength
 			continue
 		}
 
 		if i == 0 && v == '.' && k != 0 {
 			break
 		}
-		res += string(v)
-		read++
+		res += curRuneStr
+		read += curRuneLength
 	}
 	return res, read
 }


Test patch:
diff --git a/internal/command/root_select_test.go b/internal/command/root_select_test.go
index 8d28c46..ad29726 100644
--- a/internal/command/root_select_test.go
+++ b/internal/command/root_select_test.go
@@ -648,6 +648,18 @@ ECB,European Central Bank
 ESTAT,Eurostat
 ILO,International Labor Organization
 `, nil, "-w", "csv"))
+
+	// https://github.com/TomWright/dasel/issues/159
+	t.Run("SelectFilterOnUnicode", selectTest(`
+{
+   "data": [
+     {"name": "Fu Shun", "ship_type": "Destroyer"},
+     {"name": "Sheffield", "ship_type": "Light Cruiser"},
+     {"name": "Ägir", "ship_type": "Large Cruiser"}
+   ]
+ }
+`, "json", ".data.(name=Ägir).ship_type", `"Large Cruiser"
+`, nil))
 }
 
 func TestRootCmd_Select_JSON_Format(t *testing.T) {
diff --git a/node_test.go b/node_test.go
index 2a1f653..1cd4d35 100644
--- a/node_test.go
+++ b/node_test.go
@@ -369,6 +369,18 @@ func TestParseSelector(t *testing.T) {
 			},
 		},
 	}))
+	t.Run("Unicode", testParseSelector(".(name=Ägir).b", dasel.Selector{
+		Raw:       ".(name=Ägir).b",
+		Current:   ".(name=Ägir)",
+		Remaining: ".b",
+		Type:      "DYNAMIC",
+		Conditions: []dasel.Condition{
+			&dasel.EqualCondition{
+				Key:   "name",
+				Value: "Ägir",
+			},
+		},
+	}))
 }
 
 func extractValues(nodes []*dasel.Node) []interface{} {
diff --git a/selector_test.go b/selector_test.go
index 382fdd6..a4816ef 100644
--- a/selector_test.go
+++ b/selector_test.go
@@ -49,6 +49,7 @@ func TestExtractNextSelector(t *testing.T) {
 	t.Run("SimpleProp", testExtractNextSelector(`.name`, `.name`, 5))
 	t.Run("SimpleIndex", testExtractNextSelector(`.[123]`, `.[123]`, 6))
 	t.Run("SimpleLength", testExtractNextSelector(`.[#]`, `.[#]`, 4))
+	t.Run("UnicodeCharacter", testExtractNextSelector(`.(name=Ägir).asd`, `.(name=Ägir)`, 13))
 }
 
 func TestDynamicSelectorToGroups(t *testing.T) {
@@ -74,6 +75,10 @@ func TestDynamicSelectorToGroups(t *testing.T) {
 		"a=.",
 		"b=2",
 	}))
+	t.Run("Unicode", testDynamicSelectorToGroups("(a=.)(b=Ägir)", []string{
+		"a=.",
+		"b=Ägir",
+	}))
 }
 
 func TestFindDynamicSelectorParts(t *testing.T) {
@@ -102,6 +107,11 @@ func TestFindDynamicSelectorParts(t *testing.T) {
 		Comparison: "<=",
 		Value:      "b",
 	}))
+	t.Run("UnicodeEqual", testFindDynamicSelectorParts("name=Ägir", dasel.DynamicSelectorParts{
+		Key:        "name",
+		Comparison: "=",
+		Value:      "Ägir",
+	}))
 	t.Run("NestedGroupIgnored", testFindDynamicSelectorParts("(.(x=y)).x=1", dasel.DynamicSelectorParts{
 		Key:        "(.(x=y)).x",
 		Comparison: "=",