Skip to content

Commit 1eba9c8

Browse files
Add custom regex commands feature with named flag properties
Implements user-configurable regex-based string manipulation commands as requested in issue #73. Users can now define their own transformations using clear boolean flag properties instead of cryptic flag letters. Features: - Custom regex commands via VS Code settings - Named flag properties (global, ignoreCase, multiline, dotAll, unicode, sticky) - Real-time validation with helpful error messages - Dynamic command picker accessible via "String Manipulation: Custom Command" - Live previews of transformations - Multi-selection support - Integration with existing features (repeat last action, telemetry) Settings schema provides clear descriptions and autocompletion support. Documentation includes comprehensive examples and MDN RegExp flags reference. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 871962c commit 1eba9c8

File tree

7 files changed

+750
-0
lines changed

7 files changed

+750
-0
lines changed

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ This is a VSCode extension that provides string manipulation commands for text e
3333
- `increment-decrement.ts` - Number manipulation commands
3434
- `sequence.ts` - Number sequencing functionality
3535
- `title-case.ts` - Specialized title casing (AP Style, Chicago Style)
36+
- `custom-regex.ts` - Custom user-defined regex-based commands
3637
- `preview.ts` - Live preview functionality for transformations
3738
- `sidebar.ts` - Optional webview sidebar (Labs feature)
3839

