๐ป Regex Psychic - Debugging Helper
Translates cryptic regex errors into human-readable explanations instantly
import re
from typing import Optional, Dict
class RegexPsychic:
"""
Translates regex failures from cryptic error messages into human-readable explanations.
No more guessing why your pattern expects a digit but found 'a' at position 7.
"""
def __init__(self):
self.error_translations = {
'nothing to repeat': "Your pattern has a quantifier (*, +, ?, {}) with nothing before it to repeat",
'unbalanced parenthesis': "You have mismatched opening and closing parentheses",
'bad character range': "Your character class [a-Z] has invalid range (use [a-zA-Z] instead)",
'missing ): unterminated subpattern': "You forgot to close a group with ')'",
'unexpected end of pattern': "Your regex ends abruptly, likely missing a closing bracket or parenthesis"
}
def debug_pattern(self, pattern: str, test_string: str) -> Optional[str]:
"""
Try to match pattern against test_string and provide human-readable error if it fails.
"""
try:
match = re.match(pattern, test_string)
if match:
return f"โ Pattern matched successfully!"
else:
# Analyze common failure patterns
if '^' in pattern and not test_string.startswith(pattern[1] if len(pattern) > 1 else ''):
return f"Pattern expects string to start with '{pattern[1]}' but found '{test_string[0]}'"
# Check for digit expectations
digit_pattern = r'\\d'
if digit_pattern in pattern:
for i, char in enumerate(test_string):
if not char.isdigit() and i < len(pattern):
return f"Pattern expects a digit at position {i+1} but found '{char}'"
return f"Pattern didn't match, but no specific error detected. Try the pattern in smaller parts."
except re.error as e:
error_msg = str(e)
# Translate common errors
for error_key, translation in self.error_translations.items():
if error_key in error_msg.lower():
return f"โ {translation}"
# Generic fallback
return f"โ Regex error: {error_msg}"
return None
# Usage example:
psychic = RegexPsychic()
# Debug a phone number pattern
pattern = r'^\\d{3}-\\d{3}-\\d{4}$'
test_string = "555-867-5309"
result = psychic.debug_pattern(pattern, test_string)
print(result) # Outputs: โ Pattern matched successfully!
# Debug a failing pattern
bad_pattern = r'^\\d{3}-\\d{3}-\\d{3}$' # Expects 3 digits at end
result = psychic.debug_pattern(bad_pattern, test_string)
print(result) # Outputs: Pattern expects a digit at position 10 but found '0'
The Problem: When Regex Becomes Dark Magic
Regular expressions were invented in the 1950s by Stephen Kleene, who probably thought he was creating a neat mathematical notation for regular languages. Little did he know he was giving birth to a form of arcane sorcery that would torment developers for generations.
Here's the absurd reality: we write these logical expressions to match patterns, but when they fail, we debug them through what can only be described as divination. You stare at /^\d{3}-\d{3}-\d{4}$/ trying to match phone numbers, and when it rejects "555-867-5309" (Jenny's number, obviously), you don't get "Your pattern expects exactly three digits after the second hyphen but found four." You get... nothing. Or worse, you get "no match"โthe programming equivalent of a mystic shrugging and saying "the spirits are not aligned today."
The worst part? We've normalized this madness. We accept that debugging regex requires:
- Opening regex101.com in three different tabs
- Adding and removing question marks like you're performing an exorcism
- Whispering "maybe it needs another backslash?" to your rubber duck
- Finally giving up and using string methods for everything
It's like trying to fix a car by randomly hitting it with different wrenches while chanting "vroom vroom."
The Solution: A Psychic Who Actually Knows Regex
I got tired of performing regex rituals every time I needed to validate an email (which, let's be honest, you should never actually do with regex anyway). So I built Regex Psychicโa CLI tool that does what regex engines should have done from the beginning: explain what went wrong in plain English.
Instead of "no match" or some cryptic error code, Regex Psychic tells you things like:
- "Your \\d expects a digit but found 'a' at position 7"
- "Your pattern ends here but the string continues with '...'"
- "You're using a greedy quantifier that's eating your entire string"
It's like having a regex expert looking over your shoulder, except this expert doesn't charge $300/hour and won't judge you for using .* when you meant .*?.
The magic (and I use that term ironically) happens through pattern analysis. The tool compares what your regex expects at each position with what's actually in your test string. When expectations diverge from reality, it highlights exactly where and explains why. No more guessing. No more sacrifices to the regex gods.
How to Use It: From Witchcraft to Engineering
Installation is straightforward because we're not summoning demons here:
npm install -g regex-psychic
# or
pip install regex-psychic
# or download the binary from GitHubBasic usage looks like this:
regex-psychic "\\d{3}-\\d{3}-\\d{4}" "555-867-5309a"The tool would output something like:
๐ฎ Regex Psychic Analysis:
Pattern: /\d{3}-\d{3}-\d{4}/
Test string: "555-867-5309a"
โ Match failed at position 12
Expected: End of pattern (after 4 digits)
Found: 'a' (character continues)
๐ก Suggestion: Your string has extra characters after the expected pattern.
Try: /\d{3}-\d{3}-\d{4}$/ to enforce end-of-stringHere's a peek at the core logic from the main file:
function analyzeFailure(pattern, testString) {
const regex = new RegExp(pattern);
const match = regex.exec(testString);
if (match) return { success: true };
// Walk through pattern and string simultaneously
let patternPos = 0;
let stringPos = 0;
while (patternPos < pattern.length && stringPos < testString.length) {
const expected = getNextExpected(pattern, patternPos);
const found = testString[stringPos];
if (!matchesExpectation(expected, found)) {
return {
success: false,
failurePoint: stringPos,
expected: expected.description,
found: found,
suggestion: generateSuggestion(expected, found, pattern)
};
}
patternPos = expected.nextPatternPos;
stringPos++;
}
// Handle remaining expectations or string characters
return generateEndAnalysis(patternPos, stringPos, pattern, testString);
}Check out the full source code on GitHub to see how it handles edge cases, generates suggestions, and makes your regex debugging sessions 90% less mystical.
Key Features That Actually Help
- Plain English Explanations: No more deciphering "Lookbehind assertion failed"โget "Your pattern expects a digit but found a letter."
- Intelligent Suggestions: Based on common antipatterns. Using
\\d+when you meant\\d{4}for a year? It'll tell you. - Exact Failure Highlighting: Points to the precise character where expectations diverged from reality. No more scanning entire strings.
- Multiple Pattern Support: Test your regex against several strings at once to find edge cases.
- Learning Mode: Includes explanations of why certain regex constructs behave the way they do.
Conclusion: Stop Guessing, Start Knowing
Regex doesn't have to be black magic. With Regex Psychic, you can actually understand why your patterns fail instead of randomly modifying them until they work. You'll save hours of debugging time, write better regex patterns, and maybeโjust maybeโstop fearing that email validation function you wrote six months ago.
The tool is free, open source, and won't judge you for your regex sins (past or present). It's time to bring regex debugging out of the dark ages and into the realm of actual engineering.
Try it out: https://github.com/BoopyCode/regex-psychic
Your rubber duck will miss the conversations, but your productivity will thank you.
Quick Summary
- What: Regex Psychic is a CLI tool that explains regex failures in plain English and suggests fixes.
๐ฌ Discussion
Add a Comment