// created by momotaro
/*------------------------------------------------------------------------------
= 指定文字の前に空白を付加して揃えるスクリプト。
== 使い方。
 :<range>run addsp [regexp]

: regexp
この正規表現にマッチする文字の前に空白を付加します。
未指定時は $(行末) となります。

== 特徴。
* プログラムソースの = 位置を併せたり、行コメント開始位置を合せたりするのに便利です。
* タイプ別セッティングのタブ幅やソフトタブの設定を見て、
  現在のドキュメントに合せた出力をします。

*/

var config;

//設定取得
function getConfig()
{
	var config;

	//「Type Settings」→「View」→「タブ幅」
	config.tab_length		= thisView.getTypeSettings().getIntValue("tabWidth");
	//「Type Settings」→「入力・編集」→「ソフトタブ」
	config.soft_tab_flag	= thisView.getTypeSettings().getBoolValue("softTab");
	//「Global Settings」→「検索・grep」→「正規表現:'('は'('にマッチ」
	config.regexp_vi_paren	= globalSettings.getBoolValue("regexpViParen");

	if ( __argv.getCount() > 1 ) {
		config.char = __argv[1];
	} else {
		config.char = "$";
	}
	config.from = __range.from;
	config.to = __range.to;

	return config;
}

/* 指定位置へカーソルを移動 */
function curMove(X, Y)
{
	vicmd(Y + "G" + X + "|");
}

/* 検索してカラム位置を返す */
function regexpFind(str, reg)
{
	var len = 0;
	var pos = str.regexpFind(reg);
	if( pos == -1 ) return -1;
	for( var i = 0; i < pos; i++ ){
		if( str.charAt(i) == '\t' ){
			len += config.tab_length - (len % config.tab_length);
		} else {
			len += 1;
		}
	}
	return len;
}

//メイン
function main()
{
	var i, buf, len, column, sp_size;

	//設定取得
	config = getConfig();

	//揃える位置を取得
	for ( i = config.from; i <= config.to; i++) {
		buf = thisView.getLineString(i);
		len = regexpFind(buf, config.char);

		if ( column < len ) {
			if ( len % config.tab_length == 0 ) {
				column = len;
			} else {
				column = len / config.tab_length * config.tab_length + config.tab_length;
			}
		}
	}

	//undo block開始
	thisView.openUndoBlock();

	//付加する文字の前の不要なスペースを一旦削除
	// :<from>:<to>s/\s*(<char>)/\1/
	var cmd = ":" + config.from + "," + config.to;
	if ( config.char == "$" ) {
		// s/\s*($)/\1/ が動かないので特殊処理に置換
		cmd += "s/\\s*$//\n";
	} else {
		var escape = "";
		// '('が'('にマッチするときは s/\s*\(x\)/\1/ とする必要がある
		if ( config.regexp_vi_paren ) {
			escape = "\\";
		}
		cmd += "s/\\s*" + escape + "(" + config.char + escape + ")/\\1/\n";
	}
	vicmd( cmd );

	//揃える
	for ( i = config.from; i <= config.to; i++) {
		//付加する文字
		buf = thisView.getLineString(i);
		len = regexpFind(buf, config.char);
		if ( len == -1 ) continue;

		//ソフトタブ時はスペース、そうじゃなければタブ文字を作る
		sp_size = column - len;
		if ( config.soft_tab_flag ) {
			buf = " ".repeat(sp_size);
		} else {
			if ( sp_size % config.tab_length == 0 ) {
				sp_size = sp_size / config.tab_length;
			} else {
				sp_size = sp_size / config.tab_length + 1;
			}
			buf = "\t".repeat(sp_size);
		}

		//カーソルを移動して空白挿入
		curMove(len + 1, i);
		if( config.char == "$" ) {
			vicmd("a" + buf + "\x1b");
		} else {
			vicmd("i" + buf + "\x1b");
		}
	}

	//undo block終了
	thisView.closeUndoBlock();

	//マッチ背景色クリア
	vicmd("33064#c");
}

/*------------------------------------------------------------------------------
= なんとなくバージョン管理。
== Ver.0.05(2008/04/01)
* マッチ背景色表示されないようにした。(つださんThanks!)

== Ver.0.04(2008/03/27)
* TypeSettingsのキーが間違っていたのを修正。

== Ver.0.03(2003/12/05)
* 一度にundoされるようにした。

== Ver.0.02(2003/11/末)
* いろいろバグ対応。

== Ver.0.01(2003/11/頃)
* ViVi#17xxに対応。

== Ver.0.00(いつだっけ?)
* 作成。

= そしてTODO。
* 今はないなぁ〜。
------------------------------------------------------------------------------*/