カンマで位置を揃えるjEditマクロ

カンマで区切ってテキストの位置を揃えるjEditマクロを書いてみました。

使用前

[
  {'name':'グレート', 'text':'きみは究極のゲーマーだ', 'score':100},
  {'name':'グッド', 'text':'ここまでやるヤツはなかなかいないぞ', 'score':80},
  {'name':'フェア', 'text':'まあ並みの合格点だね', 'score':50}
]

使用後

[
{'name':'グレート', 'text':'きみは究極のゲーマーだ',             'score':100},
{'name':'グッド',   'text':'ここまでやるヤツはなかなかいないぞ', 'score':80},
{'name':'フェア',   'text':'まあ並みの合格点だね',               'score':50}
]

インデントがなくなってしまうのは、矩形選択モード(Alt+\)で再調整してくださいな。

カンマで位置を揃える.bsh

//text width based on CJK letter width
int widthOf(text) {
    int w = 0;
    for(i = 0; i < text.length(); i++) {
        c = text.charAt(i);
        w += (0x2000 <= c && c < 0xff61) ? 2 : 1; //Fuzzy Zenkaku range
    }
    return w;
}

//replacement for String.split(",")
String[] spritByCommaExactly(text) {
    int numTokens = 1;
    for(i = 0; i < text.length(); i++) {
        if(text.charAt(i) == ',')
            numTokens++;
    }
    tokens = new String[numTokens];
    c = 0;
    p = 0;
    for(i = 0; i < text.length(); i++) {
        if(text.charAt(i) == ',') {
            tokens[c++] = text.substring(p, i).trim();
            p = i + 1;
        }
    }
    tokens[c++] = text.substring(p, i).trim();
    return tokens;
}

String formatTextAlignmentByComma(text) {
    lines = text.split("\n");
    
    //expand text to table form.
    //...and get the max number of columns in table
    table = new String[lines.length][];
    maxTokens = 0;
    for(i = 0; i < lines.length; i++) {
        tokens = spritByCommaExactly(lines[i]);
        table[i] = tokens;
        if(tokens.length > maxTokens) {
            maxTokens = tokens.length;
        }
    }
    
    //calc width for each columns.
    widthArray = new int[maxTokens];
    for(i = 0; i < table.length; i++) {
        tokens = table[i];
        for(j = 0; j < tokens.length; j++) {
            w = widthOf(tokens[j]);
            if(w > widthArray[j]) {
                widthArray[j] = w;
            }
        }
    }
    
    //generate output.
    sb = new StringBuffer();
    for(i = 0; i < table.length; i++) {
        tokens = table[i];
        for(j = 0; j < tokens.length; j++) {
            sb.append(tokens[j]);
            if(j < tokens.length - 1) {
                sb.append(",");
                //padding for the next token
                //it's skipped if the next token is the last and the last token is empty.
                if(!(j == tokens.length - 2 && tokens[tokens.length - 1].equals(""))){
                    pad = widthArray[j] - widthOf(tokens[j]) + 1;
                    for(k = 0; k < pad; k++) {
                        sb.append(" ");
                    }
                }
            }
        }
        sb.append("\n");
    }
    return sb.toString();
}

if(buffer.isReadOnly())
	Macros.error(view, "Buffer is read-only.");
else
	textArea.setSelectedText(formatTextAlignmentByComma(textArea.getSelectedText()));

jEditマクロは日本語ファイル名でも平気でした。~/.jedit/macros に「カンマで位置を揃える.bsh」を保存すれば、マクロメニューに日本語の項目が増えます。

単語の切り方をカスタマイズすれば、より言語に特化したものができるかも。

それにしても、http://d.hatena.ne.jp/tanakahisateru/20080925/1222336816 で書いた「jEditにJRubyを組み込めたら、もっと楽で、日本でもウケるのかな。」って冗談のつもりで言ったけど、どうやら冗談じゃないっぽい。今回のスクリプトで、ほんとにGroovyとかJRubyとか使いたいと思いました。