// // 領域選択 // Version 1.0 (2011/09/29) // by mobitan http://mobitan.org/ // $HtmlExt = ".php .htm .html .shtml"; // HTML として扱う拡張子 (スペース区切り) #Notify = yes; // 見つからなかったときメッセージを出す (yes/no) // 2011/09/29 v1.0 初版 // カーソル位置を含む引用符/括弧/HTML タグ/HTML 要素の内側を選択。繰り返し実行で順次外側へ拡大。 // // Step 0. 範囲選択時はカーソルを範囲末へ移動。 // Step 1. カーソル位置の色を見て、取得すべき領域の種類を決める。 // Step 2. 領域を取得。この段階では色は見ない。 // Step 3. 領域が元のカーソル位置と重なっていたら、領域を選択。 // #debug = 1; call Initialize; call Main; if (!##return) { // 領域が見つからないか、元のカーソル位置から外れていたら… // selectcfunc; // 強調行の範囲を選択 // selectfoldable 0x0020; // アウトライン解析の対応する範囲を選択 } call Finalize; endmacro; Main: ##selected = selecting; if (##selected) { call Region; $$basesel = $$return; moveto selendx, selendy; escape; } call Coord; $$basepos = $$return; ##color = colorcode & 0x1F; if (#debug >= 2) call Confirm "\nbasesel\t= " + $$basesel + "\nbasepos\t= " + $$basepos + "\ncolor\t= " + str(##color) + " = 0x" + hex(##color) + ""; // 文字定数 if (##color == 20) { call IsOnQuote; call BetweenQuote (##return > 0); // 引用符内を選択 } // HTML タグ (要素名) else if (##color == 14 || (##color == 13 && code == '<')) { call BetweenTag true, ##selected; // HTML 要素内を選択 } // HTML タグ (属性名) else if (##color == 15) { call CoveredBy " [a-z0-9_.:-]+=(\"[^\"]*\"|'[^']*'|[^\"'<> ]*)"; // HTML タグ内の属性を選択 } // HTML タグ (その他) else if (##color == 13) { call CoveredBy "<.*?>"; // HTML タグを選択 } // 括弧 else if (strstr("()[]{}()〔〕[]{}〈〉《》「」『』【】", char(code)) >= 0) { call BetweenParen true, ##selected; // 括弧内を選択 } // スクリプト部分 else if (##color == 25) { call BetweenParen false, true; // 括弧内を選択 } // HTML ファイル (コメント外) else if (strstr($HtmlExt + " ", filetype + " ") >= 0 && ##color != 3) { call BetweenTag false, true; // HTML 要素内を選択 } // その他 else { call BetweenParen false, true; // 括弧内を選択 } $$between = $$return; if (#debug >= 2) call Confirm "\nbetween\t= " + $$between + "\nbasepos\t= " + $$basepos + ""; call RegionIncludes $$between, $$basepos, false; if (##return) { call Select $$between; return true; } if (##selected) { call Select $$basesel; } else { call MoveTo $$basepos; } return false; CoveredBy: // カーソル位置を含むパターンマッチの領域を取得 // $$1 = 正規表現 escape; ##ox = x; ##oy = y; right; searchup $$1, regular; while (result && (foundendy > ##oy || (foundendx >= ##ox && foundendy == ##oy))) { call Region; $$r = $$return; findup; } escape; moveto ##ox, ##oy; return $$r; BetweenQuote: // 引用符で囲まれた領域を取得 (論理行内限定) // ##1 = true:引用符を含む escape; ##ox = x; ##oy = y; golinetop2; // エスケープがあるので上検索はまずい。論理行頭から下検索する searchdown2 "\"([^\"\\n]|\\\\.|\"\")*(?=\")|'([^'\\n]|\\\\.|'')*(?=')|$", regular; while (result && (foundendy < ##oy || (foundendx < ##ox && foundendy == ##oy))) { moveto foundendx, foundendy; // 「閉じ引用符〜開き引用符」にヒットさせない finddown; } $$r = ""; if ((!result) || (foundtopy > ##oy || (foundtopx > ##ox && foundtopy == ##oy))) { if (#Notify) message "カーソル位置を囲む引用符が行内に見つかりません"; escape; } else { moveto foundtopx, foundtopy; call GetCharCoord (2 - ##1); $$r = $$return; moveto foundendx, foundendy; call GetCharCoord (1 + ##1); $$r = $$r + $$return; } moveto ##ox, ##oy; return $$r; BetweenParen: // 括弧で囲まれた領域を取得 // ##1 = true:括弧を含む // ##2 = true:閉じ括弧を探索 (しない場合は括弧上にカーソルを置いて呼ぶこと) escape; ##ox = x; ##oy = y; setsearch "[()\\[\\]{}()〔〕[]{}〈〉《》「」『』【】]", 0x00000010; if (##2) { finddown2; while (result && strstr(")]})〕]}〉》」』】", char(code)) < 0) { gokakko; if (!result) break; finddown; } } else { right; findup; } $$r = ""; if (!result) { if (#Notify) message "カーソル位置を囲む括弧が見つかりません"; escape; } else if (strstr("([{(〔[{〈《「『【", char(code)) >= 0) { call GetCharCoord (2 - ##1); $$r = $$return; gokakko; call GetCharCoord (1 + ##1); $$r = $$r + $$return; } else { call GetCharCoord (1 + ##1); $$r = $$return; gokakko; call GetCharCoord (2 - ##1); $$r = $$return + $$r; } moveto ##ox, ##oy; return $$r; BetweenTag: // タグで囲まれた領域を取得 // ##1 = true:タグを含む // ##2 = true:終了タグを探索 (しない場合はタグ上にカーソルを置いて呼ぶこと) escape; ##ox = x; ##oy = y; setsearch "(?\\1)<(/?[a-z][a-z0-9_.:-]*)", 0x00000010; if (##2) { finddown2; while (result && code != '/') { gotagpair; if (!result) break; finddown; } } else { right 2; findup; } $$r = ""; if (!result) { if (#Notify) message "カーソル位置を囲むタグが見つかりません"; escape; } else if (code != '/') { call GetTagCoord (2 - ##1); $$r = $$return; gotagpair; call GetTagCoord (1 + ##1); $$r = $$r + $$return; } else { call GetTagCoord (1 + ##1); $$r = $$return; gotagpair; call GetTagCoord (2 - ##1); $$r = $$return + $$r; } moveto ##ox, ##oy; return $$r; //------------------------------------------------------------------------------ IsOnQuote: // カーソルが引用符上にあるか? // ##return = 0:引用符上でない 1:開始引用符上にある 2:終了引用符上にある escape; ##ox = x; ##oy = y; if (colorcode & 0x1F != 20) return false; ##r = 0x00; left; while (result && code == 0x0D) left; if (colorcode & 0x1F != 20) ##r = ##r | 0x01; moveto ##ox, ##oy; right; while (result && code == 0x0D) right; if (colorcode & 0x1F != 20) ##r = ##r | 0x02; moveto ##ox, ##oy; return ##r; GetCharCoord: // 文字の座標を取得 // ##1 = 1:先頭 2:末尾 3:両方(領域を取得) $$r = ""; if (##1 & 0x01) { call ToCoord lineno, column; $$r = $$r + $$return; } if (##1 & 0x02) { call ToCoord lineno, column + (strlen(char(code))); $$r = $$r + $$return; } return $$r; GetTagCoord: // タグの座標を取得 // ##1 = 1:先頭 2:末尾 3:両方(領域を取得) escape; ##ox = x; ##oy = y; $$r = ""; if (##1 & 0x01) { if (code != '<') left; while (result && code != '<') left; if (code != '<') call Error "GetTagCoord:\nタグの「<」がありません"; call Coord; $$r = $$r + $$return; moveto ##ox, ##oy; } if (##1 & 0x02) { if (code != '>') right; while (result && code != '>') right; if (code != '>') call Error "GetTagCoord:\nタグの「>」がありません"; right; call Coord; $$r = $$r + $$return; moveto ##ox, ##oy; } return $$r; //============================================================================== //. 座標操作サブルーチン //============================================================================== // // 座標を表す文字列 // "0000001100000022" // \______/\______/ // lineno column // // 領域を表す文字列 // "00000011000000220000003300000044" // \______/\______/\______/\______/ // seltop seltop selend selend // lineno column lineno column // RegionIncludes: // 領域が座標を含むか? // $$1 = 領域 // $$2 = 座標 // ##3 = true:範囲末を含む if (midstr($$1, 0, 16) > midstr($$1, 16, 16)) $$1 = midstr($$1, 16, 16) + midstr($$1, 0, 16); return (midstr($$1, 0, 16) <= $$2) && ($$2 < midstr($$1, 16, 16) || ($$2 == midstr($$1, 16, 16) && ##3)); ToCoord: // 位置を座標に変換 // ##1, ##2 = 位置 (lineno, column) return rightstr("00000000" + str(##1), 8) + rightstr("00000000" + str(##2), 8); ToRegion: // 範囲を領域に変換 // ##1, ##2 = 始点 (lineno, column) // ##3, ##4 = 終点 (lineno, column) return rightstr("00000000" + str(##1), 8) + rightstr("00000000" + str(##2), 8) + rightstr("00000000" + str(##3), 8) + rightstr("00000000" + str(##4), 8); Coord: // カーソル位置の座標を取得 return rightstr("00000000" + str(lineno), 8) + rightstr("00000000" + str(column), 8); Region: // 選択範囲の領域を取得 return rightstr("00000000" + str(seltoplineno), 8) + rightstr("00000000" + str(seltopcolumn), 8) + rightstr("00000000" + str(selendlineno), 8) + rightstr("00000000" + str(selendcolumn), 8); MoveTo: // 座標へカーソル移動 moveto2 val(midstr($$1, 8, 8)), val(midstr($$1, 0, 8)); return; Select: // 領域を選択 (後から前へ) moveto2 val(midstr($$1, 24, 8)), val(midstr($$1, 16, 8)); beginsel; moveto2 val(midstr($$1, 8, 8)), val(midstr($$1, 0, 8)); endsel; return; //============================================================================== //. 共通サブルーチン //============================================================================== Initialize: // 初期化 setcompatiblemode 0x0200; $searchbuffer = searchbuffer; #searchoption = searchoption; #searchoption2 = searchoption2; call GetHidemaruEnv "CursorBreakCR"; // 「行末<->次の行の行頭」移動 if (##return == 0) { call SetHidemaruEnv "CursorBreakCR", 1; #cursorbreakchanged = 1; } if (freecursor) { freecursorswitch; #freecursorswitched = 1; } if (overwrite) { overwriteswitch; #overwriteswitched = 1; } disableerrormsg; if (!#debug) disabledraw; return; Finalize: // 後始末 if (!#debug) enabledraw; enableerrormsg; if (#cursorbreakchanged) call SetHidemaruEnv "CursorBreakCR", 0; if (#freecursorswitched) freecursorswitch; if (#overwriteswitched) overwriteswitch; setsearch $searchbuffer, #searchoption, #searchoption2; return; GetHidemaruEnv: // 動作環境取得 // $$1 = キー名 // ##return = 値 openreg "CURRENTUSER", "Software\\Hidemaruo\\Hidemaru\\Env"; ##r = getregnum($$1); closereg; return ##r; SetHidemaruEnv: // 動作環境設定 // $$1 = キー名 // ##2 = 値 openreg "CURRENTUSER", "Software\\Hidemaruo\\Hidemaru\\Env"; writeregnum $$1, ##2; closereg; envchanged; return; Error: // エラー処理 enabledraw; if ($$1 != "") message currentmacrobasename + ": " + $$1; call Finalize; endmacro; Confirm: // デバッグ用 enabledraw; question currentmacrobasename + ": " + $$1; if (result) return; endmacro; // (C) mobitan 2011