web404

HTMLの終了タグを補完するマクロ

カーソル位置で閉じられていないHTML要素の終了タグを挿入します。

マクロで定義されている終了タグを補完しない要素以外の要素について、カーソル位置からファイル先頭に向かって開始タグと終了タグの数を比較し、閉じられていない要素の終了タグを挿入します。
手軽に終了タグを補完する目的で作ったマクロなので、HTMLの文法に関係なく、積極的に終了タグを補完します。
要素名は編集中のファイルから取得しているので、未知の要素でも終了タグを補完します。

このマクロにショートカットキーを割り当てて使います。
開始タグさえ入力すれば、終了タグの入力はすべてこのマクロで行えます。

ダウンロード

endtag.zip

ソースコード

//設定
//終了タグを補完しない要素を「|」で区切って指定
$ve = "area|base|br|col|embed|hr|img|input|keygen|link|param|source|track|meta|wbr";	//空要素

setcompatiblemode 0x20200;
#x = x; #y = y;
#sel = 0;
disabledraw;

if (selecting) {
	#sel = 1;
	#xt = seltopx; #yt = seltopy; #xe = selendx; #ye = selendy;
	escape;
}

call CheckTagArea;

while (1) {
	searchup "<(?!" + $ve + ")[a-z][a-z0-9]*( [^>]+)?>", regular, nocasesense;
	if (!result) {	//終了タグが必要な開始タグが見つからなければ警告音で終了
		if (x != #x || y != #y) moveto #x, #y;
		beep;
		goto End;
	}
	$str = gettext(x, y, #x, #y);	//開始タグからカーソル位置までの文字列
	$tag = gettext(x, y, selendx, selendy);	//開始タグ
	#len = strstr($tag, " ") - 1;	//要素名の長さ
	if (#len < 0) #len = strlen($tag) - 2;
	$en = midstr($tag, 1, #len);	//要素名
	call CheckElement $str, $en;
	if (##return) break;
}

if (#sel) {
	moveto #xt, #yt;
	beginsel;
	moveto #xe, #ye;
	endsel;
} else moveto #x, #y;
insert "</" + $en + ">";

goto End;

CheckTagArea:	//カーソルがタグ内にあれば警告音で終了
	##x = x; ##y = y;
	searchup "<[a-zA-Z/]", regular;
	if (result) {
		##xr = x; ##yr = y;
		searchdown "[^ <=>?-]>", regular;
		if (result) {
			moveto selendx, selendy;
			if ((##y > ##yr || (##x > ##xr && ##y == ##yr)) && (##y < y || (##x < x && ##y == y))) {
				moveto ##x, ##y;
				beep;
				goto End;
			}
		}
		moveto ##x, ##y;
	}
	return;

CheckElement:	//指定文字列における指定要素のタグの対応を調べる
	call Count $$1, "<" + $$2 + " ";
	##stag = ##return;	//開始タグの数
	call Count $$1, "<" + $$2 + ">";
	##stag = ##stag + ##return;
	call Count $$1, "</" + $$2 + ">";
	##etag = ##return;	//終了タグの数
	##open = 0;
	if (##stag > ##etag) ##open = 1;
	return ##open;

Count:	//文字列の出現回数を調べる
	$$str = $$1;	//検索対象文字列
	##n = strstr($$1, $$2);	//文字列の出現位置
	##len = strlen($$2);	//文字列長
	##i = 0;
	while (##n > -1) {
		##i = ##i + 1;
		$$str = midstr($$str, ##n + ##len);	//未検索文字列
		##n = strstr($$str, $$2);
	}
	return ##i;

End:	//終了処理
	enabledraw;
	endmacro;

開始タグと終了タグの数を比較するだけで判定しています。
終了タグの省略や文法の正しさは考慮していません

個人的にも、終了タグを省略すると見づらくなったり不具合のもとになるので、省略しない派です。
もし特定の終了タグを省略する場合は、マクロファイルの設定項目に終了タグを補完しない要素を追加してください。

文法の検証はきりがないので、一切していません。
結局、文法は本人がわかっていないとマズいと思います。
編集の過程で、一時的に文法が正しくない状態になることもありますし。
逆に、おかしな終了タグが挿入されたら、そこまでの文法に誤りがあるとわかります。