Skip to content

Commit fcb478a

Browse files
authored
chore: refactor include/exclude config (#15)
1 parent 887f053 commit fcb478a

File tree

3 files changed

+57
-51
lines changed

3 files changed

+57
-51
lines changed

cmd/magonote/config.go

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
type Config struct {
1111
Core CoreConfig `toml:"core"`
12-
Regexp RegexpConfig `toml:"regexp"`
12+
Rules RulesConfig `toml:"rules"`
1313
Colors ColorConfig `toml:"colors"`
1414
Plugins PluginsConfig `toml:"plugins"`
1515
}
@@ -24,8 +24,16 @@ type CoreConfig struct {
2424
Contrast bool `toml:"contrast"`
2525
}
2626

27-
type RegexpConfig struct {
28-
Patterns []string `toml:"patterns"`
27+
// RulesConfig unifies user-defined include (match) and exclude (filter) rules
28+
// Both include and exclude carry a "rules" list with items of the same shape: { type, pattern }
29+
type RulesConfig struct {
30+
Include RulesList `toml:"include"`
31+
Exclude RulesList `toml:"exclude"`
32+
}
33+
34+
// RulesList groups a list of rules under a section
35+
type RulesList struct {
36+
Rules []Rule `toml:"rules"`
2937
}
3038

3139
type ColorGroup struct {
@@ -51,20 +59,15 @@ type ColorDetectionPluginConfig struct {
5159
Enabled bool `toml:"enabled"`
5260
}
5361

54-
type ExclusionRule struct {
62+
// Rule describes a single rule item used in include/exclude lists
63+
type Rule struct {
5564
Type string `toml:"type"` // "regex" or "text"
5665
Pattern string `toml:"pattern"` // The pattern or text to exclude
5766
}
5867

59-
type ExclusionConfig struct {
60-
Enabled bool `toml:"enabled"`
61-
Rules []ExclusionRule `toml:"rules"`
62-
}
63-
6468
type PluginsConfig struct {
6569
Tabledetection *TableDetectionPluginConfig `toml:"tabledetection"`
6670
Colordetection *ColorDetectionPluginConfig `toml:"colordetection"`
67-
Exclusion *ExclusionConfig `toml:"exclusion"`
6871
}
6972

7073
func NewDefaultConfig() *Config {
@@ -78,9 +81,7 @@ func NewDefaultConfig() *Config {
7881
UniqueLevel: 0,
7982
Contrast: false,
8083
},
81-
Regexp: RegexpConfig{
82-
Patterns: []string{},
83-
},
84+
Rules: RulesConfig{Include: RulesList{Rules: []Rule{}}, Exclude: RulesList{Rules: []Rule{}}},
8485
Colors: ColorConfig{
8586
Match: ColorGroup{
8687
Foreground: "green",
@@ -102,7 +103,6 @@ func NewDefaultConfig() *Config {
102103
Plugins: PluginsConfig{
103104
Tabledetection: nil,
104105
Colordetection: nil,
105-
Exclusion: nil,
106106
},
107107
}
108108
}
@@ -117,6 +117,5 @@ func LoadConfigFromFile(path string) (*Config, error) {
117117
if _, err := toml.DecodeFile(path, config); err != nil {
118118
return nil, fmt.Errorf("failed to decode TOML config: %w", err)
119119
}
120-
121120
return config, nil
122121
}

cmd/magonote/main.go

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os"
99
"os/exec"
1010
"path/filepath"
11+
"regexp"
1112
"runtime/debug"
1213
"strings"
1314

@@ -232,7 +233,11 @@ func applyCliOverrides(cmd *cobra.Command, config *Config, args *Arguments) {
232233
}
233234

234235
if len(args.regexpPatterns) > 0 {
235-
config.Regexp.Patterns = args.regexpPatterns
236+
// CLI `--regexp` only accepts regex strings, map them into include rules
237+
config.Rules.Include.Rules = make([]Rule, 0, len(args.regexpPatterns))
238+
for _, p := range args.regexpPatterns {
239+
config.Rules.Include.Rules = append(config.Rules.Include.Rules, Rule{Type: "regex", Pattern: p})
240+
}
236241
}
237242

238243
if cmd.Flags().Changed("fg-color") {
@@ -275,17 +280,14 @@ func applyCliOverrides(cmd *cobra.Command, config *Config, args *Arguments) {
275280

276281
// Handle extra exclusion patterns from CLI
277282
if len(args.extraExclusion) > 0 {
278-
if config.Plugins.Exclusion == nil {
279-
config.Plugins.Exclusion = &ExclusionConfig{Enabled: true, Rules: []ExclusionRule{}}
280-
}
281-
// Add CLI exclusion patterns as text rules
283+
// Add CLI exclusion patterns as regex rules into unified rules.exclude
282284
for _, pattern := range args.extraExclusion {
283-
config.Plugins.Exclusion.Rules = append(config.Plugins.Exclusion.Rules, ExclusionRule{
284-
Type: "text",
285-
Pattern: pattern,
286-
})
285+
if _, err := regexp.Compile(pattern); err != nil {
286+
slog.Warn("Invalid regex in --extra-exclusion; skipping", "pattern", pattern, "error", err)
287+
continue
288+
}
289+
config.Rules.Exclude.Rules = append(config.Rules.Exclude.Rules, Rule{Type: "regex", Pattern: pattern})
287290
}
288-
config.Plugins.Exclusion.Enabled = true
289291
}
290292
}
291293

@@ -297,7 +299,14 @@ func runApp(config *Config, args *Arguments) error {
297299
return err
298300
}
299301

300-
state := internal.NewState(text, config.Core.Alphabet, config.Regexp.Patterns)
302+
// Convert include rules to regex patterns list
303+
var includePatterns []string
304+
for _, r := range config.Rules.Include.Rules {
305+
if r.Type == "regex" && r.Pattern != "" {
306+
includePatterns = append(includePatterns, r.Pattern)
307+
}
308+
}
309+
state := internal.NewState(text, config.Core.Alphabet, includePatterns)
301310

302311
plugins := config.Plugins
303312
if plugins.Tabledetection != nil && plugins.Tabledetection.Enabled {
@@ -312,14 +321,11 @@ func runApp(config *Config, args *Arguments) error {
312321
state.ColorDetectionConfig = internal.NewColorDetectionConfig()
313322
}
314323

315-
if plugins.Exclusion != nil && plugins.Exclusion.Enabled {
316-
// Convert config exclusion rules to internal exclusion rules
324+
// Apply user-defined exclusion rules (unified rules section)
325+
if len(config.Rules.Exclude.Rules) > 0 {
317326
var rules []internal.ExclusionRule
318-
for _, rule := range plugins.Exclusion.Rules {
319-
rules = append(rules, internal.ExclusionRule{
320-
Type: rule.Type,
321-
Pattern: rule.Pattern,
322-
})
327+
for _, rule := range config.Rules.Exclude.Rules {
328+
rules = append(rules, internal.ExclusionRule{Type: rule.Type, Pattern: rule.Pattern})
323329
}
324330
state.ExclusionConfig = internal.NewExclusionConfig(rules)
325331
}
@@ -446,7 +452,7 @@ func main() {
446452
rootCmd.Flags().StringVarP(&args.target, "target", "t", "", "Stores the hint in the specified path")
447453
rootCmd.Flags().StringVarP(&args.inputFile, "input-file", "i", "", "Read input from file instead of stdin")
448454
rootCmd.Flags().BoolVarP(&args.showVersion, "version", "v", false, "Print version and exit")
449-
rootCmd.Flags().StringArrayVar(&args.extraExclusion, "extra-exclusion", nil, "Additional text patterns to exclude from matching")
455+
rootCmd.Flags().StringArrayVar(&args.extraExclusion, "extra-exclusion", nil, "Additional regex patterns to exclude from matching")
450456

451457
rootCmd.Flags().BoolVar(&args.listView, "list", false, "Enable list view")
452458

config.example.toml

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ alphabet = "qwerty"
88
# Output format for the picked hint (%H = hint text, %U = uppercase flag)
99
format = "%H"
1010

11-
# Hint position: "left" or "right"
11+
# Hint position: "left", "right", "off_left", or "off_right"
1212
position = "left"
1313

1414
# Enable multi-selection mode
@@ -23,12 +23,14 @@ unique_level = 0
2323
# Put square brackets around hint for visibility
2424
contrast = false
2525

26-
[regexp]
27-
# Additional regex patterns to match
28-
patterns = [
29-
# Example patterns (uncomment to use)
30-
# "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b", # Email
31-
# "\\bhttps?://[\\w.-]+\\b", # URL
26+
[rules]
27+
# User-defined matching and filtering rules
28+
29+
[rules.include]
30+
# Additional rules to match. Only { type = "regex" } is honored here.
31+
rules = [
32+
# { type = "regex", pattern = "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b" }, # Email
33+
# { type = "regex", pattern = "\\bhttps?://[\\w.-]+\\b" }, # URL
3234
]
3335

3436
[colors.match]
@@ -64,23 +66,22 @@ confidence_threshold = 0.8
6466
[plugins.colordetection]
6567
enabled = true
6668

67-
[plugins.exclusion]
68-
enabled = false
69+
[rules.exclude]
6970
# Exclusion rules to filter out unwanted matches by defining regions in the original text
7071
# The rules first identify exclusion regions in the input text, then filter out any matches
7172
# whose coordinates overlap with these regions
7273
rules = [
73-
# Example: Exclude entire shell prompt lines (automatically configured by tmux integration)
74-
# { type = "regex", pattern = "^user@hostname:.*\\$ " }, # Exclude entire lines starting with prompt
75-
# { type = "text", pattern = "~/project$ " }, # Exclude specific prompt text
74+
# Example: Exclude entire shell prompt lines
75+
# { type = "regex", pattern = "^user@hostname:.*\\$ " }, # Lines starting with prompt
76+
# { type = "text", pattern = "~/project$ " }, # Specific prompt fragment
7677

7778
# Additional examples:
78-
# { type = "text", pattern = "DEBUG" }, # Exclude matches in regions containing "DEBUG"
79-
# { type = "regex", pattern = "^\\[.*\\]\\$ " }, # Exclude bracketed prompts like "[user@host]$ "
80-
# { type = "regex", pattern = "^\\d{4}-\\d{2}-\\d{2}" }, # Exclude regions starting with dates
81-
# { type = "regex", pattern = "Error:.*" }, # Exclude entire error message lines
79+
# { type = "text", pattern = "DEBUG" }, # Regions containing "DEBUG"
80+
# { type = "regex", pattern = "^\\[.*\\]\\$ " }, # Bracketed prompts like "[user@host]$ "
81+
# { type = "regex", pattern = "^\\d{4}-\\d{2}-\\d{2}" }, # Lines starting with dates
82+
# { type = "regex", pattern = "Error:.*" }, # Entire error message lines
8283

8384
# Exclude log timestamps and noise:
84-
# { type = "regex", pattern = "^\\d{2}:\\d{2}:\\d{2}" }, # Lines starting with timestamps
85+
# { type = "regex", pattern = "^\\d{2}:\\d{2}:\\d{2}" }, # Timestamps like 12:34:56
8586
# { type = "text", pattern = "INFO" }, # Any region containing INFO logs
8687
]

0 commit comments

Comments
 (0)