diff --git a/pkg/database/tags/normalization_test.go b/pkg/database/tags/normalization_test.go index 66774b81..e0a927e8 100644 --- a/pkg/database/tags/normalization_test.go +++ b/pkg/database/tags/normalization_test.go @@ -21,8 +21,6 @@ package tags import ( "testing" - - "github.com/ZaparooProject/go-zapscript" ) func TestNormalizeTag(t *testing.T) { @@ -87,54 +85,3 @@ func TestNormalizeTag(t *testing.T) { }) } } - -func TestNormalizeTagFilter(t *testing.T) { - tests := []struct { - name string - input zapscript.TagFilter - expected zapscript.TagFilter - }{ - { - name: "basic normalization", - input: zapscript.TagFilter{ - Type: "Genre", - Value: "RPG", - }, - expected: zapscript.TagFilter{ - Type: "genre", - Value: "rpg", - }, - }, - { - name: "complex normalization", - input: zapscript.TagFilter{ - Type: " Year ", - Value: " 1.991 ", - }, - expected: zapscript.TagFilter{ - Type: "year", - Value: "1-991", - }, - }, - { - name: "keep colon and dash in value", - input: zapscript.TagFilter{ - Type: "Disc", - Value: "1-2", - }, - expected: zapscript.TagFilter{ - Type: "disc", - Value: "1-2", - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := NormalizeTagFilter(tt.input) - if result.Type != tt.expected.Type || result.Value != tt.expected.Value { - t.Errorf("NormalizeTagFilter(%+v) = %+v, want %+v", tt.input, result, tt.expected) - } - }) - } -} diff --git a/pkg/database/tags/tags.go b/pkg/database/tags/tags.go index eabff7fa..659afa62 100644 --- a/pkg/database/tags/tags.go +++ b/pkg/database/tags/tags.go @@ -20,22 +20,12 @@ package tags import ( - "regexp" - "strings" - "github.com/ZaparooProject/go-zapscript" ) // This tag system is inspired by the GameDataBase project's hierarchical // tag taxonomy. Reference: https://github.com/PigSaint/GameDataBase/blob/main/tags.yml -// Package-level compiled regexes for tag normalization. -// These are compiled once at initialization for optimal performance. -var ( - reColonSpacing = regexp.MustCompile(`\s*:\s*`) - reSpecialChars = regexp.MustCompile(`[^a-z0-9:,+\-]`) -) - // TagType represents a top-level tag category type TagType string @@ -134,41 +124,8 @@ const ( // for simplicity, but the taxonomy and tag values are directly inspired by their work. // NormalizeTag normalizes a tag string for consistent querying and storage. -// Applied to BOTH type and value parts separately. -// Rules: trim whitespace, normalize colon spacing, lowercase, spaces→dashes, -// periods→dashes, and remove special chars (except colon, dash, and comma) -func NormalizeTag(s string) string { - // 1. Trim whitespace - s = strings.TrimSpace(s) - - // 2. Normalize colon spacing - remove spaces around colons first - s = reColonSpacing.ReplaceAllString(s, ":") - - // 3. Convert to lowercase - s = strings.ToLower(s) - - // 4. Replace remaining spaces with dashes - s = strings.ReplaceAll(s, " ", "-") - - // 5. Convert periods to dashes (for version numbers like "1.2.3" → "1-2-3") - s = strings.ReplaceAll(s, ".", "-") - - // 6. Remove other special chars (except colon, dash, and comma) - // Keep: a-z, 0-9, dash, colon, comma - s = reSpecialChars.ReplaceAllString(s, "") - - return s -} - -// NormalizeTagFilter normalizes a TagFilter for consistent querying. -// Applies normalization to both Type and Value fields. -func NormalizeTagFilter(filter zapscript.TagFilter) zapscript.TagFilter { - return zapscript.TagFilter{ - Type: NormalizeTag(filter.Type), - Value: NormalizeTag(filter.Value), - Operator: filter.Operator, - } -} +// Delegates to go-zapscript's implementation. +var NormalizeTag = zapscript.NormalizeTag var CanonicalTagDefinitions = map[TagType][]TagValue{ TagTypeInput: { diff --git a/pkg/zapscript/advargs/advargs_test.go b/pkg/zapscript/advargs/advargs_test.go index 249a808a..adf086ae 100644 --- a/pkg/zapscript/advargs/advargs_test.go +++ b/pkg/zapscript/advargs/advargs_test.go @@ -74,34 +74,6 @@ func TestParse_GlobalArgs(t *testing.T) { } } -func TestGlobalArgs_ShouldRun(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - when string - want bool - }{ - {name: "empty when", when: "", want: true}, - {name: "true", when: "true", want: true}, - {name: "yes", when: "yes", want: true}, - {name: "false", when: "false", want: false}, - {name: "no", when: "no", want: false}, - // IsTruthy only accepts "true" and "yes", all other values are falsey - {name: "1 is falsey", when: "1", want: false}, - {name: "0 is falsey", when: "0", want: false}, - {name: "random string is falsey", when: "random", want: false}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - args := zapscript.GlobalArgs{When: tt.when} - assert.Equal(t, tt.want, ShouldRun(args)) - }) - } -} - func TestParse_LaunchRandomArgs(t *testing.T) { t.Parallel() diff --git a/pkg/zapscript/advargs/helpers.go b/pkg/zapscript/advargs/helpers.go deleted file mode 100644 index d9f75775..00000000 --- a/pkg/zapscript/advargs/helpers.go +++ /dev/null @@ -1,39 +0,0 @@ -// Zaparoo Core -// Copyright (c) 2026 The Zaparoo Project Contributors. -// SPDX-License-Identifier: GPL-3.0-or-later -// -// This file is part of Zaparoo Core. -// -// Zaparoo Core is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Zaparoo Core is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Zaparoo Core. If not, see . - -package advargs - -import ( - "github.com/ZaparooProject/go-zapscript" -) - -// IsActionDetails returns true if action is "details" (case-insensitive). -func IsActionDetails(action string) bool { - return zapscript.IsActionDetails(action) -} - -// IsActionRun returns true if action is "run" or empty (case-insensitive). -func IsActionRun(action string) bool { - return zapscript.IsActionRun(action) -} - -// IsModeShuffle returns true if mode is "shuffle" (case-insensitive). -func IsModeShuffle(mode string) bool { - return zapscript.IsModeShuffle(mode) -} diff --git a/pkg/zapscript/advargs/helpers_test.go b/pkg/zapscript/advargs/helpers_test.go deleted file mode 100644 index b9dbc503..00000000 --- a/pkg/zapscript/advargs/helpers_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Zaparoo Core -// Copyright (c) 2026 The Zaparoo Project Contributors. -// SPDX-License-Identifier: GPL-3.0-or-later -// -// This file is part of Zaparoo Core. -// -// Zaparoo Core is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Zaparoo Core is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Zaparoo Core. If not, see . - -package advargs - -import ( - "testing" - - "github.com/ZaparooProject/go-zapscript" - "github.com/stretchr/testify/assert" -) - -func TestIsActionDetails(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - action string - want bool - }{ - {name: "exact match lowercase", action: "details", want: true}, - {name: "exact match uppercase", action: "DETAILS", want: true}, - {name: "exact match mixed case", action: "Details", want: true}, - {name: "run action", action: "run", want: false}, - {name: "empty string", action: "", want: false}, - {name: "similar but wrong", action: "detail", want: false}, - {name: "whitespace", action: " details ", want: false}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got := IsActionDetails(tt.action) - assert.Equal(t, tt.want, got) - }) - } -} - -func TestIsActionRun(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - action string - want bool - }{ - {name: "exact match lowercase", action: "run", want: true}, - {name: "exact match uppercase", action: "RUN", want: true}, - {name: "exact match mixed case", action: "Run", want: true}, - {name: "empty string is run", action: "", want: true}, - {name: "details action", action: "details", want: false}, - {name: "similar but wrong", action: "running", want: false}, - {name: "whitespace", action: " run ", want: false}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got := IsActionRun(tt.action) - assert.Equal(t, tt.want, got) - }) - } -} - -func TestIsModeShuffle(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - mode string - want bool - }{ - {name: "exact match lowercase", mode: "shuffle", want: true}, - {name: "exact match uppercase", mode: "SHUFFLE", want: true}, - {name: "exact match mixed case", mode: "Shuffle", want: true}, - {name: "empty string", mode: "", want: false}, - {name: "similar but wrong", mode: "shuffled", want: false}, - {name: "whitespace", mode: " shuffle ", want: false}, - {name: "sequential mode", mode: "sequential", want: false}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - got := IsModeShuffle(tt.mode) - assert.Equal(t, tt.want, got) - }) - } -} - -// TestShouldRun_EmptyWhen verifies that empty When condition means command should run. -func TestShouldRun_EmptyWhen(t *testing.T) { - t.Parallel() - - args := zapscript.GlobalArgs{When: ""} - assert.True(t, ShouldRun(args)) -} diff --git a/pkg/zapscript/advargs/parse.go b/pkg/zapscript/advargs/parse.go index e758fd5b..ca650a3c 100644 --- a/pkg/zapscript/advargs/parse.go +++ b/pkg/zapscript/advargs/parse.go @@ -29,7 +29,6 @@ import ( "github.com/ZaparooProject/go-zapscript" "github.com/ZaparooProject/zaparoo-core/v2/pkg/database/filters" "github.com/ZaparooProject/zaparoo-core/v2/pkg/database/systemdefs" - "github.com/ZaparooProject/zaparoo-core/v2/pkg/helpers" "github.com/go-playground/validator/v10" "github.com/go-viper/mapstructure/v2" ) @@ -155,14 +154,6 @@ func stringToTagFiltersHook() mapstructure.DecodeHookFunc { } } -// ShouldRun returns true if the command should execute based on the When condition. -func ShouldRun(g zapscript.GlobalArgs) bool { - if g.When == "" { - return true - } - return helpers.IsTruthy(g.When) -} - // validateLauncher checks if a launcher ID exists in the available launchers. // Comparison is case-insensitive since launcher IDs are user-facing identifiers. func validateLauncher(ctx context.Context, fl validator.FieldLevel) bool {