admin管理员组文章数量:1293777
I'm making my own "toggle block comment" keybinding for python, using ''' instead of """ for delimiters.
This is the best I could come up with to mimic the existing keybinding (and adapt it to my liking):
{
"key": "alt+shift+a",
"command": "editor.action.insertSnippet",
"args": {
"snippet": "${TM_SELECTED_TEXT/^('''\n?)?(.*?)(\n?''')?$/${1:?\n:'''\n}$2${3:?\n:\n'''}/s}"
},
"when": "editorTextFocus && editorHasSelection && editorLangId == 'python'"
}
^('''\n?)
: The regex captures the opening delimiter if it exists, and places it in the first group.
${1:?\n:'''\n}
: If the group was found, it substitutes it with a line break, if it doesn't, it adds the delimiter (it adds ''' and a line break). The same thing happens for the closing delimiter.
However my intention is not to substitute the delimiter if found with a line break, but with nothing, i.e. to remove the group if it is found. How could I do this?
I'm making my own "toggle block comment" keybinding for python, using ''' instead of """ for delimiters.
This is the best I could come up with to mimic the existing keybinding (and adapt it to my liking):
{
"key": "alt+shift+a",
"command": "editor.action.insertSnippet",
"args": {
"snippet": "${TM_SELECTED_TEXT/^('''\n?)?(.*?)(\n?''')?$/${1:?\n:'''\n}$2${3:?\n:\n'''}/s}"
},
"when": "editorTextFocus && editorHasSelection && editorLangId == 'python'"
}
^('''\n?)
: The regex captures the opening delimiter if it exists, and places it in the first group.
${1:?\n:'''\n}
: If the group was found, it substitutes it with a line break, if it doesn't, it adds the delimiter (it adds ''' and a line break). The same thing happens for the closing delimiter.
However my intention is not to substitute the delimiter if found with a line break, but with nothing, i.e. to remove the group if it is found. How could I do this?
Share Improve this question asked Feb 12 at 15:56 Paulo ModuloPaulo Modulo 998 bronze badges 6 | Show 1 more comment2 Answers
Reset to default 0In this case, instead or replacing the delimiter group with nothing, capture the content between|after|before the delimiter(s) and return the captured group (content), $1
, without the delimiters. To get the toggle effect will require one or more test strings with the matching desired replacement option (add delimiter(s) OR no delimiters)
I have the matching content group $1
be the part to keep and then add or remove what you want around it, see two solution options below**
I am not aware of if-else if-else if-else then replacements that I could build with regex, so
If I understand correctly, you are looking for four different cases for the desired toggle effect:
- If opening and closing delimiter, remove opening and closing delimiter.
- If opening delimiter without closing delimiter, add closing delimiter.
- If closing delimiter without opening delimiter, add opening delimiter.
- If no opening or closing delimiter, add opening and closing delimiter.
OPTION 1:
Each option is only true for the specific case. Here are the regex patterns and replacement patterns for the four snippets.
1) snippet_for_matching_delimiters:
"snippet": "${TM_SELECTED_TEXT/^'''\n?((?:.*?)(?:\n.*)*)'''\n?$/$1/s}"
2) snippet_for_unmatched_opening_delimiters"
"snippet": "${TM_SELECTED_TEXT/^('''\n?(?:.*?)(?:\n.*)*)(?!'''\n?)$/s}"
3) snippet_for_unmatched_closing_delimiters:
"snippet": "${TM_SELECTED_TEXT/^('''\n?(?:.*?)(?:\n.*)*)(?!'''\n?)$/s}"
4) snippet_for_no_opening_or_closing_delimiter:
"snippet": "${TM_SELECTED_TEXT/^(?!'''\n?)((?:.*?)(?:\n.*)*)(?!'''\n?)$/```\n$1\n```/s}"
Regex Demo matching delimiters: https://regex101/r/WXobxd/3
Regex Demo unmatched opening delimiter: https://regex101/r/qscBxC/2
Regex Demo unmatched closing delimiter: https://regex101/r/1smRle/2
Regex Demo no_opening_or_closing_delimiter: https://regex101/r/GlH7LQ/1
OPTION 2:
IF OPENING AND CLOSING DELIMITER: THEN REMOVE BOTH DELIMITERS
This only matches if there are no opening or closing delimiters present.
"snippet": "${TM_SELECTED_TEXT/^(?!'''\n?)((?:.*?)(?:\n.*)*)(?!'''\n?)$/```\n$1\n```/s}"
ELSE: ADD MISSING OPENING AND/OR DELIMITER:
This option also captures the string target text inside the delimiters when both opening and closing delimiters are present. It will return all four options with both opening and closing delimiters.
"snippet": "${TM_SELECTED_TEXT/^(?:'''\n?)?((?:.*?)(?:\n.*?)*?)(?:\n?'''\n?)?$/```\n$1\n```/s}"
Regex Demo IF-THEN: https://regex101/r/WXobxd/3
Regex Demo ELSE: https://regex101/r/Wv7DD0/3
I used the ECMAScript regex flavor
So I realised my first try above did not take indentation into account. Here is the snippet I came up with. It's good enough for my purpose. So far, in spite of the limitations described below, I've been able to use it in a satisfactory manner.
[
{
"key": "alt+shift+a",
"command": "editor.action.insertSnippet",
"args": {
// Indentation-saving snippet
// MATCH
// ^ Beginning of selected text
// ( *) $1 is a possible indentation that is to be reused for delimiters and content
// ('''\n *)? $2 is a possible opening delimiter, including following line break and indentation
// (.*?) $3 is a possible content (non-greedy)
// (\n *''')? $4 is a possible closing delimiter, including previous line break and indentation
// $ End of selected text
// SUBSTITUTION
// $1 If there was an indentation, indent the opening delimiter
// ${2:?\n:'''\n} If there was an opening delimiter, replace it with a line break, otherwise make a delimiter and line break
// $1 If there was an indentation, indent the content
// $3\n The content and a line break
// $1 If there was an indentation, indent the closing delimiter
// ${4:?\n:'''} If there was a closing delimiter, replace it with a line break, otherwise make a linebreak and a delimiter
// LIMITATIONS
// The selection must be the entire lines of the content to comment in / out
// Line breaks are created because we can't replace a group by nothing in this REGEX implementation
"snippet": "${TM_SELECTED_TEXT/^( *)('''\n *)?(.*?)(\n *''')?$/$1${2:?\n:'''\n}$1$3\n$1${4:?\n:'''}/s}"
},
"when": "editorTextFocus && editorHasSelection && editorLangId == 'python'"
}
]
My settings generate indentation as spaces, but I assume it could be adapted to tabs.
I'm accepting @rich neadle's reply as the answer, namely this did answer the initial question:
I am not aware of if-else if-else if-else then replacements that I could build with regex
本文标签:
版权声明:本文标题:regex - When transforming a vscode snippet variable, how to substitute a group with nothing? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741585375a2386815.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
${1:+'''\n}$2${3:+\n'''}
replacement. If Group 1 or 3 is matched, replace with'''
+ a newline. – Wiktor Stribiżew Commented Feb 12 at 16:14${x:+yyy}
syntax. – Wiktor Stribiżew Commented Feb 12 at 17:32