diff --git a/.gitignore b/.gitignore index 2905c9c..3af37cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Compiled Binaries, Executables, and Libraries +meshexec *.exe *.exe~ *.dll diff --git a/internal/targeting/evaluator.go b/internal/targeting/evaluator.go index d538709..e7bb22b 100644 --- a/internal/targeting/evaluator.go +++ b/internal/targeting/evaluator.go @@ -431,16 +431,29 @@ func (e *Evaluator) evaluateAST(ast *internal.TargetAST, device *internal.Device } } -// evaluateCondition evaluates a single condition against device information +// evaluateCondition evaluates a single condition against device information. +// Supports device attributes: name, role, os, arch, and custom tags. +// Comparisons are case-insensitive for better usability. +// Returns false (not error) when tags don't exist to support negative matching. func (e *Evaluator) evaluateCondition(condition string, device *internal.DeviceInfo) (bool, error) { parts := strings.SplitN(condition, "=", 2) if len(parts) != 2 { - return false, fmt.Errorf("invalid condition format: %s", condition) + return false, fmt.Errorf("invalid condition format: %s (expected 'attribute=value')", condition) } attribute := strings.TrimSpace(parts[0]) value := strings.TrimSpace(parts[1]) + // Validate attribute name + if attribute == "" { + return false, fmt.Errorf("attribute cannot be empty") + } + + // Validate value + if value == "" { + return false, fmt.Errorf("invalid condition format: %s (value cannot be empty)", condition) + } + // Remove quotes from value if present if len(value) >= 2 && (value[0] == '"' && value[len(value)-1] == '"') { value = value[1 : len(value)-1] diff --git a/internal/tui/model.go b/internal/tui/model.go index 0a08235..abc9224 100644 --- a/internal/tui/model.go +++ b/internal/tui/model.go @@ -25,6 +25,21 @@ const ( tabCommands ) +// Output preview settings +const ( + maxOutputPreviewLength = 30 + outputTruncateSuffix = "..." + outputTruncateLength = maxOutputPreviewLength - len(outputTruncateSuffix) +) + +// Table formatting settings for results view +const ( + deviceColumnWidth = 9 + statusColumnWidth = 6 + exitCodeColumnWidth = 4 + durationColumnWidth = 8 +) + // simple peer list placeholder compatible with tests type peerListModel struct { items []interface{} @@ -492,12 +507,16 @@ func (m *model) renderResults() string { if output == "" { output = result.Stderr } - if len(output) > 30 { - output = output[:27] + "..." + if len(output) > maxOutputPreviewLength { + output = output[:outputTruncateLength] + outputTruncateSuffix } - row := fmt.Sprintf("│ %-9s │ %-6s │ %-4d │ %-8d │ %s", - result.Device, status, result.ExitCode, result.Duration, output) + row := fmt.Sprintf("│ %-*s │ %-*s │ %-*d │ %-*d │ %s", + deviceColumnWidth, result.Device, + statusColumnWidth, status, + exitCodeColumnWidth, result.ExitCode, + durationColumnWidth, result.Duration, + output) rows = append(rows, row) }