5

I am new to VSCode. Thinking about code snippets, I looked around for a way to kind of script inside the snippet. I mean to do more than just fill or transform a variable. For example...

This is a simple snippet. I am going to type rci for the class initializer. When I enter the method arguments I would like the assignment and documentation + some other things to happen.

rci<tab> and then def initialize(a, b)) to result in something like this...

attr_reader :a
attr_reader :b

# @param a [...] ...
# @param b [...] ...
def initialize(a, b)
  @a = a
  @b = b
end

Is it possible? How can it be achieved? There could be any number of arguments. And each argument would trigger another line of the class initializer.

Mark
  • 143,421
  • 24
  • 428
  • 436
Ziyan Junaideen
  • 3,270
  • 7
  • 46
  • 71
  • 2
    VSC snippets do not have manipulation by Javascript. ActiveState Komodo does have scripted snippets only it creates the snippet before you fill in the fields based on arguments you supply in the prefix. Your best option is to create N snippets like Mark showed for 2 arguments and call them `rci1` ... `rci5`. – rioV8 Oct 04 '19 at 07:59
  • @rioV8 Yah... afterall how many arguments will an initializer / constructor take... Simpler... – Ziyan Junaideen Oct 07 '19 at 18:01

1 Answers1

12
"Class Initializer": {
  "prefix": "rci",
  "body": [

    "${1/([^,]+)([,\\s]*|)/attr_reader :$1\n/g}",    
    "${1/([^,]+)([,\\s]*|)/# @param $1 [...]${2:+\n}/g}",    
    "def initialize($1)",        
    "${1/([^,]+)((,\\s*)|)/\t@$1 = $1${2:+\n}/g}",
    "end"
  ],

  "description": "Initialize Class"
}

The key to get it to work for any number of method arguments is to get them into the same regex capture group.

Then, with the global flag set, each capture group will trigger the replacement text. So for instance, /attr_reader :$1\n/g will get triggered 3 times if you have 3 method arguments.

You will see this ${2:+\n} in the transforms above. That means if there is a capture group 2, add a newline. The regex is designed so that there is only a capture group 2 if there is another , between arguments. So a final ) after the last argument will not trigger another newline - so the output exactly matches your desired output as to newlines (but you could easily add or remove newlines).

Your input must be in the correct form:

v1, v2, v3

Here is a demo:

demo snippet of multiple arguments

So again the necessary form is just v1 v2 v3. There doesn't need to be a space between the arguments but then you would get def initialize(v1,v2,v3) without spaces either.

Hit Tab after the final argument to trigger completion.

It turns out snippets are pretty powerful!!

For a similar question about using multiple arguments, see VSCode snippet: add multiple objects to a class constructor

Mark
  • 143,421
  • 24
  • 428
  • 436
  • Sorry if I was clear... I want the arguments to the input dynamic. Meaning it will split the string by the comma and based on the segments iterate and add lines there. Is that possible? – Ziyan Junaideen Oct 04 '19 at 06:13
  • 1
    this is a really clever trick, I need to remember this replacement of fields, now I can recreate the python `def __init__` snippet from komodo in VSC – rioV8 Oct 05 '19 at 01:29
  • I changed the snippet substantially to accomplish what you wanted @Ziyan. – Mark Oct 17 '19 at 09:24
  • @rioV8 have you made it work with keyword arguments in __init__ as well? – Zilong Li Aug 05 '20 at 12:09
  • @Gnoliz I made a python __init__ version https://stackoverflow.com/a/63270466/9938317 – rioV8 Aug 05 '20 at 17:26