vim bag of tricks:如何找到有效的C预处理条件

时间:2013-11-29 16:31:29

标签: c perl vim preprocessor-directive

当我编辑C源文件时,我经常发现自己想要知道哪些C预处理条件在给定行有效,即在

#if FOO
 /* FOO is active */
#elif BAR
 /* here only BAR is active */
#else
 /* here NOT BAR is active */
#endif
#if BAZ
#if ZAP
  /* Here BAZ and ZAP are active */
#endif
  /* Only BAZ active */
#else
  /* NOT BAZ */
#endif
  /* Nothing active */

你明白了。我写了一个小的perl脚本来输出给定行的活动预处理条件,每行一个:

#!/usr/bin/env perl
#
# ppcond.pl - find active preprocessing conditionals
# usage: ppcond.pl file.c line_no

use warnings;
use diagnostics;
use strict;

my ($file, $line) = @ARGV;
my $line_number = 1;
my @ppc_stack = ();

open my $FILE, '<', $file
    or die "cannot open $file for reading: $!";
while (<$FILE>) {
    if ($line_number++ > $line) {
        print @ppc_stack;
        last;
    }
    if (/^\s*#\s*(if|ifdef|ifndef)/) {
        push @ppc_stack, $_;
    }
    elsif (/^\s*#\s*elif/) {
        $ppc_stack[$#ppc_stack] = $_;
    }
    elsif (/^\s*#\s*else/) {
        $ppc_stack[$#ppc_stack] = "NOT $ppc_stack[$#ppc_stack]";
    }
    elsif (/^\s*#\s*endif/) {
        pop @ppc_stack;
    }
}
close $FILE;

从vim中调用它很容易,但将它重写为vim函数而不是perl的shell会很好。我的vim-fu尚未发展到足以解决这个问题。主人甚至可以弹出一个带有结果的上下文窗口吗?

1 个答案:

答案 0 :(得分:2)

这应该可以解决问题:

function! ConditionalsInPlay()
    let ppc_stack=[]
    for cline in range(1, line('.'))
        let str = getline(cline)
        if (match(str, '\v^\s*#\s*(if|ifdef|ifndef)') >= 0)
            let ppc_stack += [str]
        elseif (match(str, '\v^\s*#\s*elif') >= 0)
            let ppc_stack[-1] = str
        elseif (match(str, '\v^\s*#\s*else') >= 0)
            let ppc_stack[-1] = 'NOT ' . ppc_stack[-1]
        elseif (match(str, '\v^\s*#\s*endif') >= 0)
            call remove(ppc_stack, len(ppc_stack) - 1)
        endif
    endfor
    echo string(ppc_stack)
endfunction