com.wallstop-studios.dxmessaging 2.1.5 → 2.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.artifacts/SourceGenerators.Tests/obj/Debug/net9.0/WallstopStudios.DxMessaging.SourceGenerators.Tests.AssemblyInfo.cs +1 -1
- package/.cspell.json +4 -1
- package/.github/workflows/actionlint.yml +11 -1
- package/.github/workflows/csharpier-autofix.yml +34 -3
- package/.github/workflows/dotnet-tests.yml +13 -0
- package/.github/workflows/format-on-demand.yml +38 -44
- package/.github/workflows/json-format-check.yml +24 -0
- package/.github/workflows/lint-doc-links.yml +13 -0
- package/.github/workflows/markdown-json.yml +21 -4
- package/.github/workflows/markdown-link-text-check.yml +10 -0
- package/.github/workflows/markdown-link-validity.yml +10 -0
- package/.github/workflows/markdownlint.yml +7 -5
- package/.github/workflows/prettier-autofix.yml +67 -11
- package/.github/workflows/release-drafter.yml +2 -2
- package/.github/workflows/sync-wiki.yml +3 -3
- package/.github/workflows/yaml-format-lint.yml +26 -0
- package/.llm/context.md +113 -3
- package/.llm/skills/documentation/changelog-management.md +38 -0
- package/.llm/skills/documentation/documentation-style-guide.md +18 -0
- package/.llm/skills/documentation/documentation-update-workflow.md +2 -0
- package/.llm/skills/documentation/documentation-updates.md +2 -0
- package/.llm/skills/documentation/markdown-compatibility.md +476 -0
- package/.llm/skills/documentation/mermaid-theming.md +326 -0
- package/.llm/skills/documentation/mkdocs-navigation.md +290 -0
- package/.llm/skills/github-actions/git-renormalize-patterns.md +231 -0
- package/.llm/skills/github-actions/workflow-consistency.md +346 -0
- package/.llm/skills/index.md +53 -27
- package/.llm/skills/scripting/javascript-code-quality.md +417 -0
- package/.llm/skills/scripting/regex-documentation.md +461 -0
- package/.llm/skills/scripting/shell-best-practices.md +55 -4
- package/.llm/skills/scripting/validation-patterns.md +418 -0
- package/.llm/skills/specification.md +4 -1
- package/.llm/skills/testing/test-code-quality.md +243 -0
- package/.llm/skills/testing/test-production-code.md +348 -0
- package/CHANGELOG.md +24 -0
- package/README.md +113 -24
- package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +1 -6
- package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +1 -1
- package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +1 -1
- package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +1 -1
- package/coverage/clover.xml +216 -3
- package/coverage/clover.xml.meta +7 -7
- package/coverage/coverage-final.json +2 -1
- package/coverage/coverage-final.json.meta +7 -7
- package/coverage/lcov-report/base.css.meta +1 -1
- package/coverage/lcov-report/block-navigation.js.meta +1 -1
- package/coverage/lcov-report/favicon.png.meta +1 -1
- package/coverage/lcov-report/index.html +25 -10
- package/coverage/lcov-report/index.html.meta +7 -7
- package/coverage/lcov-report/prettify.css.meta +1 -1
- package/coverage/lcov-report/prettify.js.meta +1 -1
- package/coverage/lcov-report/sort-arrow-sprite.png.meta +1 -1
- package/coverage/lcov-report/sorter.js.meta +1 -1
- package/coverage/lcov-report/transform-docs-to-wiki.js.html +1 -1
- package/coverage/lcov-report/transform-docs-to-wiki.js.html.meta +7 -7
- package/coverage/lcov-report/vendor.meta +1 -1
- package/coverage/lcov-report.meta +8 -8
- package/coverage/lcov.info +365 -0
- package/coverage/lcov.info.meta +7 -7
- package/docs/architecture/design-and-architecture.md +0 -1
- package/docs/concepts/index.md +37 -0
- package/docs/concepts/index.md.meta +7 -0
- package/docs/concepts/interceptors-and-ordering.md +0 -2
- package/docs/concepts/mental-model.md +390 -0
- package/docs/concepts/mental-model.md.meta +7 -0
- package/docs/concepts/message-types.md +0 -1
- package/docs/getting-started/getting-started.md +1 -0
- package/docs/getting-started/index.md +6 -5
- package/docs/getting-started/overview.md +1 -0
- package/docs/getting-started/quick-start.md +2 -1
- package/docs/getting-started/visual-guide.md +4 -10
- package/docs/hooks.py +10 -1
- package/docs/images/DxMessaging-banner.svg +1 -1
- package/docs/index.md +7 -7
- package/docs/javascripts/mermaid-config.js +44 -4
- package/docs/reference/helpers.md +130 -154
- package/docs/reference/quick-reference.md +5 -1
- package/docs/reference/reference.md +124 -130
- package/mkdocs.yml +2 -0
- package/package.json +7 -2
- package/scripts/__tests__/generate-skills-index.test.js +397 -0
- package/scripts/__tests__/generate-skills-index.test.js.meta +7 -0
- package/scripts/__tests__/mermaid-config.test.js +467 -0
- package/scripts/__tests__/mermaid-config.test.js.meta +7 -0
- package/scripts/__tests__/validate-skills-optional-fields.test.js +1474 -0
- package/scripts/__tests__/validate-skills-optional-fields.test.js.meta +7 -0
- package/scripts/__tests__/validate-skills-required-fields.test.js +188 -0
- package/scripts/__tests__/validate-skills-required-fields.test.js.meta +7 -0
- package/scripts/__tests__/validate-skills-tags.test.js +353 -0
- package/scripts/__tests__/validate-skills-tags.test.js.meta +7 -0
- package/scripts/__tests__/validate-workflows.test.js +188 -0
- package/scripts/__tests__/validate-workflows.test.js.meta +7 -0
- package/scripts/generate-skills-index.js +88 -3
- package/scripts/validate-skills.js +230 -30
- package/scripts/validate-workflows.js +272 -0
- package/scripts/validate-workflows.js.meta +7 -0
- package/scripts/wiki/generate-wiki-sidebar.js.meta +1 -8
- package/scripts/wiki/transform-docs-to-wiki.js.meta +1 -1
- package/site/404.html +1 -1
- package/site/advanced/emit-shorthands/index.html +2 -2
- package/site/advanced/message-bus-providers/index.html +2 -2
- package/site/advanced/registration-builders/index.html +2 -2
- package/site/advanced/runtime-configuration/index.html +2 -2
- package/site/advanced/string-messages/index.html +2 -2
- package/site/advanced.meta +1 -1
- package/site/architecture/comparisons/index.html +2 -2
- package/site/architecture/design-and-architecture/index.html +2 -2
- package/site/architecture/performance/index.html +1 -1
- package/site/architecture.meta +1 -1
- package/site/concepts/index.html +1 -0
- package/site/concepts/index.html.meta +7 -0
- package/site/concepts/interceptors-and-ordering/index.html +4 -4
- package/site/concepts/listening-patterns/index.html +2 -2
- package/site/concepts/mental-model/index.html +146 -0
- package/site/concepts/mental-model/index.html.meta +7 -0
- package/site/concepts/mental-model.meta +8 -0
- package/site/concepts/message-types/index.html +2 -2
- package/site/concepts/targeting-and-context/index.html +2 -2
- package/site/concepts.meta +1 -1
- package/site/examples/end-to-end/index.html +2 -2
- package/site/examples/end-to-end-scene-transitions/index.html +2 -2
- package/site/examples.meta +1 -1
- package/site/getting-started/getting-started/index.html +3 -3
- package/site/getting-started/index.html +4 -4
- package/site/getting-started/install/index.html +3 -3
- package/site/getting-started/overview/index.html +2 -2
- package/site/getting-started/quick-start/index.html +2 -2
- package/site/getting-started/visual-guide/index.html +11 -11
- package/site/getting-started.meta +1 -1
- package/site/guides/advanced/index.html +2 -2
- package/site/guides/diagnostics/index.html +2 -2
- package/site/guides/migration-guide/index.html +2 -2
- package/site/guides/patterns/index.html +2 -2
- package/site/guides/testing/index.html +2 -2
- package/site/guides/unity-integration/index.html +2 -2
- package/site/guides.meta +1 -1
- package/site/hooks.py.meta +1 -1
- package/site/images/DxMessaging-banner.svg +119 -0
- package/site/images/DxMessaging-banner.svg.meta +7 -0
- package/site/images.meta +8 -0
- package/site/index.html +2 -2
- package/site/integrations/index.html +2 -2
- package/site/integrations/reflex/index.html +2 -2
- package/site/integrations/vcontainer/index.html +2 -2
- package/site/integrations/zenject/index.html +2 -2
- package/site/integrations.meta +1 -1
- package/site/javascripts/csharp-highlight.js.meta +7 -7
- package/site/javascripts/mermaid-config.js +4 -1
- package/site/javascripts/mermaid-config.js.meta +1 -1
- package/site/javascripts.meta +1 -1
- package/site/reference/compatibility/index.html +1 -1
- package/site/reference/faq/index.html +1 -1
- package/site/reference/glossary/index.html +2 -2
- package/site/reference/helpers/index.html +15 -15
- package/site/reference/quick-reference/index.html +3 -3
- package/site/reference/reference/index.html +37 -37
- package/site/reference/troubleshooting/index.html +1 -1
- package/site/reference.meta +1 -1
- package/site/search/search_index.json +1 -1
- package/site/sitemap.xml +46 -38
- package/site/sitemap.xml.gz +0 -0
- package/site/stylesheets/extra.css.meta +1 -1
- package/site/stylesheets.meta +1 -1
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Regex Pattern Documentation"
|
|
3
|
+
id: "regex-documentation"
|
|
4
|
+
category: "scripting"
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
created: "2026-01-29"
|
|
7
|
+
updated: "2026-01-29"
|
|
8
|
+
|
|
9
|
+
source:
|
|
10
|
+
repository: "wallstop/DxMessaging"
|
|
11
|
+
files:
|
|
12
|
+
- path: "scripts/"
|
|
13
|
+
- path: "docs/"
|
|
14
|
+
url: "https://github.com/wallstop/DxMessaging"
|
|
15
|
+
|
|
16
|
+
tags:
|
|
17
|
+
- "regex"
|
|
18
|
+
- "documentation"
|
|
19
|
+
- "scripting"
|
|
20
|
+
- "patterns"
|
|
21
|
+
- "comments"
|
|
22
|
+
- "maintenance"
|
|
23
|
+
|
|
24
|
+
complexity:
|
|
25
|
+
level: "intermediate"
|
|
26
|
+
reasoning: "Requires regex knowledge to understand flag behaviors and documentation implications"
|
|
27
|
+
|
|
28
|
+
impact:
|
|
29
|
+
performance:
|
|
30
|
+
rating: "none"
|
|
31
|
+
details: "Documentation only; no runtime performance impact"
|
|
32
|
+
maintainability:
|
|
33
|
+
rating: "high"
|
|
34
|
+
details: "Improves code clarity and prevents maintenance bugs from misleading comments"
|
|
35
|
+
testability:
|
|
36
|
+
rating: "medium"
|
|
37
|
+
details: "Helps verify regex behavior matches documented expectations"
|
|
38
|
+
|
|
39
|
+
prerequisites:
|
|
40
|
+
- "Basic regex syntax"
|
|
41
|
+
- "Understanding of regex flags"
|
|
42
|
+
|
|
43
|
+
dependencies:
|
|
44
|
+
packages: []
|
|
45
|
+
skills:
|
|
46
|
+
- "shell-best-practices"
|
|
47
|
+
|
|
48
|
+
applies_to:
|
|
49
|
+
languages:
|
|
50
|
+
- "JavaScript"
|
|
51
|
+
- "PowerShell"
|
|
52
|
+
- "C#"
|
|
53
|
+
- "Bash"
|
|
54
|
+
frameworks: []
|
|
55
|
+
versions: {}
|
|
56
|
+
|
|
57
|
+
aliases:
|
|
58
|
+
- "Regex comments"
|
|
59
|
+
- "Pattern documentation"
|
|
60
|
+
- "Regular expression documentation"
|
|
61
|
+
|
|
62
|
+
related:
|
|
63
|
+
- shell-best-practices
|
|
64
|
+
- cross-platform-compatibility
|
|
65
|
+
|
|
66
|
+
status: "stable"
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
# Regex Pattern Documentation
|
|
70
|
+
|
|
71
|
+
> **One-line summary**: Document regex patterns accurately by describing what they actually match,
|
|
72
|
+
> including all flag-dependent behavior.
|
|
73
|
+
|
|
74
|
+
## Overview
|
|
75
|
+
|
|
76
|
+
This skill covers best practices for documenting regular expression patterns. Accurate comments are critical because regex behavior changes dramatically based on flags, and misleading comments cause maintenance bugs. Many subtle bugs arise when comments describe intended behavior rather than actual behavior.
|
|
77
|
+
|
|
78
|
+
## Solution
|
|
79
|
+
|
|
80
|
+
1. **Describe actual behavior** - Comments must answer "What will this pattern match?" not "What do I hope it matches?"
|
|
81
|
+
1. **Document flag effects** - Global, case-insensitive, multiline, and dotall flags change matching behavior significantly
|
|
82
|
+
1. **Use precise language** - Say "matches all occurrences" (global) vs "matches first occurrence" (non-global)
|
|
83
|
+
1. **Include character class details** - Specify whether patterns match Unicode, newlines, or specific character ranges
|
|
84
|
+
|
|
85
|
+
## Core Principle
|
|
86
|
+
|
|
87
|
+
### Comments must describe actual behavior, not intended behavior
|
|
88
|
+
|
|
89
|
+
A regex comment should answer: "What will this pattern actually match?" not "What do I hope it matches?"
|
|
90
|
+
|
|
91
|
+
## Whitespace Character Classes
|
|
92
|
+
|
|
93
|
+
### `\s` vs `[ \t]` - A Critical Distinction
|
|
94
|
+
|
|
95
|
+
The `\s` shorthand matches **all whitespace characters including newlines**. This is a frequent source of bugs when you only want to match spaces and tabs.
|
|
96
|
+
|
|
97
|
+
| Pattern | Matches | Use When |
|
|
98
|
+
| ----------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
99
|
+
| `\s` | Space, tab, newline (`\n`), carriage return (`\r`), form feed, vertical tab | You want to match ANY whitespace including line breaks |
|
|
100
|
+
| `[ \t]` | Only space and tab | You want horizontal whitespace only, preserving newlines |
|
|
101
|
+
| `[\r\n]` | Only newline characters | You want to match line breaks specifically |
|
|
102
|
+
| `[^\S\r\n]` | Whitespace except newlines (double negative trick) | Alternative to `[ \t]` that includes other horizontal whitespace |
|
|
103
|
+
|
|
104
|
+
#### Wrong Pattern
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
// WRONG: \s* consumes newlines, concatenating lines when replaced
|
|
108
|
+
const DIRECTIVE_PATTERN = /^%%\{init:.*?\}%%\s*/gm;
|
|
109
|
+
// Intended: Strip directive and trailing spaces
|
|
110
|
+
// Actual: Also consumes the newline, joining this line with the next
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Correct Pattern
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
// CORRECT: [ \t]* only matches horizontal whitespace
|
|
117
|
+
const DIRECTIVE_PATTERN = /^[ \t]*%%\{init:.*?\}%%[ \t]*\r?\n?/gm;
|
|
118
|
+
// Strips directive, surrounding spaces/tabs, and just its own line ending
|
|
119
|
+
// Preserves separation between other lines
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### Practical Impact
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const text = "line1\n%%{init:...}%%\nline2";
|
|
126
|
+
|
|
127
|
+
// Bug: \s* consumes the newline AFTER the directive
|
|
128
|
+
text.replace(/%%\{init:.*?\}%%\s*/g, "");
|
|
129
|
+
// Result: "line1\nline2" with missing newline before line2
|
|
130
|
+
|
|
131
|
+
// Fixed: [ \t]* preserves newlines
|
|
132
|
+
text.replace(/%%\{init:.*?\}%%[ \t]*/g, "");
|
|
133
|
+
// Result: "line1\n\nline2" - newlines preserved
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Flag Reference Table
|
|
137
|
+
|
|
138
|
+
| Flag | Name | Effect | Comment Implications |
|
|
139
|
+
| ---- | -------------------- | --------------------------------------------------------- | --------------------------------------------------------------- |
|
|
140
|
+
| `g` | Global | Match all occurrences, not just the first | Comments must use plural ("matches all X" not "matches X") |
|
|
141
|
+
| `i` | Case-insensitive | `[A-Za-z]` matches regardless of case | Comments must mention "case-insensitive" explicitly |
|
|
142
|
+
| `m` | Multiline | `^` and `$` match start/end of each line, not just string | Comments must say "at start/end of any line" not "at start/end" |
|
|
143
|
+
| `s` | DotAll (Single-line) | `.` matches newline characters too | Comments must mention "including newlines" when using `.` |
|
|
144
|
+
| `u` | Unicode | Enables full Unicode support, `\p{}` escapes | Comments should note Unicode-aware matching if relevant |
|
|
145
|
+
|
|
146
|
+
## Flag-Specific Documentation Rules
|
|
147
|
+
|
|
148
|
+
### Global Flag (`g`)
|
|
149
|
+
|
|
150
|
+
The global flag changes whether a pattern finds one or all matches. Comments must reflect this.
|
|
151
|
+
|
|
152
|
+
#### Wrong Comments
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
// WRONG: Comment implies single match, but /g finds all
|
|
156
|
+
const pattern = /\d+/g;
|
|
157
|
+
// Matches a number in the string
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
// WRONG: Singular language with global flag
|
|
162
|
+
const emailPattern = /\w+@\w+\.\w+/g;
|
|
163
|
+
// Matches an email address
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### Correct Comments
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
// CORRECT: Plural language matches global behavior
|
|
170
|
+
const pattern = /\d+/g;
|
|
171
|
+
// Matches all numbers in the string
|
|
172
|
+
|
|
173
|
+
const emailPattern = /\w+@\w+\.\w+/g;
|
|
174
|
+
// Matches all email addresses in the string
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Multiline Flag (`m`)
|
|
178
|
+
|
|
179
|
+
The multiline flag changes the meaning of `^` and `$` anchors. This is one of the most commonly misdocumented behaviors.
|
|
180
|
+
|
|
181
|
+
#### Wrong Comments
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
// WRONG: Says "at start" but /m means "at start of ANY line"
|
|
185
|
+
const pattern = /^function/m;
|
|
186
|
+
// Matches 'function' at start of string
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
// WRONG: Omits multiline behavior entirely
|
|
191
|
+
const endPattern = /;$/m;
|
|
192
|
+
// Matches semicolon at end
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### Correct Comments
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
// CORRECT: Explicitly mentions line-level matching
|
|
199
|
+
const pattern = /^function/m;
|
|
200
|
+
// Matches 'function' at start of any line (not just string start)
|
|
201
|
+
|
|
202
|
+
const endPattern = /;$/m;
|
|
203
|
+
// Matches semicolon at end of any line (not just string end)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### Multiline Behavior Demonstration
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
const text = `line1
|
|
210
|
+
function test() {
|
|
211
|
+
return 42;
|
|
212
|
+
}`;
|
|
213
|
+
|
|
214
|
+
// Without /m flag: ^ only matches position 0
|
|
215
|
+
/^function/.test(text); // false - 'function' is not at string start
|
|
216
|
+
|
|
217
|
+
// With /m flag: ^ matches after every newline too
|
|
218
|
+
/^function/m.test(text); // true - 'function' is at start of line 2
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### DotAll Flag (`s`)
|
|
222
|
+
|
|
223
|
+
The DotAll flag makes `.` match newline characters. Without it, `.` matches any character except newlines.
|
|
224
|
+
|
|
225
|
+
#### Wrong Comments
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
// WRONG: Says "any character" but without /s, newlines are excluded
|
|
229
|
+
const pattern = /start.*end/;
|
|
230
|
+
// Matches 'start', then any characters, then 'end'
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
// WRONG: Implies newlines are matched when they're not
|
|
235
|
+
const blockPattern = /<div>.*<\/div>/;
|
|
236
|
+
// Matches everything between div tags
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Correct Comments
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
// CORRECT: Explicitly notes newline exclusion
|
|
243
|
+
const pattern = /start.*end/;
|
|
244
|
+
// Matches 'start', any characters EXCEPT newlines, then 'end'
|
|
245
|
+
|
|
246
|
+
// CORRECT: With /s flag, mentions newline inclusion
|
|
247
|
+
const multilinePattern = /start.*end/s;
|
|
248
|
+
// Matches 'start', any characters INCLUDING newlines, then 'end'
|
|
249
|
+
|
|
250
|
+
// CORRECT: Alternative using explicit character class
|
|
251
|
+
const explicitPattern = /start[\s\S]*end/;
|
|
252
|
+
// Matches 'start', any characters including newlines, then 'end'
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### DotAll Behavior Demonstration
|
|
256
|
+
|
|
257
|
+
```javascript
|
|
258
|
+
const text = `start
|
|
259
|
+
middle
|
|
260
|
+
end`;
|
|
261
|
+
|
|
262
|
+
// Without /s: . doesn't match newlines
|
|
263
|
+
/start.*end/.test(text); // false - can't cross newlines
|
|
264
|
+
|
|
265
|
+
// With /s: . matches everything including newlines
|
|
266
|
+
/start.*end/s.test(text); // true - matches across lines
|
|
267
|
+
|
|
268
|
+
// Alternative: [\s\S] matches any character including newlines
|
|
269
|
+
/start[\s\S]*end/.test(text); // true - explicit any-character class
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Case-Insensitive Flag (`i`)
|
|
273
|
+
|
|
274
|
+
#### Wrong Comments
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
// WRONG: Doesn't mention case-insensitivity
|
|
278
|
+
const pattern = /error/i;
|
|
279
|
+
// Matches 'error' in the string
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### Correct Comments
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
// CORRECT: Explicitly mentions case behavior
|
|
286
|
+
const pattern = /error/i;
|
|
287
|
+
// Matches 'error' case-insensitively (ERROR, Error, error, etc.)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Unicode Flag (`u`)
|
|
291
|
+
|
|
292
|
+
#### Wrong Comments
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
// WRONG: Doesn't explain Unicode implications
|
|
296
|
+
const emojiPattern = /\p{Emoji}/u;
|
|
297
|
+
// Matches emoji
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
#### Correct Comments
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
// CORRECT: Notes Unicode property escapes
|
|
304
|
+
const emojiPattern = /\p{Emoji}/u;
|
|
305
|
+
// Matches any Unicode emoji character (requires /u flag for \p{} syntax)
|
|
306
|
+
|
|
307
|
+
const letterPattern = /\p{Letter}+/gu;
|
|
308
|
+
// Matches all sequences of Unicode letters (any script, not just ASCII)
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Combined Flag Documentation
|
|
312
|
+
|
|
313
|
+
When patterns use multiple flags, document the combined effect.
|
|
314
|
+
|
|
315
|
+
### Wrong Comments
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
// WRONG: Doesn't explain combined behavior
|
|
319
|
+
const pattern = /^todo:/gim;
|
|
320
|
+
// Matches TODO markers
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Correct Comments
|
|
324
|
+
|
|
325
|
+
```javascript
|
|
326
|
+
// CORRECT: Documents each flag's contribution
|
|
327
|
+
const pattern = /^todo:/gim;
|
|
328
|
+
// Matches all 'todo:' markers at start of any line, case-insensitively
|
|
329
|
+
// - /g: finds all occurrences
|
|
330
|
+
// - /i: matches TODO, Todo, todo, etc.
|
|
331
|
+
// - /m: ^ matches start of each line, not just string start
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Anti-Patterns to Avoid
|
|
335
|
+
|
|
336
|
+
### 1. Copy-Paste Comments
|
|
337
|
+
|
|
338
|
+
Never copy comments from a similar regex without verifying accuracy.
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
// ANTI-PATTERN: Comment copied from non-global version
|
|
342
|
+
const pattern = /\bword\b/g;
|
|
343
|
+
// Matches 'word' as a whole word // WRONG: should say "all occurrences"
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### 2. Intent-Based Comments
|
|
347
|
+
|
|
348
|
+
Comments should describe behavior, not intent.
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
// ANTI-PATTERN: Describes intent, not behavior
|
|
352
|
+
const pattern = /^#.*/m;
|
|
353
|
+
// For matching comment lines // WRONG: doesn't explain what it actually does
|
|
354
|
+
|
|
355
|
+
// CORRECT: Describes actual matching behavior
|
|
356
|
+
const pattern = /^#.*/m;
|
|
357
|
+
// Matches lines starting with # (from # to end of line, on any line)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### 3. Incomplete Anchor Documentation
|
|
361
|
+
|
|
362
|
+
Always specify what anchors match in context.
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
// ANTI-PATTERN: Vague anchor description
|
|
366
|
+
const pattern = /^start/;
|
|
367
|
+
// Matches 'start' at the beginning
|
|
368
|
+
|
|
369
|
+
// CORRECT: Specific anchor behavior
|
|
370
|
+
const pattern = /^start/;
|
|
371
|
+
// Matches 'start' at string start only (not line start; no /m flag)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### 4. Omitting Quantifier Behavior
|
|
375
|
+
|
|
376
|
+
Document what quantifiers actually capture.
|
|
377
|
+
|
|
378
|
+
```javascript
|
|
379
|
+
// ANTI-PATTERN: Doesn't explain greedy vs lazy
|
|
380
|
+
const pattern = /".+"/;
|
|
381
|
+
// Matches quoted strings
|
|
382
|
+
|
|
383
|
+
// CORRECT: Explains greedy matching implications
|
|
384
|
+
const pattern = /".+"/;
|
|
385
|
+
// Matches from first " to LAST " (greedy); may span multiple quoted sections
|
|
386
|
+
// Use /"[^"]+"/g or /".+?"/g for individual quoted strings
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### 5. Ignoring Edge Cases
|
|
390
|
+
|
|
391
|
+
Document known limitations.
|
|
392
|
+
|
|
393
|
+
```javascript
|
|
394
|
+
// ANTI-PATTERN: No edge case documentation
|
|
395
|
+
const urlPattern = /https?:\/\/\S+/g;
|
|
396
|
+
// Matches URLs
|
|
397
|
+
|
|
398
|
+
// CORRECT: Documents limitations
|
|
399
|
+
const urlPattern = /https?:\/\/\S+/g;
|
|
400
|
+
// Matches all http/https URLs (simple pattern)
|
|
401
|
+
// Note: May include trailing punctuation; doesn't validate URL structure
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Validation Checklist
|
|
405
|
+
|
|
406
|
+
Before committing any regex pattern with comments, verify:
|
|
407
|
+
|
|
408
|
+
### Flag Verification
|
|
409
|
+
|
|
410
|
+
- [ ] **Global (`g`)**: Comments use plural forms ("all X" not "X")
|
|
411
|
+
- [ ] **Multiline (`m`)**: Comments say "any line" for `^` and `$` anchors
|
|
412
|
+
- [ ] **DotAll (`s`)**: Comments mention newline matching for `.`
|
|
413
|
+
- [ ] **Case-insensitive (`i`)**: Comments explicitly note case behavior
|
|
414
|
+
- [ ] **Unicode (`u`)**: Comments note Unicode-specific features if used
|
|
415
|
+
|
|
416
|
+
### Anchor Verification
|
|
417
|
+
|
|
418
|
+
- [ ] `^` comment specifies: string start, line start, or both (based on `/m`)
|
|
419
|
+
- [ ] `$` comment specifies: string end, line end, or both (based on `/m`)
|
|
420
|
+
- [ ] `\b` and `\B` behavior is correctly described
|
|
421
|
+
|
|
422
|
+
### Quantifier Verification
|
|
423
|
+
|
|
424
|
+
- [ ] Greedy vs lazy behavior is documented when it matters
|
|
425
|
+
- [ ] `*` vs `+` implications are clear (zero-or-more vs one-or-more)
|
|
426
|
+
|
|
427
|
+
### Behavioral Verification
|
|
428
|
+
|
|
429
|
+
- [ ] Comment describes actual behavior, not intended behavior
|
|
430
|
+
- [ ] Edge cases and limitations are documented
|
|
431
|
+
- [ ] Combined flag effects are explained
|
|
432
|
+
|
|
433
|
+
### Testing Verification
|
|
434
|
+
|
|
435
|
+
- [ ] Pattern has been tested with expected matches
|
|
436
|
+
- [ ] Pattern has been tested with expected non-matches
|
|
437
|
+
- [ ] Edge cases have been verified
|
|
438
|
+
|
|
439
|
+
## Language-Specific Notes
|
|
440
|
+
|
|
441
|
+
### JavaScript
|
|
442
|
+
|
|
443
|
+
- Use template literals for patterns with many escapes: ``new RegExp(`pattern`, 'flags')``
|
|
444
|
+
- Remember that string escaping doubles backslashes: `new RegExp('\\d+')` vs `/\d+/`
|
|
445
|
+
|
|
446
|
+
### Shell (grep, sed, awk)
|
|
447
|
+
|
|
448
|
+
- BRE (Basic Regular Expressions): `grep 'pattern'`
|
|
449
|
+
- ERE (Extended Regular Expressions): `grep -E 'pattern'`
|
|
450
|
+
- Different flag syntax: `-i` for case-insensitive, not `/i`
|
|
451
|
+
- See [Shell Best Practices](shell-best-practices.md) for grep-specific guidance
|
|
452
|
+
|
|
453
|
+
### Python
|
|
454
|
+
|
|
455
|
+
- Use raw strings: `r'\d+'` to avoid double-escaping
|
|
456
|
+
- `re.MULTILINE` corresponds to `/m`, `re.DOTALL` to `/s`
|
|
457
|
+
|
|
458
|
+
## See Also
|
|
459
|
+
|
|
460
|
+
- [Shell Best Practices](shell-best-practices.md) - grep pattern matching guidelines
|
|
461
|
+
- [Cross-Platform Compatibility](cross-platform-compatibility.md) - regex differences across platforms
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "Shell Scripting Best Practices"
|
|
3
3
|
id: "shell-best-practices"
|
|
4
4
|
category: "scripting"
|
|
5
|
-
version: "1.
|
|
5
|
+
version: "1.1.0"
|
|
6
6
|
created: "2026-01-28"
|
|
7
7
|
updated: "2026-01-28"
|
|
8
8
|
|
|
@@ -322,6 +322,56 @@ shellcheck scripts/*.sh
|
|
|
322
322
|
shellcheck .husky/*
|
|
323
323
|
```
|
|
324
324
|
|
|
325
|
+
## Avoid Redundant Pipe Patterns
|
|
326
|
+
|
|
327
|
+
### Problem: Unnecessary `head` with `grep -q`
|
|
328
|
+
|
|
329
|
+
The `grep -q` flag (quiet mode) already stops reading after the first match, making a preceding
|
|
330
|
+
`head` command redundant:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
# WRONG: head -1 is redundant when using grep -q
|
|
334
|
+
git ls-files "*.md" | head -1 | grep -q .
|
|
335
|
+
|
|
336
|
+
# WRONG: head -N with grep -q adds no value
|
|
337
|
+
some_command | head -5 | grep -q "pattern"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Solution: Use `grep -q` Alone
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
# CORRECT: grep -q already stops on first match
|
|
344
|
+
git ls-files "*.md" | grep -q .
|
|
345
|
+
|
|
346
|
+
# CORRECT: Use if/then for clarity in conditional logic
|
|
347
|
+
if git ls-files "*.$ext" "**/*.$ext" | grep -q .; then
|
|
348
|
+
git add --renormalize -- "*.$ext" "**/*.$ext"
|
|
349
|
+
fi
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Why `grep -q` Is Sufficient
|
|
353
|
+
|
|
354
|
+
The `-q` (quiet) flag has two behaviors:
|
|
355
|
+
|
|
356
|
+
1. **Suppresses output**: No matches are printed to stdout
|
|
357
|
+
1. **Exits immediately on first match**: Does not read remaining input
|
|
358
|
+
|
|
359
|
+
This means `grep -q` is inherently optimized for existence checks. Adding `head -1` before it:
|
|
360
|
+
|
|
361
|
+
- Adds a process fork overhead
|
|
362
|
+
- Provides no functional benefit
|
|
363
|
+
- Obscures the intent of the code
|
|
364
|
+
|
|
365
|
+
### When `head` IS Appropriate
|
|
366
|
+
|
|
367
|
+
Use `head` when you need to:
|
|
368
|
+
|
|
369
|
+
- **Limit display output**: `git log --oneline | head -10` (showing last 10 commits)
|
|
370
|
+
- **Process only first N lines**: `cat file.txt | head -100 | process_lines`
|
|
371
|
+
- **Debug/diagnose**: `some_command | head -5` (see first few lines of output)
|
|
372
|
+
|
|
373
|
+
But NOT when combined with `grep -q` for existence checks.
|
|
374
|
+
|
|
325
375
|
## See Also
|
|
326
376
|
|
|
327
377
|
- [PowerShell Best Practices](./powershell-best-practices.md) - Cross-language scripting patterns
|
|
@@ -330,6 +380,7 @@ shellcheck .husky/*
|
|
|
330
380
|
|
|
331
381
|
## Changelog
|
|
332
382
|
|
|
333
|
-
| Version | Date | Changes
|
|
334
|
-
| ------- | ---------- |
|
|
335
|
-
| 1.
|
|
383
|
+
| Version | Date | Changes |
|
|
384
|
+
| ------- | ---------- | ----------------------------------------------- |
|
|
385
|
+
| 1.1.0 | 2026-01-28 | Added redundant pipe patterns section (PR #150) |
|
|
386
|
+
| 1.0.0 | 2026-01-28 | Initial version from PR feedback cycle |
|