/* (Tab=4) [概要] 行末に Tab (タブ文字)を、指定した桁位置まで挿入します。 カーソルの桁位置が、指定する桁位置の初期値になります。 桁位置は 1 開始です。 範囲選択されていない場合、カーソル行のみを処理します。(あまり意味がありません。) 範囲選択されている場合、選択範囲の行すべてを処理します。 範囲選択は、行頭からではなく行の途中から(桁位置>=2)でも構いません。 指定した桁位置がTabの停止位置ではない場合、その後ろに最初に現れるTab停止位置が 自動的に指定されます。 例:Tab幅=4 で、指定した桁位置= 6〜 9 → 指定した桁位置= 9 Tab幅=4 で、指定した桁位置=10〜13 → 指定した桁位置=13 指定した桁位置が、行末の桁位置より小さい場合、Tabは挿入されません。 次の定義値で、挙動を変更可能です: bREPLACE_TRAILINGSPACES_TO_TAB bINSERT_TAB_WHEN_EOL_EQUALTO_COLUMN bINSERT_TAB_WHEN_EOL_GREATERTHAN_COLUMN bINSERT_SPACE_FOR_TAB [変更履歴] 2012/07/28 Unicode版対応 2010/01/15 新規 */ //2012/07/28 Unicode版対応 // ANSI版/Unicode版の区別 var bUNICODE_VER = (Editor.ExpandParameter("$V").split(".")[0] == "1") ? false : true; // false=ANSI版 / true=Unicode版 // "$V":サクラエディタのバージョン (例:ANSI版="1.6.6.0" / Unicode版="2.0.5.0") // とりあえず、先頭が "1" ならANSI版とする。 // 行末の空白(スペースやTab)を、Tabに置き換えるか。 // true 行末の空白にスペースが含まれていれば、Tabに変換します。 // (行末の空白は、すべてTabになります。) // bINSERT_SPACE_FOR_TAB が true の場合、 // 行末の空白にTabが含まれていれば、スペースに変換します。 // (行末の空白は、すべてスペースになります。) // false 行末の空白はそのままで、Tabを後ろに挿入します。 // bINSERT_SPACE_FOR_TAB が true の場合、Tabの代わりに // スペースを後ろに挿入します。 // true の場合、行末の空白(スペースやTab)を一旦取り除き、 // 新たな行末の桁位置として扱います。 // この結果、指定した桁位置以降に空白のみが続く場合には、 // 指定した桁位置にまで行末が縮められることになります。 var bREPLACE_TRAILINGSPACES_TO_TAB = true; // 行末の桁位置が、指定した桁位置と等しい場合に、行末にTabを1文字挿入するか。 // true 行末の桁位置が、指定した桁位置と等しい場合、行末に // Tabを1文字だけ挿入します。 // bINSERT_SPACE_FOR_TAB が true の場合、Tabの代わりに // スペースを1文字だけ挿入します。 // bREPLACE_TRAILINGSPACES_TO_TAB が true の場合、 // 行末の空白(スペースやTab)を一旦取り除き、 // 新たな行末の桁位置として扱います。 // false Tabは挿入せずそのままにします。 var bINSERT_TAB_WHEN_EOL_EQUALTO_COLUMN = false; // 行末の桁位置が、指定した桁位置より大きい場合に、行末にTabを1文字挿入するか。 // true 行末の桁位置が、指定した桁位置より大きい場合、行末に // Tabを1文字だけ挿入します。 // bINSERT_SPACE_FOR_TAB が true の場合、Tabの代わりに // スペースを1文字だけ挿入します。 // bREPLACE_TRAILINGSPACES_TO_TAB が true の場合、 // 行末の空白(スペースやTab)を一旦取り除き、 // 新たな行末の桁位置として扱います。 // false Tabは挿入せずそのままにします。 var bINSERT_TAB_WHEN_EOL_GREATERTHAN_COLUMN = false; // 行末にTabではなくスペースを挿入するか。 // true スペースを挿入します。 // bREPLACE_TRAILINGSPACES_TO_TAB が true の場合、 // 行末の空白にTabが含まれていれば、それもスペースに変換します。 // (行末の空白は、すべてスペースになります。) // false Tabを挿入します。 var bINSERT_SPACE_FOR_TAB = false; // 選択範囲の最大行数。(安全の為、制限する。) var nMAX_LINES = 50; // Popupの書式: intButton = WshShell.Popup(strText,[nSecondsToWait],[strTitle],[nType]) var WshShell = new ActiveXObject("WScript.Shell"); // メッセージボックスのタイトル (本マクロ名) var CAPTION = Editor.ExpandParameter("$M").replace( /^.*\\/, "" ); // タブ幅の取得 var nTABWIDTH = Editor.ChangeTabWidth(0); //-------------- // メイン Main(); function Main() { var oSC = new ActiveXObject("ScriptControl"); // InputBox var nSetCol; // 指定した桁位置 var nEOLCol; // 行末の桁位置 var sTabOrSpace; var nTabOrSpaceWidth; var str; var strNL; var selstr; // 選択範囲の文字列 var newstr; // 選択範囲の処理後の文字列 var s; var x; var i; // エディタが「読み取り専用」なら処理終了。 if( Editor.ExpandParameter("${R?読専$:$:$}") == "読専" ) return; // InputBoxの初期値 (カーソルの桁位置) // カーソル行の、行頭からカーソル桁位置までの文字列を取得。 s = Editor.GetLineStr( 0 ); // カーソル行 x = Editor.ExpandParameter("$x") -1; //2012/07/28 Unicode版対応 // for(i=x; i >= 0; i--){ // if( getStringBytes( s.substring( 0, i ) ) <= x ) break; // } if( bUNICODE_VER ){ // Unicode版では "$x" は(行頭からの)バイト数ではなく文字数が返る。 i = x; }else{ for(i=x; i >= 0; i--){ if( getStringBytes( s.substring( 0, i ) ) <= x ) break; } } // 表示上の桁位置に変換。 nSetCol = getEOLColumn( s.substring( 0, i ) ); // Tab停止位置ではない場合、その後ろに最初に出現するTab停止位置を選ぶ。 nSetCol = Math.ceil( (nSetCol -1) / nTABWIDTH ) * nTABWIDTH +1; s = nSetCol; // InputBoxの初期値 // InputBox oSC.Language = "VBScript"; oSC.AddCode( 'Function InBox(prompt,title,default):InBox=InputBox(prompt,title, default):End Function' ); do{ var charname = (bINSERT_SPACE_FOR_TAB) ? "スペース" : "Tab 文字"; var prompt = "行末に " + charname + " を、指定した桁位置まで挿入します。\n" + "指定した桁位置が Tab の停止位置ではない場合、" + "その後ろに最初に現れる Tab 停止位置が指定されます。\n\n" + "桁位置 (1から始まります):"; s = oSC.Run( "InBox", prompt, CAPTION, s ); if( typeof s == "undefined" ) return; // キャンセルされた }while( s == "" ); nSetCol = parseInt( s ); if( isNaN( nSetCol ) || (nSetCol < 1) ){ WshShell.Popup( "無効な値です。\n\n" + s, 0, CAPTION, 0|48 ); // 0=MB_OK, 48=MB_ICONEXCLAMATION return; } // Tab停止位置ではない場合、その後ろに最初に出現するTab停止位置を選ぶ。 nSetCol = Math.ceil( (nSetCol -1) / nTABWIDTH ) * nTABWIDTH +1; // カーソル行(非選択時) または 選択範囲の行すべてを範囲選択する。 if( !SelectLinesOnSelectedRange() ) return; //if( Editor.IsTextSelected() == 0 ) return; // EOFのみの行(ファイルが空も該当) selstr = Editor.GetSelectedString(0); // 選択範囲の文字列 sTabOrSpace = (bINSERT_SPACE_FOR_TAB) ? " " : "\t"; nTabOrSpaceWidth = (bINSERT_SPACE_FOR_TAB) ? 1 : nTABWIDTH; newstr = ""; do{ // 1行取り出す。 selstr = selstr.replace( /^([^\r\n]*)(\r\n|\r|\n)?/, "" ); str = RegExp.$1; // 改行の手前まで (これが処理対象) strNL = RegExp.$2; // 改行 if( bREPLACE_TRAILINGSPACES_TO_TAB ){ str = str.replace( /[ \t]+$/, "" ); // 行末の空白(スペースやTab)を取り除く。 } nEOLCol = getEOLColumn( str ); if( nEOLCol == nSetCol ){ if( bINSERT_TAB_WHEN_EOL_EQUALTO_COLUMN ) str += sTabOrSpace; }else if( nEOLCol > nSetCol ){ if( bINSERT_TAB_WHEN_EOL_GREATERTHAN_COLUMN ) str += sTabOrSpace; }else{ for(; nEOLCol < nSetCol; nEOLCol += nTabOrSpaceWidth ) str += sTabOrSpace; } str += strNL; newstr += str; }while( selstr.length > 0 ); selstr = Editor.GetSelectedString(0); // 選択範囲の文字列 if( selstr != newstr ){ Editor.InsText( newstr ); // 選択範囲を置き換える。 }else{ Editor.CancelMode(); // 選択状態の解除。 } Editor.ReDraw(); // S_InsText() 後は再描画が必要。 } // 行末の桁位置を取得する。桁位置は 1 開始。(表示上の桁位置。) // str 行の文字列。(1行分のみ。) function getEOLColumn( str ) { var tabstop; // 次のTab停止位置 var col; var i; var ch; // ここでは、文字位置(桁位置)は 0 開始で処理する。 tabstop = nTABWIDTH; col = 0; for(i=0; i < str.length; i++){ ch = str.charAt( i ); if( (ch == "\r") || (ch == "\n") ) break; col = (ch == "\t") ? tabstop : col + getStringBytes( ch ); while( col >= tabstop ) tabstop += nTABWIDTH; } return col +1; // 戻り値の桁位置は 1 開始。 } // 文字列のバイト数を返す。 // 日本語のみ対応。 function getStringBytes( str ) { var len = 0; // バイト数 var i, c; for(i=0; i < str.length; i++){ // Shift_JIS: 0x0 〜 0x80, 0xa0 , 0xa1 〜 0xdf , 0xfd 〜 0xff // Unicode : 0x0 〜 0x80, 0xf8f0, 0xff61 〜 0xff9f, 0xf8f1 〜 0xf8f3 c = str.charCodeAt( i ); if( (c>=0x0 && c<=0x80) || (c>=0xf8f0 && c<=0xf8f3) || (c>=0xff61 && c<=0xff9f) ){ len++; }else{ len += 2; } } return len; } //-------------------------------------------------------------- // カーソル行(非選択時) または 選択範囲の行すべてを範囲選択する。 // 選択範囲の開始桁、終了桁は行の途中でも可。(行全体を選択していなくても可。) // EOFのみの行(行番号が表示されない行)だと何も選択されない(非選択状態)。 // 戻り値:true=成功 / false=メッセージボックスでCancel function SelectLinesOnSelectedRange() { var nIsTextSelected; var row1, row2, col2; var y1, y2, x2; var ans; nIsTextSelected = Editor.IsTextSelected(); if( nIsTextSelected == 0 ){ // カーソルのある行を1行選択。 Editor.SelectLine(0); }else{ // 選択範囲の開始行(の行頭)から終了行(の行末)までを選択。 row1 = Editor.GetSelectLineFrom(); // 選択開始行(折り返し単位) row2 = Editor.GetSelectLineTo(); // 選択終了行(折り返し単位) col2 = Editor.GetSelectColmTo(); // 選択終了桁(折り返し単位) // 選択状態の取り消し。(範囲選択開始(F6)、矩形範囲選択開始(Shift+F6)の取り消し。) Editor.CancelMode(); // 選択開始行の行頭(改行単位)へ移動。 Editor.Jump( row1, 0 ); // 折り返し単位 Editor.GoLineTop( 1<<3|1<<0 ); // 行頭(改行単位) y1 = Editor.ExpandParameter("$y") -0; // 行位置(改行単位)、文字列→数値 // 範囲選択開始。 Editor.BeginSelect(); // 選択終了行の、次の行の行頭へ移動。 Editor.Jump( row2, 0 ); // 折り返し単位 y2 = Editor.ExpandParameter("$y") -0; // 行位置(改行単位)、文字列→数値 x2 = Editor.ExpandParameter("$x") -0; // 桁位置(改行単位)、文字列→数値 if( (nIsTextSelected != 2) && ((col2 == 1) && (x2 == 1)) // 選択終了位置は行頭(改行単位)だった。 && (Editor.GetSelectLineTo() >= row2) // 最終行選択や、選択開始行=終了行だと偽。 ){ //y2 = y2; そのまま。 }else{ y2++; // 選択終了行の行末まで(次の行の行頭まで)を選択。(EOF行なら最後まで。) } Editor.Jump( y2, 1 ); // 改行単位 // 範囲選択終了 しておく。 Editor.BeginSelect(); // 選択範囲の最大行数。(安全の為、制限する。) if( y2 - y1 > nMAX_LINES ){ ans = WshShell.Popup( "選択範囲が多すぎます。\n" + "安全のため、最大 " + nMAX_LINES + " 行に制限しています。\n\n" + "続けますか?", 0, CAPTION, 1|48|256 ); // 1=MB_OKCANCEL, 48=MB_ICONEXCLAMATION, 256=MB_DEFBUTTON2 if( ans != 1 ){ // 1=IDOK //Editor.CancelMode(); とりあえず選択したまま。 return false; } } } return true; }