0

I'm working on applying doctrine/coding-standard on doctrine/orm, and I would like to work smarter.

I would like to search occurences of

 /** * @Id * @Column(type="integer") * @GeneratedValue(strategy="AUTO") */ 

and replace them with

 /** * @var int * @Id * @Column(type="integer") * @GeneratedValue(strategy="AUTO") */ 

My current grepprg is rg\ --vimgrep\ --smart-case, so I tried :gr '/\*\*\n \* @Id\n \* @Column.*"integer"\)\n \* @GeneratedValue.*\n \*/' --multiline tests/ (I'm planning to use :cdo … after that, which should be easy enough.

It finds the occurences alright, but it formats them in such a way that each line of the matched block is considered a separate occurence, like this:

tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:109:5: /** tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:110:5: * @Id tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:111:5: * @Column(type="integer") tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:112:5: * @GeneratedValue(strategy="AUTO") tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:113:5: */ tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:189:5: /** tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:190:5: * @Id tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:191:5: * @Column(type="integer") tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:192:5: * @GeneratedValue(strategy="AUTO") tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:193:5: */ 

That will not work well with :cdo I'm afraid. Maybe it would work if rg '/\*\*\n \* @Id\n \* @Column.*"integer"\)\n \* @GeneratedValue.*\n \*/' --multiline tests/ --vimgrep printed the following instead:

tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:109:5: /** * @Id * @Column(type="integer") * @GeneratedValue(strategy="AUTO") */ tests/Doctrine/Tests/ORM/Functional/Ticket/DDC881Test.php:189:5: /** * @Id * @Column(type="integer") * @GeneratedValue(strategy="AUTO") */ 

How would you do such a complicated search and replace?

4
  • Probably I would grep something smaller and cdo a function call that checks for the whole pattern. Commented Feb 13, 2021 at 14:27
  • Ah so for some reason it would work with grep? Interesting, let me try! Commented Feb 13, 2021 at 17:23
  • 🤔 It does not seem that grep is able to do that: stackoverflow.com/questions/2686147/… Commented Feb 13, 2021 at 17:39
  • 1
    No, I would :grep a single-line patter, and then do :cdo call F() where F examines the next few lines for a match and then applies the transformation. The -r trick is nice though. Commented Feb 13, 2021 at 19:33

1 Answer 1

0

Answering my own question: It's a bit hackish, but you can hijack ripgrep's --replace flag, you can essentially replace each match with a single line one, producing the desired effect. In the end, what I did is the following:

:gr '/\*\*\n \* @Id\n \* @Column.*"integer"\)\n \* @GeneratedValue.*\n \*/' --multiline tests/ -r 'whatever, it does not matter' :cdo call append('.', ' * @var int') | update 

In more generic terms, _if ripgrep is your grepprg:

:gr 'some multiline pattern' --multiline tests/ -r 'whatever, it does not matter' :cdo the colon command you want to execute for each occurence | update 

The same does not seem to be doable with grep.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.