// created by momotaro
/*------------------------------------------------------------------------------
= 数値のリナンバを行うスクリプト。
== 使い方。
 :<range>run renum [step]

: step
リナンバする際のステップ数を指定します。
未指定時は1が設定されます。

== 標準の :renum との違い。
* BOX選択内の数値のみリナンバの対象とすることが可能。
* 2バイト数値に対応。
* 引数の意味が違う。
  :renumは指定したn番目の数値がリナンバされます。

== exmapしちゃえ。
って人はこんな感じで。
これで、標準の:renumが完全に置き換えられると思われ。

exmap renumber run renum
exmap renumbe run renum
exmap renumb run renum
exmap renum run renum
exmap renu run renum
exmap ren run renum

*/

//指定行の文字列を数値部分、前、後ろに分割して返す。
function getString( line, param )
{
	var lineStr = thisView.getLineString(line);
	var buf;
	var findTarget;

	if ( param.column.to >= 0 ) {
		var offset;
		offset.from = thisView.columnToOffset(line, param.column.from);
		offset.to   = thisView.columnToOffset(line, param.column.to) + 1;

		findTarget = lineStr.substring(offset.from, offset.to);
		buf.before = lineStr.left(offset.from);
		buf.after  = lineStr.substr(offset.to);
	} else {
		findTarget = lineStr;
		buf.before = "";
		buf.after = "";
	}

	if ( findTarget =~ /(\d+|[0-9]+)/ ) {
		buf.before = buf.before + $`;
		buf.number = $&;
		buf.after  = $' + buf.after;
	} else {
		buf.before = lineStr;
		buf.number = "";
		buf.after = "";
	}
	return buf;
}

//設定取得
function getParam()
{
	var param;

	//範囲指定
	if ( thisView.isBoxSelected() ) {
		//Box選択時
		var sel = thisView.getSelectedRange();
		param.line.from		= sel.line1;
		param.line.to		= sel.line2;
		param.column.from	= sel.column1;
		param.column.to		= sel.column2;

	} else {
		//それ以外
		param.line.from		= __range.from;
		param.line.to		= __range.to;
		param.column.from	= 0;
		param.column.to		= -1;
	}

	//増分値
	if ( __argv.getCount() == 2  ) {
		param.step = __argv[1].toInteger();
	} else {
		param.step = 1;
	}

	//変換の仕方(範囲の一行目から判断する)
	var buf, i;
	for (i = param.line.from; i <= param.line.to; i++) {
		buf = getString( i, param );
		if ( buf.number == "" ) continue;

		//開始値
		param.first = buf.number.translate(7).toInteger();

		//全角か半角か
		param.zenkaku = (buf.number =~ /[0-9]/);

		//ゼロ埋めする場合の桁数(ゼロ埋めしない場合は-1)
		if ( buf.number.regexpFind( /^[00]/ ) == 0 ) {
			param.keta = buf.number.length();
			if ( param.zenkaku ) param.keta /= 2;
		} else {
			param.keta = -1;
		}

		//処理開始行を次の行からにする
		param.line.from = i + 1;

		//チェックができたのでループを抜ける。
		break;
	}

	return param;
}

//メイン処理
function main()
{
	var param = getParam();

	//選択範囲クリア
	thisView.clearSelected();

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

	var i, buf;
	for (i = param.line.from; i <= param.line.to; i++) {
		buf = getString( i, param );
		if ( buf.number == "" ) continue;

		//インクリメント
		param.first += param.step;
		buf.number = param.first.toString();

		//頭ゼロ埋め
		if ( param.keta >= 0 ) {
			buf.number = "0".repeat( param.keta - buf.number.length() ) + buf.number;
		}

		//全角化
		if ( param.zenkaku ) {
			buf.number = buf.number.translate(6);
		}

		//値変更
		vicmd(i + "G0C" + buf.before + buf.number + buf.after + "\x1b");
	}

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

/*------------------------------------------------------------------------------
= なんとなくバージョン管理。
== Ver.0.04(2003/12/05)
* 一度にundoされるようにした。

== Ver.0.03(2003/12/05)
* 000から始まる数値をゼロ埋めリナンバできなかった問題を修正。
* 範囲選択して :'<,'>run renum とすると正しくリナンバされない問題を修正。

== Ver.0.02(2003/12/05)
* getBoxSelected()が使えるようになったので、微修正

== Ver.0.01(2003/12/03)
* #17xx対応版として移行。

== Ver.0.00(随分昔)
* 作成。

= そしてTODO。
* __range指定がないときは、isSelected()していればその範囲でリナンバしたほうがいいかなぁ。
------------------------------------------------------------------------------*/