web404

引用符の間を順次選択するマクロ

カーソル位置を含む引用符の間を選択します。
ただし、同じ論理行にある引用符のみが対象です。

カーソル位置が引用符内にない場合は、ファイルの末尾に向かって同じ論理行に複数存在する引用符を探索し、その間を選択します。
連続して実行すると、次の引用符の間を選択します。

連続実行時は、選択範囲に隣接する引用符との間は選択しないようにしています。
たとえば、1つの論理行に同じ引用符が4つあり、このマクロで1つ目と2つ目の間を選択している場合、次に選択するのは3つ目と4つ目の間です。
なお、2つ目と3つ目の引用符の間を個別に選択することは可能です。

対応する引用符は「"」「'」です。
引用符の直前に「\」があれば、エスケープされているとみなします。


ダウンロード

quotation.zip


更新履歴

Version 1.00 (2025/01/28)
公開

ソースコード

#x = x; #y = y;
#sel = 0; #cont = 0;
disabledraw;

if (selecting) {
	#sel = 1;
	escape;
}

while (1) {
	if (code == 13) moveto2 0, lineno + 1;
	else if (code == -1) {
		moveto #x, #y;
		beep;
		goto End;
	}
	call SeekRange;
	if (##return) break;
}

moveto2 #ct, #ln;
beginsel;
moveto2 #ce, #ln;
endsel;

goto End;

SeekRange:	//同じ論理行の引用符の間を探索
	#col = column; #ln = lineno;
	
	if (#sel && (code == '"' || code == '\'')) {	//連続実行時の処理
		#sel = 0;
		call CheckEscape;
		if (##return) {
			#cont = 1;
			#col = #col + 1;
		}
	}
	
	while (column && (!#cont)) {	//左方向に開始引用符を探索
		left;
		if (code == '"' || code == '\'') {
			call CheckEscape;
			if (##return) {
				$q = gettext2(column, lineno, column + 1, lineno);
				right;
				#ct = column;
				call SeekEnd;
				if (##return) return 1;
				break;
			}
		}
	}
	
	moveto2 #col, #ln;
	while (code != 13 && code != -1) {	//右方向に開始引用符を探索
		if (code == '"' || code == '\'') {
			call CheckEscape;
			if (##return) {
				$q = gettext2(column, lineno, column + 1, lineno);
				right;
				#ct = column;
				call SeekEnd;
				if (##return) return 1;
				break;
			}
		}
		right;
	}
	
	moveto2 #col, #ln;
	if ($q == "\"") $q = "'";	//探索対象の変更
	else $q = "\"";
	while (code != 13 && code != -1) {	//右方向に開始引用符を探索
		if (code == ascii($q)) {
			call CheckEscape;
			if (##return) {
				right;
				#ct = column;
				call SeekEnd;
				if (##return) return 1;
				break;
			}
		}
		right;
	}
	
	return 0;

SeekEnd:	//右方向に終了引用符を探索
	while (code != 13 && code != -1) {
		if (code == ascii($q)) {
			call CheckEscape;
			if (##return) {
				#ce = column;
				return 1;
			}
		}
		right;
	}
	return 0;

CheckEscape:	//エスケープされていないかを調べる
	##e = 0;
	if (column) {
		left;
		while (code == '\\') {
			##e = ##e + 1;
			left;
		}
		right ##e + 1;
	}
	return (##e + 1) % 2;

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

できるだけ無意味な範囲は選択しないようにしています。
複数の論理行にわたる範囲を対象外にしたのも、このためです。