2

I am currently working on some Python snippets for VSCode using JavaScript regular expressions and I'd like to have one like :

Given

var1, var2, var3

Produce

self.var1 = var1
self.var2 = var2
self.var3 = var3

I currently know how to replace commas with line jump but not how to replace each word with another string. I'm pretty bad at regular expressions so it doesn't help. I think I'll need something that does the following :

var1, var2 -> self.var1 = var1, self.var2 = var2

Thanks for your help

Edit : From suggestions in comments I tried this : /(.*,)/self.$0 = $0/ It obviously doesn't work for several reasons : it matches all strings up to the last comma. VSCode doesn't give access to "\w" but i don't see how it would help. Other thing I tested that couldn't work either since I'm looking for duplicating each of the words : /(.*)/self.$0 = $0/

And since I didn't post it, here is the comme replacement by a new line : /[,]/\n/g

Edit2 (updated) : From comment suggestions I tried : /(.*?)(?:, |$)/self.$1 = $1\n/g which leads to almost perfect result :

toto, titi, tata

leads to

self.toto = toto
self.titi = titi
self.tata = tata
self. = 
Ricocotam
  • 41
  • 7
  • Please let us know what you tried to see where the issue is. – Wiktor Stribiżew Mar 10 '20 at 14:50
  • 1
    I actually don't know how to try anything. As I said, I can replace commas with line jump (which is quite easy) but I don't know where to start. I'd like to select the beginning of each word and replace it with "self." as well as duplicating each word and appending an "=" before. But I don't know how to do it – Ricocotam Mar 10 '20 at 14:52
  • Then [this](https://stackoverflow.com/questions/39837571/how-to-add-a-string-to-the-end-of-each-line-in-vs-code-using-regex) will give you a jumpstart. [Here](https://stackoverflow.com/questions/22937618/reference-what-does-this-regex-mean), you will find all the rest. – Wiktor Stribiżew Mar 10 '20 at 14:55
  • 1
    Ok, so this doesn't help at all since I already went through the entire regex doc of JS and Python. I want ti duplicate a word and insert string before/after it. None of the thing I read answers this nor leads to an idea. – Ricocotam Mar 10 '20 at 15:08
  • Why? Look, the first post tells you how to duplicate: once there is a match, `$0` is the backreference to the whole match. When you use it in the replacement pattern, you basically insert the match value. All you need is now a pattern to match what you need. If you need to match any word, use `\w+` (and that is clear once you open any basic regex tutorial, see http://regexone.com, e.g.) – Wiktor Stribiżew Mar 10 '20 at 15:10
  • 1
    Ok so it was not clear at all since you linked something to add string at the end of a line. I tested what you explained but it does not work since I am matching any word, just as you said. But what I want is to duplicate each of the words : "toto, tata, titi" should give "toto toto, tata tata, titi titi" and it gives "toto, tata, titi toto, tata, titi" – Ricocotam Mar 10 '20 at 15:16
  • Very good, please update the question with what you tried, what you got, and what you expected to get. – Wiktor Stribiżew Mar 10 '20 at 15:21
  • 1
    Try the following: /(.*?)(?:, |$)/self.$0 = $0\n/ – Harm van der Wal Mar 10 '20 at 15:26
  • 1
    I think we have something here, thanks @HarmvanderWal. Sadly it doesn't exactly work. I'll update the question – Ricocotam Mar 10 '20 at 15:31
  • 1
    Sorry, I matched the wrong group. It should be: /(.*?)(?:, |$)/self.$1 = $1\n/ – Harm van der Wal Mar 10 '20 at 15:33
  • 1
    Due to VSCode limitations, it seems I can't to use \1 ($1 is already used for another purpose) but your fix almost works – Ricocotam Mar 10 '20 at 15:34
  • 1
    $0 is the full match on the regex. $1 is just the first captured group. How do you have $1 with another purpose? This is all I can do with the limited information you gave. – Harm van der Wal Mar 10 '20 at 15:36
  • 1
    In VSCode snippets $1 is a place holder for the cursor (multicursor edition) and tab-stop functionnality. Thanks a lot, it honestly almost works, I'll try on VSCode forums/github to know is someone has an idea. You awesome @HarmvanderWal – Ricocotam Mar 10 '20 at 15:38
  • 1
    All for the upvotes ;) Also: to not match on empty lines, try the following: /(.+?)(?:, |$)/self.$1 = $1\n/ – Harm van der Wal Mar 10 '20 at 15:39
  • 1
    My bad, using $1 actually works. I'll update the post but I still have an issue. An extra line is added – Ricocotam Mar 10 '20 at 15:43
  • If you want do have it done in 1 regex, this is the best I can do. If you use 2, it's a lot easier: 1: /, /\n/ 2: /^.+$/self.$0 = $0/ – Harm van der Wal Mar 10 '20 at 15:48
  • Use `\s*([^,\s]+)(?:,|$)` and replace with `self.$1 = $1\n` – Wiktor Stribiżew Mar 10 '20 at 15:57

2 Answers2

3

Add the following to your python.json snippet file

  "var-init": {
    "prefix": "varinit",
    "body": [
      "${1/([\\w_]+)(?:[,\\s]|$)/self.$1 = $1\n/g}",
      "$0"
    ],
    "description": "var initialisation"
  }
  • Type the prefix: varinit
  • Press Tab
  • Type the variables you want separated by , with or without spaces: titi,tata,toto
  • Press Tab

Result

self.titi = titi
self.tata = tata
self.toto = toto

And the cursor on the next line.

Edit

A simplification of the regex and using the tip from Mark about the if-replacement ${2:+\n}

"${1/([\\w_]+)([, ])*/self.$1 = $1${2:+\n}/g}"

now the variables can be separated with spaces or ,

rioV8
  • 12,369
  • 2
  • 12
  • 26
  • 1
    Looks familiar... I would suggest ` "${1/\\s*([^,]+)(,)*/self.$1 = $1${2:+\n}/g}",` as the regex is a little simpler and it doesn't add an extra newline after the last variable. And the spaces are handled much better. I get spaces added to the beginning of subsequent lines with your code. – Mark Mar 10 '20 at 16:59
  • 1
    It is also easy to modify this to where the variables are already listed and selected. If that is a use case for the OP. For more complicated cases of using variable numbers of arguments in a class constructor snippet see https://stackoverflow.com/questions/53998252/vscode-snippet-add-variable-number-of-objects-to-a-class-constructor/58459793#58459793 and for a class initializer see https://stackoverflow.com/questions/58225204/make-a-vscode-snippet-that-can-use-a-variable-number-of-arguments/58228253#58228253 – Mark Mar 10 '20 at 17:05
0

You may use

Find What: \s*([^,\s]+)(?:,|$)
Replace With: self.$1 = $1\n

See the regex demo.

Details

  • \s* - 0 or more whitespaces
  • ([^,\s]+) - capturing group 1: one or more chars other than whitespace and comma
  • (?:,|$) - a non-capturing group matching , or end of line.

enter image description here

Wiktor Stribiżew
  • 484,719
  • 26
  • 302
  • 397