Rewrite indoc!
macro Has Fix
Description
This example, created from a Tweet, shows a refactoring operation being performed on Rust source code. The changes involve removing indoc!
macro declarations while preserving the CSS-like content within them.
Previously, the same refactor is implemented by a unreadable monster regex in vim syntax.
Click to see the original regex (neovim, btw)
vimscript
:%s/\v(indoc!|)(| )([|\{)r#"(([^#]+|\n+)+)"#/`\4`
I have to confess that I don't understand this regex even if I use neovim, btw.
Let Claude break it down piece by piece:
:%s/
- Vim substitution command for all lines\v
- Very magic mode in vim for simpler regex syntax(indoc!|)
- First capture group: matches either "indoc!" or nothing(| )
- Second capture group: matches either empty string or a space([|\{)
- Third capture group: matches either[
or{
r#"
- Matches literalr#"
(Rust raw string delimiter)(([^#]+|\n+)+)
- Fourth capture group (nested):[^#]+
- One or more non-# characters|\n+
- OR one or more newlines- Outer
()+
makes this repeat one or more times
"#
- Matches the closing raw string delimiter- `\4` - Replaces with the fourth capture group wrapped in backticks
This regex is designed to find Rust raw string literals (possibly wrapped in indoc!
macro), capture their content, and replace the entire match with just the content wrapped in backticks. It's more precise than my previous explanation and matches the pattern you're showing.
Pattern
shell
ast-grep --pattern 'indoc! { r#"$$$A"# }' --rewrite '`$$$A`' sgtest.rs
Example
rs
fn main() {
indoc! {r#"
.foo {
order: 1;
}
"#};
}
Diff
rs
fn main() {
indoc! {r#" // [!code --]
`.foo { // [!code ++]
order: 1;
}
"#};
`;
}