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