【MATLAB/Simulink】コメントアウトを探して削除するスクリプトを作ってみた

# あらすじ

Simulinkモデルを書き進めていくと、テキスト言語と同様にコメントアウトがどんどん溜まっていきます。幸い、Simulink（というかMATLAB）でコメントアウトを探すことができ、それらの一斉削除も容易です。しかしその中には当然他人が残したものもあり、それらを削除していいかどうかは自分では判断できません。

そこで、モデルに残されたコメントアウトをひとつずつ検索していき、削除もしくは削除しない、の判断が可能なツールを作成します。


# 環境

・MATLAB 2015b
・Simulink 8.6

# 実際に使ってみる

作成したスクリプトを、下記Simulinkモデル「test_co.slx」に対して使用してみます。
このモデルは、各階層にブロックやサブシステムのコメントアウトが散りばめられています。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/ccb575cd-9130-53fd-8954-dd0fd3a53de3.png)


まず、スクリプトを実行します。モデル中の全コメントアウトがリストに記載されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/cd7471b4-483b-6fd0-de8e-34f5e4a2242a.png)

次にリストに追加されたコメントアウトをクリックすると、その場所にジャンプしてクリック対象が青く強調表示されます。GUIの方には「削除して次を検索」ボタンと「削除せずに次を検索」ボタンが新たに表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/7c26e66a-e09d-0e74-895c-5010f5770549.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/0e2e10c5-0386-a158-3ae6-6c59f94ad9e6.png)

「削除して次を検索」を押すと、Simulink上で対象のコメントアウトが削除され、リストからも消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/c4e2b06e-8826-5cba-1e64-a5517266893a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/6254f443-1663-751d-5d33-bb1f35b41316.png)

「削除せずに次を検索」を押すと、単に強調の対象が次のブロックに移ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/d7581a5e-48e8-fdfd-6d59-f2fce0df8c99.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/93f11d63-4ea3-5ede-0b9a-cf8e3e34a593.png)

どんどん削除していくと、最後には以下のように表示されます。
（最初からコメントアウトが存在しない場合も、同様の表示がなされます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271833/c4eaba4b-5cf1-e4db-01e6-3456b8f92b43.png)


# ソース

```matlab:delete_comment_out.m

function delete_comment_out

    % リスト上のブロック/サブシステムをクリック時、そのブロック/サブシステムを強調する
    function go_to_commented_out(source, command)
        
        if ~strcmp(source.String, nocomsg) % コメントアウトが存在する場合
            if prvco ~= 0 && ~strcmp(command, 'delete') 
                % 前回強調したブロックを、元の状態に戻す
                hilite_system(source.String(prvco), 'default');
            else
                % 特定のブロック/サブシステムが強調状態になって初めて、削除ボタンなどを表示する
                dlt_next.Visible  = 'on';
                just_next.Visible = 'on';
            end

            % ブロックを強調
            hilite_system(source.String(source.Value), 'user1');

            prvco = source.Value; % 今回強調したブロックを、前回値として保存
        end
    end

    % 現在強調しているコメントアウトを削除して次のコメントアウトを強調
    function delete_block_and_next_block(~, ~)
        
        % リストの一番下以外のコメントアウトを強調している時
        if tgtbox.Value < size(tgtbox.String, 1)
            
            curco = tgtbox.Value; % リスト上で強調中のブロック/サブシステム番号を保存
        else  % 一番下を強調している時
            curco = 1;
            tgtbox.Value = curco; % リストの最初に戻る
        end
        
        delete_block(tgtbox.String(tgtbox.Value));
        
        % コメントアウトされたブロック/サブシステムを再取得（削除したコメントアウトをリストから除くため）
        list = find_system('test_co', 'IncludeCommented', 'on', 'Commented', 'on');

        if isempty(list) % コメントアウトが１つもない場合
        
            list = nocomsg;
        end
        tgtbox.String = list;    
        tgtbox.Value = curco;
        
        go_to_commented_out(tgtbox, 'delete'); % 次のブロック/サブシステムを強調
    end
    
    % 現在強調しているコメントアウトを削除しないで次のコメントアウトを強調
    function go_next_block(~, ~)
        
        % リストの一番下以外のコメントアウトを強調している時
        if tgtbox.Value < size(tgtbox.String, 1)
    
            tgtbox.Value = tgtbox.Value + 1; % リスト上の次のブロック/サブシステムを強調
        else % 一番下を強調している時
            tgtbox.Value = 1; % リストの最初に戻る
        end
        
        go_to_commented_out(tgtbox, 'go_next'); % 次のブロック/サブシステムを強調
    end

    % Simulinkモデルを読み込み
    load_system('test_co');
    
    % コメントアウトされたブロック/サブシステムを取得
    list = find_system('test_co', 'IncludeCommented', 'on', 'Commented', 'on');
    
    figure('Name', 'コメントアウト削除ツール', 'Position', [300, 150, 600, 370]);
    
    prvco = 0; % 前回強調していたブロック/サブシステムの番号
    nocomsg = '** コメントアウトされているブロック/サブシステムはありません。 **';
    
    if isempty(list) % コメントアウトが１つもない場合
        list = nocomsg;
    end
        
    % ブロックの強調/強調解除の設定
    set_param(0, 'HiliteAncestorsData',... 
                    struct('HiliteType', 'user1', ... 
                           'ForegroundColor', 'darkGreen', ... 
                           'BackgroundColor', 'lightBlue'));
    set_param(0, 'HiliteAncestorsData', ... 
                    struct('HiliteType', 'default', ... 
                           'ForegroundColor', 'black', ... 
                           'BackgroundColor', 'white'));
    
    uicontrol('Style', 'text', 'String', 'コメントアウトされたブロック/サブシステムを以下に表示', 'Position', [35, 335, 250, 20]);
    tgtbox = uicontrol('Style', 'listbox', 'String', list, 'Position', [35, 45, 525, 250], 'Callback', @go_to_commented_out);
    dlt_next  = uicontrol('Visible', 'off', 'Style', 'pushbutton', 'String', '削除して次を検索', 'Position', [35, 305, 110, 25], 'Callback', @delete_block_and_next_block);
    just_next = uicontrol('Visible', 'off', 'Style', 'pushbutton', 'String', '削除せずに次を検索', 'Position', [170, 305, 110, 25], 'Callback', @go_next_block);
end

```

# 参考にさせていただいた情報

本記事執筆のために、下記サイト様の情報を参考にさせていただきました。

|内容|リンク先|
|---|---|
|MATLABによるSimulink中の全コメントアウト削除|http://blog.smooth-works.net/archives/3343|

# 最後

ご指摘・改善案・間違い指摘、大歓迎です。どしどしいただければ喜びに舞い、技術の海に溺れます。