web404

HTMLタグを状況に応じて削除するマクロ

カーソル位置と選択状況をもとに、HTMLタグを削除します。
基本的に、カーソル位置を含む要素の開始タグと終了タグを削除します。
範囲選択していれば、選択範囲内のタグをすべて削除します。

範囲選択では、コメントやPHPのタグも削除します。
BOX選択にも対応しています。
ただし、複数選択には非対応です。

範囲選択の有無による2つの削除機能は、完全に別物です。
タグを単独で削除したい場合は、範囲選択してもいいですが、HTMLタグを選択するマクロを使って削除したほうが早いです。


ダウンロード

delete_tag.zip


更新履歴

Version 1.10 (2025/2/15)
範囲選択に関する修正
不要な処理の削除
ソースコードの整理
過去の履歴
Version 1.01 (2024/2/25)
空要素の定義を削除
Version 1.00 (2023/12/14)
公開

ソースコード

setcompatiblemode 0x20200;
disabledraw;
begingroupundo;

if (selecting) goto DeleteSelected;
goto DeletePair;

DeleteSelected:	//選択範囲内のタグを削除
	#xt = seltopx; #yt = seltopy; #xe = selendx; #ye = selendy;
	#rect = rectselecting;
	#r = 0;
	
	escape;
	moveto #xe, #ye;
	
	while (1) {
		searchup "<[a-zA-Z!/?]", regular;
		if (!result) break;
		#xr = x; #yr = y;
		$str = gettext2(column, lineno, column + 4, lineno);
		if (!strstr($str, "<!--")) searchdown "-->";
		else if (!strstr($str, "<?")) searchdown "?>";
		else searchdown "[^ <=>?-]>", regular;
		if (result) {
			moveto selendx, selendy;
			if ((#rect && (#xt <= #xr && #xr < #xe && #yt <= #yr
			 && #xt < x && x <= #xe && y <= #ye))
			 || ((!#rect) && ((#yt < #yr || (#xt <= #xr && #yt == #yr))
			 && (y < #ye || (x <= #xe && y == #ye))))) {
				#r = 1;
				beginsel;
				moveto #xr, #yr;
				delete;
				continue;
			}
			moveto #xr, #yr;
		}
		if (y < #yt || (x < #xt && y == #yt)) break;
	}
	
	moveto #xt, #yt;
	if (!#r) beep;
	
	goto End;

DeletePair:	//カーソル位置を含む要素の開始タグと終了タグを削除
	#x = x; #y = y;
	
	while (1) {
		searchup "<[a-zA-Z][a-zA-Z0-9]*( [^>]+)?>", regular;
		if (!result) {
			if (x != #x || y != #y) moveto #x, #y;
			beep;
			goto End;
		}
		#xr = x; #yr = y;
		$stag = gettext(x, y, selendx, selendy);	//開始タグ
		#len = strstr($stag, " ") - 1;	//要素名の長さ
		if (#len < 0) #len = strlen($stag) - 2;
		$en = midstr($stag, 1, #len);	//要素名
		$etag = "</" + $en + ">";	//終了タグ
		while (1) {
			searchdown $etag;
			if (!result) break;
			moveto selendx, selendy;
			$str = gettext(#xr, #yr, x, y);	//開始タグから終了タグまでの文字列
			call CheckElement $str, $en;
			if (##return) break;
		}
		if (result && (#y < y || (#x < x && #y == y))) break;
		moveto #xr, #yr;
	}
	
	searchup $etag;
	delete;
	moveto #xr, #yr;
	searchdown2 $stag;
	delete;
	
	goto End;

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

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

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

範囲選択による削除は、タグの先頭と末尾が選択範囲に含まれているかどうかで判定しています。
複数行にわたるタグをBOX選択で削除する場合は、この点に注意してください。

実は最初は、タグ内で実行するとタグを単独で削除する機能も作っていました。
でも実際に使ってみると、HTMLタグを選択するマクロを使ってタグを削除したほうが早く、結局ほとんど使わない機能となり、むしろ開始タグと終了タグを削除する機能の邪魔になってしまったため、ソースコードも削除した経緯があります。