2011年2月8日火曜日

xcode の user scripts でコメントトグルの仕様変更

先の記事に書いたとおり、選択範囲の行頭がコメントかどうかだけで、コメントアウト、アンコメントを切り替えてしまうと、行頭にコメント記号のない行を最初の行として選択してしまった場合に、期待したとおりの結果をうまない。

というわけで、ほんのちょっと仕様変更して、選択した最初の行がコメントであるかどうかを、選択範囲の最初にコメントがあるかどうかではなく、選択範囲の最初の行がコメントであるかどうか(言い回しが難しいけど、要はその行がコメントであるかどうか)で判断するようにしてみた。以下全文。

#! /usr/bin/perl -w
#
# un_commentLines.pl -  Comments or uncomments the selected lines
#   Uses '# ' for Perl and shell scripts; '// ' otherwise

my $outputString = "";
my $perlCmt = "#";
my $cCmt = "//";

# Get the first few lines of the file
my $fileString = <<'HEADTEXT';
%%%{PBXHeadText}%%%
HEADTEXT


# determine the type of file we have by looking for the #! line at the top
# careful--it might already be commented out!
my $commentString;
if ($fileString =~ m!^($perlCmt|$cCmt)?#\!\s*.*?/perl|^($perlCmt|$cCmt)?#\!\s*.*?/sh!) {
 $commentString = $perlCmt;
} else {
 $commentString = $cCmt;
}

my @selection = ;       # read the selection from standard input

# no chars in selection, so create an empty selection
if (!@selection) {
    push @selection, "";
};  

# add or remove comment markers depending on the state of the first line of the selection
# if it is uncommented, comment all lines.  If it is commented, remove comment markers, if present
my $firstLineOfSelection = $selection[0]; #get first line
my $addingCommentsString = 1;
# ※1 この行をコメントして下記のように(\s*?)を活かす
#if ($firstLineOfSelection =~ /^$commentString/) { #selection starts with comment
if ($firstLineOfSelection =~ /^(\s*?)$commentString/) { #selection starts with comment
    $addingCommentsString = 0;
}

foreach my $line (@selection) {
    if ($addingCommentsString == 1) {
        $outputString .= $commentString.$line;
    } else {
# ※2 この行をコメントして下記のように(\s*?)を活かす
#        $line =~ s/^$commentString//;
        $line =~ s/^(\s*?)$commentString//;
        $outputString .= $line;
    }
}

print "%%%{PBXSelection}%%%";
print $outputString;
print "%%%{PBXSelection}%%%";

ご覧のように、選択範囲の先頭がコメント記号であるかどうか、ではなく、選択範囲の先頭から空白(ホワイトスペース、タブ等が含まれる)を無視して、コメント記号が最初にくるか、で判断するように変更した。※1
また、アンコメントする部分も、空白を含めて削除するようにした。※2

これにより、下記のようになった。

  // コメント
  ^ここから選択すると
   コメント
のようになり、
  // コメント
^ここから選択すると
 コメント
のようになる

一旦ここまでで満足していたのだけれど、eclipse (のPDTでしか見てないけど)のコメントトグルは、実は下記のように動く

  // コメント 文面だったりする
               ^ このあたりにカーソルがある場合でも
   コメント 文面だったりする
こんな風にちゃんとその行を見て処理してくれる。頭いい!

これもちゃちゃっと実装できないかなーと思ったのだけど、そもそもこのユーザースクリプトというシロモノ、入力と出力に規定の形があり、cmd+/は、入力が”選択部分”、出力が”選択部分を置き換える”となっており、この例のように選択されていない範囲を適用範囲に加えることができなさそう。。。もちろん、簡単じゃないだけで、何かしら抜け道はあるのだろうけれど。

例えば入力を”書類全体”にし、出力を”書類の内容を置き換える”にして、さらに選択範囲を把握することができれば、書類全体を書き換えてしまうことで対処可能なのかも。さすがにそこまではちょっとよろしくない気がするので、とりあえず置いておく事にするけど。誰かうまいことやったら教えてください。

0 件のコメント:

コメントを投稿