On May 01, 2006, Yakov Lerner pointed out: >On 5/2/06, Suresh Govindachar wrote: >> >> Yakov Lerner wondered: >> >>> But how do you remove #ifdef blocks? I mentioned piping >>> because there is ready utility, 'unifdef', that removes some >>> or all of #if blocks. >> >> Isn't there a way to do a multi-line substitution: >> >> :%s/^\s*#ifdef .*^\s*#endif// >> >> where the *s are multi-line and non-greedy, or maybe I should >> say the *s are non-greedy and the . is multi-line? (I >> haven't actually tried, but I am confident I can do it in >> perl.) > > What if #if/#endif blocks are nested ? [In the above pseudo :%s expression, replace ifdef by just if.] I can think of three approaches, the second and third of which I have tested successfully. While the third is elegant for deleting #if/#endif blocks, the second is much more flexible.
1) Have . not match ^\s*#if -- so that we can get rid of inner-most #if/#endif blocks. Repeat this in a while loop till there are no more ^\s*#if in the buffer. 2) I successfully tested the following all-in-one-line command: :perl my $skip=0; my @extract=(); foreach my $line ($curbuf->Get(1 .. VIM::Eval('line("$")'))) { $line =~ /^\s*#if/ and $skip++; $skip or push @extract, $line; $line =~ /^\s*#endif/ and $skip--;} VIM::DoCommand('new'); $curbuf->Append(1, @extract); VIM::DoCommand('1d'); with a file that looked like (note the nested, unaligned #if): stay stay, next blank too #if go away, previous blank too go away, previous blank too go away #if go away go away, previous blank too #endif some more go away #endif stay, previous blank too stay stay, previous blank too stay very last stay 3) The following works on the above example :%/^\s*#if/normal d%dd Of course, the perl solution can be translated to other languages, including viml. --Suresh