/*
	縦位置揃え 複数列対応&デリミタ自動選択
	デリミタは事前に設定したものの中から自動判別します
	PukiWikiのテーブルや、複数行にわたる配列の初期化子などに、幅広く使えます
	written by Nickle 2007/4/21-

	動作例

	|a|bbb|c|h                    |a  |bbb  |c  |h
	|aaa|   bb|ccc|          -->  |aaa|   bb|ccc|
	|aaa|b|cc|                    |aaa|b    |cc |

	a   ,bb,cccc                  a   ,bb ,cccc
	aa,b,c                   -->  aa  ,b  ,c
	a,bbb,cc                      a   ,bbb,cc

	const char* array[] = {       const char* array[] = {
	    "a", "b", "c",                "a"  , "b"   , "c" ,
	    "aaa", "b", "cc",    -->      "aaa", "b"   , "cc",
	    "aa", "bbbb", "c",            "aa" , "bbbb", "c" ,
	};                            };

	// 各要素の先頭・末尾の空白を削除すると、こういう場合に綺麗にいかない
	int i = 0;                    int i            = 0;
	int abc = 1;             -->  int abc          = 1;
	int longlonglong = 2;         int longlonglong = 2;

	仕様
	・矩形選択は非対応です
	・デリミタは、delimitersの中から最初に現れたものを選択します
	・タブは考慮しません。必要なら空白<->タブ変換と組み合わせて使うと吉です
*/

// 設定 --------------------------------------------------------------

// デリミタ候補。優先度の高い順に並べてください
var delimiters = [ "|", ",", "=" ];

// 各要素の先頭・末尾の空白を削除するかどうか
// (有効にするなら、インデントなど意図して入れてある場合に注意)
var removeLeadingSpace = false;
var removeTrailingSpace = false;

// ここまで ----------------------------------------------------------

var delimiter = "";
main();

function main()
{
	if(Editor.IsTextSelected() == 0)
		return;

	var lines = getSelectedLines();

	// デリミタ決定
	outer:
	for(i in delimiters)
	{
		for(j in lines)
		{
			if(lines[j].indexOf(delimiters[i]) != -1)
			{
				delimiter = delimiters[i];
				break outer;
			}
		}
	}

	if(delimiter == "")
		return;
	
	// Editor.InsText(delimiter);
	
	// 各列の最大幅取得
	var maxWidth = new Array;
	for(i in lines)
	{
		var cols = getCols(lines[i]);

		// デリミタがひとつもない行
		if(cols.length == 1)
			continue;

		for(j in cols)
		{
			if(maxWidth[j] == null)
				maxWidth[j] = bytes(cols[j]);
			else
				maxWidth[j] = Math.max(maxWidth[j], bytes(cols[j]));
		}
	}

	// Editor.InsText(maxWidth.join(","));

	// 最大幅に合わせて整形
	var out = new Array;
	for(i in lines)
	{
		var cols = getCols(lines[i]);

		// デリミタがひとつもない行
		if(cols.length == 1)
		{
			out.push(lines[i]);
			continue;
		}

		// 各列に空白を入れる
		var newCols = new Array;
		for(j in cols)
		{
			var s = cols[j];
			assert(bytes(s) <= maxWidth[j]);
			
			newCols[j] = s;
			for(var i=0;i<maxWidth[j] - bytes(s); i++)
				newCols[j] += " ";
		}

		// 行全体を生成
		out.push(newCols.join(delimiter).replace(/\s+$/, ""));

		/*
			"|a|b|c|".split("|") => ("", a, b, c, "")
			("", a, b, c, "").join("|") => |a|b|c|
			ということで、先頭や末尾のデリミタも気にしなくてOK。幸せだ
		*/
	}

	Editor.InsText(out.join(newLine()));
}

function assert(cond)
{
	if(!cond)
		throw new Error("assertion failed!", cond);
}

function newLine()
{
	switch(Editor.GetLineCode())
	{
		case 0: return "\r\n";
		case 1: return "\r";
		case 2: return "\n";
	}
}

function getSelectedLines()
{
	var lines = Editor.GetSelectedString(0).split(newLine());
	return lines;
}

// thx to Macro-BBS[341]
function isWide(charCode)
{
	return 0x80 <= charCode && (charCode <= 0xff60 || 0xffa0 <= charCode);
}

// Shift-JIS換算のバイト数(=画面上の表示桁数)を返す
function bytes(str)
{
	var bytes = 0;
	for (var i=0;i<str.length;i++)
	{
		var ch = str.charCodeAt(i);
		if (isWide(ch))
			bytes += 2;
		else
			bytes += 1;
	}
	return bytes;
}

function getCols(line)
{
	var cols = line.split(delimiter);

	// 各列になにか操作したければここで
	for(i in cols)
	{
		if(removeLeadingSpace)
			cols[i] = cols[i].replace(/^\s+/, "");

		if(removeTrailingSpace)
			cols[i] = cols[i].replace(/\s+$/, "");
	}

	return cols;
}