Replace backslash '\' with forward '/' slash in VS Code snippets with Regex - regex

Background:
I am adding a custom JavaScript snippet in VS Code to insert the file path of the current file. VS Code provides variables to get the file path but the file path contains backslashes in the path. And I want to get the path with '/' instead of '\'
eg. 'hello\world.js' -> 'hello/world.js'
VS Code also provides variable transformations using regex. I tried to replace backslashes with forward slashes but I could not make it work. I also checked similar questions but I could not any result for this specific to variable transformations in VS Code snippets. And I could not figure it out with other similar solutions as I'm new to regex.
What I tried:
This works fine and replaces backslashes '\' with '_'
"filepath": {
"prefix": "filepath",
"body": ["/${RELATIVE_FILEPATH/([\\\\])/_/g}"],
"description": "Path of current file"
}
But if I change '_' with '/' it does not work.
"filepath": {
"prefix": "filepath",
"body": ["/${RELATIVE_FILEPATH/([\\\\])///g}"],
"description": "Path of current file"
}
I tried some variations by escaping slash and using regex groups but I could not make it work.

\\\\/\\//g is your expression. That one should mean the same, because it is a choice of only one character: [\\\\]/\\//g.

Related

replace markdown images without alt with filename using regex using find & replace in vscode?

i have multiple markdown files that contain images without alt that look like:
# my file
![](./filename-1.png)
# this is an example image
![](./this-is-a-an-example-image.png)
i want to replace them with alt from the filename but without the .png extension & without ./ & replacing hyphens (- ) with empty spaces.
so the above markdown would look like:
# my file
![filename 1](./filename-1.png)
# this is an example image
![this is an example image](./this-is-an-example-image.png)
i can't do this manually as i have 100+ images so would love to automate this with a regex using vscode's find & replace.
i had previously removed alt but want it back now. i didn't version control it so can't go back either.
how do i do it?
Here is how to do it with an extension, Find and Transform, that can run two find and replaces in a row. Install the extension and then make this keybinding (in your keybindings.json):
{
"key": "alt+m",
"command": "findInCurrentFile",
"args": {
"find": [
"(!\\[\\])\\((\\.\\/)?(.*)(\\.(png|jpg|gif)\\))",
"(?<=!\\[.*)(-)(?=.*\\])"
],
"replace": ["![$3]($2$3$4", " "],
"isRegex": true,
"postCommands": "cancelSelection"
}
}
I made it to handle other image formats which you may not need.
The first find and replace just moves the filename (minus the leading .\ and trailing .png) into the ![].
The second find matches just the - in that ![asdasd-asdasd-asdasd] and replaces those - with " " i.e., one space.
this is the demo on regex101 to find the group between ./ & .png → https://regex101.com/r/gMgc6r/1
important: i enabled the search in each file, not the sidebar & ticked the .* button that says use regular expression
then i typed the following:
find: !\[\]\(.\/(.*).png\)
replace: ![$1](./$1.png)
this converts:
![](./a-filename.png)
to
![a-filename](./a-filename.png)
this finds the string between each bracket [ & ] → https://regex101.com/r/Ke89CK/1 but i couldn't figure out how to use it in vscode.
i have to convert [a-filename] by replacing - with empty spaces.
find: ?
replace: ?

Getting subdirectory with regex for snippet

To create a snippet in vscode that returns the name of a file I use:
{$TM_FILENAME}
To create a snippet in vscode that returns the name of a directory with its first capital letter I use:
${TM_DIRECTORY/.*\\/(.*)$/${1:/capitalize}/g}
But I need to get a subdirectory and leave all the letters in lowercase. For example,
a/b/c/d/e
how could i get the \d directory?
You can use
"LowercaseFolderPath": {
"scope": "",
"prefix": "lowercasefolderpath",
"body": [
"${TM_DIRECTORY/([^\\/\\\\]+)(?=[\\/\\\\][^\\/\\\\]*$)/${1:/downcase}/}"
],
"description": "Lower-case folder path"
},
Here, ([^\/\\]+)(?=[\/\\][^\/\\]*$) regex captures the last but one subdirectory into $1, and the ${1:/downcase} replacement turns it to lower case.
See the regex demo.

