//////////////////////////////////////////////////////////////////////////////// // html 入力支援 // の直後にを自動で補完します。 // // インストール方法 // キー SHIFT + . にこのマクロを割り当ててください。 Main(); function Main() { // SHIFT + . で呼び出されるので、とりあえず > を出力する Editor.Char(0x3e); // 0x3e = '>' if(Editor.IsCurTypeExt("html")){ CompleteTagHtml(false); } } // タグ補間 // bForce == true のとき // カーソル位置に入るべき終了タグを探して挿入し // カーソル位置をその直後に移す // bForce == false のとき // カーソル位置の直前に開始タグがある場合のみ // それに対応する終了タグを挿入し // カーソル位置を開始・終了タグの間に置く // いずれの場合も // 終了タグを挿入しなくてもいい場合は挿入しない // 間違った終了タグが存在する場合は、 // まずそれを置き換えることを考えてみる function CompleteTagHtml(bForce) { // 現在位置と全文 var xCur = Number(Editor.ExpandParameter("$x")) - 1; var yCur = Number(Editor.ExpandParameter("$y")) - 1; var asText = []; var height = Editor.GetLineCount(0); for(var y = 1; y <= height; ++y){ asText.push(Editor.GetLineStr(y)); } // カーソルより左の全テキスト var as = asText.slice(0, yCur+1); as[yCur] = as[yCur].substring(0, xCur); var sBack = as.join(''); // カーソルより左にある部分から、タグを抜き出す var atTagBack = ExtractTags(sBack); if(atTagBack.length <= 0) return; // 強制補完を指定されなかったときは、なにもしないで終わる条件がいくつかある if(! bForce){ var tTagLast = atTagBack[atTagBack.length - 1]; // 今しがた入力された '>' が タグの一部でなければなにもしない if(tTagLast.posEnd != sBack.length) return; // 今入力されたタグが終了タグなら、なにもしない if(tTagLast.name.substring(0,2) == ""がある場合、それを消して代わりに終了タグをいれてみる if( ixErr != null && ixErr >= atTagBack.length ){ var ixErrFore = ixErr - atTagBack.length; if( atTagFore[ixErrFore].name != sEndTag ){ var t = atTagFore[ixErrFore]; atTagFore[ixErrFore] = { "name": sEndTag }; // 整合性がとれるなら if(IsConsistent(atTagBack.concat(atTagFore), {})){ // 置き換え xyTag = PositionToXY(sBack.length + t.posBeg, asText); lenTag = t.posEnd - t.posBeg; GotoXY(xyTag.x, xyTag.y); Editor.BeginSelect(); for(var i = 0; i < lenTag; ++i) Editor.Right(); Editor.InsText(sEndTag); if(! bForce){ // カーソルを挿入前のところに戻す GotoXY(xCur, yCur); } return; } atTagFore[ixErrFore] = t; // 元に戻す }} // 上でうまくいかなかったときは、そのまま挿入 Editor.InsText(sEndTag); if(! bForce){ // カーソルを挿入前のところに戻す GotoXY(xCur, yCur); } } // タグを抜き出す -> atTags = array of { name, beg, end } // name は もしくは の形式 function ExtractTags(s) { var atTags = []; var re = /