@@ -47,6 +48,7 @@ The extension registers VSCode commands dynamically from the `commandNameFunctio
4748
- **Multi-selection support**: All commands work with multiple text selections
4849
- **Preview mode**: Live preview of transformations before applying
4950
- **Argument-based commands**: Some commands (like `chop`, `truncate`) prompt for numeric arguments
51+
- **Custom regex commands**: Users can define their own regex-based transformations via settings
5052
- **Duplicate operations**: Special handling for duplicate-and-increment/decrement commands
5153
- **Labs features**: Experimental features behind a configuration flag
5254

CUSTOM-COMMANDS.md

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Custom Regex Commands
2+
3+
The String Manipulation extension now supports custom regex-based commands that you can configure yourself!
4+
5+
## How to Access Custom Commands
6+
7+
1. Select some text in your editor
8+
2. Open Command Palette (`Cmd+Shift+P` on Mac, `Ctrl+Shift+P` on Windows/Linux)
9+
3. Type "String Manipulation: Custom Command"
10+
4. Choose from your configured custom commands
11+
12+
## How to Configure Custom Commands
13+
14+
### Via Settings UI
15+
1. Open VS Code Settings (`Cmd+,` or `Ctrl+,`)
16+
2. Search for "string manipulation custom"
17+
3. Click "Edit in settings.json" next to "Custom Commands"
18+
19+
### Via settings.json
20+
Add this to your VS Code settings:
21+
22+
```json
23+
{
24+
"stringManipulation.customCommands": [
25+
{
26+
"name": "Extract Numbers",
27+
"searchPattern": "[^0-9]",
28+
"replacement": "",
29+
"global": true
30+
},
31+
{
32+
"name": "Wrap in Quotes",
33+
"searchPattern": "^(.*)$",
34+
"replacement": "\"$1\""
35+
},
36+
{
37+
"name": "Camel to Snake",
38+
"searchPattern": "([a-z])([A-Z])",
39+
"replacement": "$1_$2",
40+
"global": true
41+
},
42+
{
43+
"name": "Remove Vowels",
44+
"searchPattern": "[aeiouAEIOU]",
45+
"replacement": "",
46+
"global": true
47+
},
48+
{
49+
"name": "Add Prefix",
50+
"searchPattern": "^(.*)$",
51+
"replacement": "PREFIX_$1",
52+
"global": true,
53+
"multiline": true
54+
},
55+
{
56+
"name": "Case Insensitive Replace",
57+
"searchPattern": "hello",
58+
"replacement": "hi",
59+
"global": true,
60+
"ignoreCase": true
61+
}
62+
]
63+
}
64+
```
65+
66+
## Regex Features Supported
67+
68+
- **Capture Groups**: Use `$1`, `$2`, etc. to reference captured groups
69+
- **Full Match**: Use `$&` to reference the entire match
70+
- **Named Flag Properties**: Use boolean properties for clear flag configuration
71+
- **All JavaScript regex features**: Full JavaScript regex syntax support
72+
73+
## Regular Expression Flags
74+
75+
Instead of using cryptic flag letters, use clear boolean properties in your custom commands. These correspond to the [JavaScript RegExp flags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags):
76+
77+
| Property | Flag | Description | Default |
78+
|----------|------|-------------|---------|
79+
| `global` | `g` | Find all matches rather than stopping after the first match | `true` |
80+
| `ignoreCase` | `i` | Case-insensitive search | `false` |
81+
| `multiline` | `m` | `^` and `$` match start/end of line, not just start/end of string | `false` |
82+
| `dotAll` | `s` | `.` matches newline characters | `false` |
83+
| `unicode` | `u` | Enable full Unicode support | `false` |
84+
| `sticky` | `y` | Match only at the index indicated by the lastIndex property | `false` |
85+
86+
**Example with flags:**
87+
```json
88+
{
89+
"name": "Case Insensitive Word Replace",
90+
"searchPattern": "\\bhello\\b",
91+
"replacement": "hi",
92+
"global": true,
93+
"ignoreCase": true,
94+
"multiline": true
95+
}
96+
```
97+
98+
## Examples
99+
100+
### Extract Only Numbers
101+
```json
102+
{
103+
"name": "Extract Numbers",
104+
"searchPattern": "[^0-9]",
105+
"replacement": "",
106+
"global": true
107+
}
108+
```
109+
Input: `abc123def456` → Output: `123456`
110+
111+
### Convert camelCase to snake_case
112+
```json
113+
{
114+
"name": "Camel to Snake",
115+
"searchPattern": "([a-z])([A-Z])",
116+
"replacement": "$1_$2",
117+
"global": true
118+
}
119+
```
120+
Input: `camelCaseString` → Output: `camel_Case_String`
121+
122+
### Wrap Lines in Quotes
123+
```json
124+
{
125+
"name": "Wrap in Quotes",
126+
"searchPattern": "^(.*)$",
127+
"replacement": "\"$1\"",
128+
"global": true,
129+
"multiline": true
130+
}
131+
```
132+
Input: `hello world` → Output: `"hello world"`
133+
134+
### Extract Email Domains
135+
```json
136+
{
137+
"name": "Extract Email Domain",
138+
"searchPattern": ".*@(.+)",
139+
"replacement": "$1",
140+
"global": true
141+
}
142+
```
143+
Input: `[email protected]` → Output: `example.com`
144+
145+
### Case-Insensitive Replace
146+
```json
147+
{
148+
"name": "Replace Hello (Any Case)",
149+
"searchPattern": "hello",
150+
"replacement": "hi",
151+
"global": true,
152+
"ignoreCase": true
153+
}
154+
```
155+
Input: `Hello HELLO hello` → Output: `hi hi hi`
156+
157+
## Validation
158+
159+
The extension validates your regex patterns and will show helpful error messages if:
160+
- The regex pattern is invalid
161+
- Command names contain invalid characters
162+
- Required fields are missing
163+
164+
## Features
165+
166+
- **Live Preview**: See transformation previews in the command picker
167+
- **Multi-selection Support**: Works with multiple text selections
168+
- **Dynamic Updates**: Changes to settings immediately update available commands
169+
- **Integration**: Works with the repeat last action feature
170+
- **Error Handling**: Clear error messages for invalid configurations
171+
172+
## Differences from VS Code Find & Replace
173+
174+
- **Saved Commands**: Your regex transformations are saved and reusable
175+
- **Named Commands**: Give your transformations meaningful names
176+
- **Quick Access**: Access via Command Palette without opening find/replace dialog
177+
- **Multi-selection**: Apply to multiple selections at once
178+
- **Integration**: Works seamlessly with other String Manipulation features

README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,68 @@ This feature makes it easier to find the right transformation without trial and
7171

7272
![String Manipulation Preview Feature](images/preview-demo.gif)
7373

74+
## 🎛️ Custom Commands
75+
76+
Create your own regex-based string manipulation commands! Define custom transformations that fit your specific workflow needs.
77+
78+
### Quick Start with Custom Commands
79+
80+
1. **Select text** in your editor
81+
2. **Open Command Palette** (`Cmd+Shift+P` / `Ctrl+Shift+P`)
82+
3. **Type "String Manipulation: Custom Command"**
83+
4. **Choose from your configured commands** (or add some if none exist)
84+
85+
### Setting Up Custom Commands
86+
87+
Add custom commands to your VS Code settings:
88+
89+
```json
90+
{
91+
"stringManipulation.customCommands": [
92+
{
93+
"name": "Extract Numbers",
94+
"searchPattern": "[^0-9]",
95+
"replacement": "",
96+
"global": true
97+
},
98+
{
99+
"name": "Wrap in Quotes",
100+
"searchPattern": "^(.*)$",
101+
"replacement": "\"$1\""
102+
},
103+
{
104+
"name": "Camel to Snake",
105+
"searchPattern": "([a-z])([A-Z])",
106+
"replacement": "$1_$2",
107+
"global": true
108+
}
109+
]
110+
}
111+
```
112+
113+
### Regular Expression Flags
114+
115+
Use intuitive boolean properties instead of cryptic flag letters. See the [MDN RegExp flags documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions#advanced_searching_with_flags) for detailed information.
116+
117+
| Property | Flag | Description |
118+
|----------|------|-------------|
119+
| `global` | `g` | Find all matches rather than stopping after the first |
120+
| `ignoreCase` | `i` | Case-insensitive search |
121+
| `multiline` | `m` | `^` and `$` match start/end of line |
122+
| `dotAll` | `s` | `.` matches newline characters |
123+
| `unicode` | `u` | Enable full Unicode support |
124+
| `sticky` | `y` | Match only at specific index |
125+
126+
### Custom Command Features
127+
128+
- **🔍 Live Previews**: See transformation results before applying
129+
- **✅ Validation**: Real-time regex pattern validation with helpful errors
130+
- **🔄 Multi-selection**: Works with multiple text selections
131+
- **🎯 Saved & Reusable**: Your commands are stored and accessible anytime
132+
- **🔗 Integration**: Works with repeat last action and other features
133+
134+
📖 **[Complete Custom Commands Guide](CUSTOM-COMMANDS.md)** - Detailed examples and advanced usage
135+
74136
## 🧪 Introducing Labs Features
75137

76138
Introducing String Manipulation Labs

package.json

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,66 @@
3939
"telemetry",
4040
"usesOnlineServices"
4141
]
42+
},
43+
"stringManipulation.customCommands": {
44+
"type": "array",
45+
"default": [],
46+
"description": "Custom regex-based string manipulation commands. Each command consists of a name, search pattern (regex), and replacement string.",
47+
"items": {
48+
"type": "object",
49+
"properties": {
50+
"name": {
51+
"type": "string",
52+
"description": "Display name for the custom command (will appear in command palette as 'String Manipulation: <name>')",
53+
"pattern": "^[a-zA-Z0-9\\s\\-_]+$",
54+
"minLength": 1,
55+
"maxLength": 50
56+
},
57+
"searchPattern": {
58+
"type": "string",
59+
"description": "Regular expression pattern to match text. Use parentheses to create capture groups that can be referenced in the replacement.",
60+
"minLength": 1
61+
},
62+
"replacement": {
63+
"type": "string",
64+
"description": "Replacement string. Use $1, $2, etc. to reference capture groups from the search pattern. Use $& for the entire match.",
65+
"minLength": 0
66+
},
67+
"global": {
68+
"type": "boolean",
69+
"description": "Global flag (g): Find all matches rather than stopping after the first match. Default: true.",
70+
"default": true
71+
},
72+
"ignoreCase": {
73+
"type": "boolean",
74+
"description": "Ignore case flag (i): Case-insensitive search. Default: false.",
75+
"default": false
76+
},
77+
"multiline": {
78+
"type": "boolean",
79+
"description": "Multiline flag (m): ^ and $ match start/end of line, not just start/end of string. Default: false.",
80+
"default": false
81+
},
82+
"dotAll": {
83+
"type": "boolean",
84+
"description": "Dot all flag (s): . matches newline characters. Default: false.",
85+
"default": false
86+
},
87+
"unicode": {
88+
"type": "boolean",
89+
"description": "Unicode flag (u): Enable full Unicode support. Default: false.",
90+
"default": false
91+
},
92+
"sticky": {
93+
"type": "boolean",
94+
"description": "Sticky flag (y): Match only at the index indicated by the lastIndex property. Default: false.",
95+
"default": false
96+
}
97+
},
98+
"required": ["name", "searchPattern", "replacement"],
99+
"additionalProperties": false
100+
},
101+
"maxItems": 20
42102
}
43103
}
44104
},
@@ -58,6 +118,11 @@
58118
"category": "String Manipulation",
59119
"command": "string-manipulation.showTransformationsWithPreview"
60120
},
121+
{
122+
"title": "Custom Command",
123+
"category": "String Manipulation",
124+
"command": "string-manipulation.customCommand"
125+
},
61126
{
62127
"title": "Titleize",
63128
"category": "String Manipulation",
@@ -240,6 +305,11 @@
240305
"command": "string-manipulation.showTransformationsWithPreview",
241306
"group": "7_modification",
242307
"when": "editorHasSelection"
308+
},
309+
{
310+
"command": "string-manipulation.customCommand",
311+
"group": "7_modification",
312+
"when": "editorHasSelection"
243313
}
244314
],
245315
"string-manipulation": [

0 commit comments

Comments
 (0)