VS Code snippet regex for relative path

I'm coding in Elixir/Phoenix Framework using VS Code and trying to transform the following relative path
lib/shop_web/live/product_live/index.ex
into
ShopWeb.Live.ProductLive.Index
using snippets.
The closest to that was the regex below
"${RELATIVE_FILEPATH/^(lib\\/|test\\/)(\\w)|(.ex|.exs)$|\\/(\\w)|_(\\w)/${2:/upcase}${4:/upcase}${5:/upcase}/g}"
who gives me the following output
ShopWebLiveProductLiveIndex
I could not find a way to insert the missing dots.
Can anyone help me?
Thanks in advance!
Try this:
"test7": {
"prefix": "al",
"body": [
// my version
"${RELATIVE_FILEPATH/^([^\\/\\\\]+[\\/\\\\])|(\\.ex|\\.exs)$|([^._\\/\\\\]+)|_|([\\/\\\\])/${3:/capitalize}${4:+.}/g}",
// your version tweaked
"${RELATIVE_FILEPATH/^(lib[\\/\\\\]|test[\\/\\\\])(\\w)|(\\.ex|\\.exs)$|([\\/\\\\])(\\w)|_(\\w)/${2:/upcase}${4:+.}${5:/upcase}${6:/upcase}/g}",
],
"description": "alert line"
}
[Note: I made these work for both path.separators / and \. If you don't need that you could shorten the snippet by a lot.]
Your version was very close. I changed it to \\.ex just to make the dots explicit.
I also added a 4th capturing group ([\\/\\\\]) just before the 5th as in ([\\/\\\\])(\\w).
Now that 4th group can be used in a conditional ${4:+.} to add the .'s where the path separators were.
My version is a little shorter - it matches but doesn't use whatever directory is first, be it lib or test or whatever. If that doesn't work for you it is easy to modify that bit of the regexp. I shortened it to 4 capture groups.
([^._\\/\\\\]+)|_|([\\/\\\\]) the end of my version:
([^._\\/\\\\]+) : match characters other than ._\/, or
_ : match it but we aren't using it so no need for a capture group, or
([\\/\\\\]) : match just the path separator in group 4 to use in the conditional.
${4:+.} : conditional, if there is a group 4 (a path separator) add a ..
Thanks to #Mark, my snippet to create a module in Elixir or Phoenix Framework looks like this now:
"Module": {
"prefix": "defmodule",
"description": "Create a module by the Elixir naming convention",
"body": [
"defmodule ${RELATIVE_FILEPATH/^([^\\/\\\\]+[\\/\\\\])|(\\.ex|\\.exs)$|([^._\\/\\\\]+)|_|([\\/\\\\])/${3:/capitalize}${4:+.}/g} do",
"\t$1",
"end"
],
}
As the naming convention, the output for the file in my question lib/shop_web/live/product_live/index.ex will be:
defmodule ShopWeb.Live.ProductLive.Index do
end

Extracting message content from JSON using regular expresions

I need to extract content of messages from JSON, I am not allowed to use JSON parser so I tried using regular expressions, however I got stuck on extracting message content. I am using C++.
Here's an example of the JSON file:
{
"id":"776752463986294785",
"type":0,
"content":"\"",
"channel_id":"762106839054811176",
"author":{
"id":"487706666905894923",
"username":"Emzak",
"avatar":"a70859ecda1355dfd55bddcfd0194458",
"discriminator":"6235",
"public_flags":0
},
"attachments":[
],
"embeds":[
],
"mentions":[
],
"mention_roles":[
],
"pinned":false,
"mention_everyone":false,
"tts":false,
"timestamp":"2020-11-13T10:16:58.777000+00:00",
"edited_timestamp":null,
"flags":0
}
as I said i need the Content field, my current regex is :
"content"[ :]+(\"[^"]*\")
Which works unless there are quotation marks in the content. If there are any, they are always escaped, but I haven't found a way to get past them. With quotation marks my current regex gives me this string :
"content": "\"
Which would be problematic if there was any message behind that quotation mark. I would like to get this string :
"content": "\""
Any help would be appreciated, Thanks :)
You can make it escape \" as follows:
"content"[ :]+(\"(?:\\.|[^"])*\")
It creates a non-capturing group that matches every \ with the following character, as well as the original [^"] criteria.

Regex in Sublime Text tmLanguage file doesn't use multiline

I'm trying to create a custom syntax language file to highlight and help with creating new documents in Sublime Text 2. I have come pretty far, but I'm stuck at a specific problem regarding Regex searches in the tmLanguage file. I simply want to be able to match a regex over multiple lines within a YAML document that I then convert to PList to use in Sublime Text as a package. It won't work.
This is my regex:
/(foo[^.#]*bar)/
And this is how it looks inside the tmLanguage YAML document:
patterns:
- include: '#test'
repository:
test:
comment: Tester pattern
name: constant.numeric.xdoc
match: (foo[^.#]*bar)
If I build this YAML to a tmLanguage file and use it as a package in Sublime Text, I create a document that uses this custom syntax, try it out and the following happens:
This WILL match:
foo 12345 bar
This WILL NOT match:
foo
12345
bar
In a Regex tester, they should and will both match, but in my tmLanguage file it does not work.
I also already tried to add modifiers to my regex in the tmLanguage file, but the following either don't work or break the document entirely:
match: (/foo[^.#]*bar/gm)
match: /(/foo[^.#]*bar/)/gm
match: /foo[^.#]*bar/gm
match: foo[^.#]*bar
Note: My Regex rule works in the tester, this problem occurs in the tmLanguage file in Sublime Text 2 only.
Any help is greatly appreciated.
EDIT: The reason I use a match instead of begin/end clauses is because I want to use capture groups to give them different names. If someone has a solution with begin and end clauses where you can still name 'foo', '12345' and 'bar' differently, that's fine by me too.
I found that this is impossible to do. This is directly from the TextMate Manual, which is the text editor Sublime Text is based on.
12.2 Language Rules
<...>
Note that the regular expressions are matched against only a single
line of the document at a time. That means it is not possible to use a
pattern that matches multiple lines. The reason for this is technical:
being able to restart the parser at an arbitrary line and having to
re-parse only the minimal number of lines affected by an edit. In most
situations it is possible to use the begin/end model to overcome this
limitation.
My situation is one of the few in which a begin/end model cannot overcome the limitation. Unfortunate.
Long time since asked, but are you sure you can't use begin/end? I had similar problems with begin/end until I got a better grasp of the syntax/logic. Here's a rough example from a json tmLanguage file I'm doing (don't know the proper YAML syntax).
"repository": {
"foobar": {
"begin": "foo(?=[^.#]*)", // not sure about what's needed for your circumstance. the lookahead probably only covers the foo line
"end": "bar",
"beginCaptures": {
"0": {
"name": "foo"
}
},
"endCaptures": {
"0": {
"name": "bar"
}
},
"patterns": [
{"include": "#test-after-foobarmet"}
]
},
"test-after-foobarmet": {
"comment": "this can apply to many lines before next bar so you may need more testing",
"comment2": "you could continue to have captures here that go to another deeper level...",
"name": "constant.numeric.xdoc",
"match": "anyOtherRegexNeeded?"
}
}
I didn't follow your
"i need to number the different sections between the '#' and '.'
characters."
, but you should be able to have a test in test-after-foobarmet with more captures if needed for naming different groups between foo bar.
There's are good explanation of TextMate Grammar here. May still suffer from some errors but explains it in a way that was helpful for me when I didn't know anything about the topic.