— y2sunlight 2021-12-02
マクロを以下フォルダに設置する。
{ユーザフォルダ}\AppData\Roaming\sakura
以上でショートカットキーでマクロを実行することが出来るようになります。 ショートカットキー以外で実行する時は、[ツール][名前を指定してマクロ実行]を押し、マクロを選択します。
// ----------------------------------------------- // 1行の最大文字数を指定して改行を入れる // ファイル名に.chopを付けて保存する(改行コードは入力する) // 0x0Dが含まれる時は確認メッセージ表示 // [はい]:0x0D を 0x0F に変換する // [いいえ]: 何もしない // ※ 0x0D:'-' 0x0C:'+' 0x0F:' ' // ----------------------------------------------- main(); function main() { // 0x0d(\r)検索 Editor.SearchNext('\\r', 36); if(Editor.GetSelectedString()){ if(Editor.YesNoBox('0x0Dが含まれます。0x0Fに変換して続けますか?') == 6) { // はい // 変換 Editor.ReplaceAll('\\r','\\x0F',4); // 再描画 Editor.ReDraw(0); } else { // いいえ return; } } // 最大文字数取得 var maxLen = parseInt(Editor.InputBox('1行の最大文字数を入力してください', 100)); if(isNaN(maxLen)) return; // 元の折り返し桁数と折り返し桁数設定 var oldWrapColm = Editor.ChangeWrapColm(maxLen); // 全て選択 Editor.SelectAll(); // 折り返し位置に改行をつけてコピー Editor.CopyAddCRLF(0); // 折り返し桁数を元に戻す Editor.ChangeWrapColm(oldWrapColm); // ペースト Editor.Paste(0); // 改行コード var code = parseInt(Editor.InputBox('[0]変換なし | [1]CRLF | [2]LF | [3]CR を入力して下さい。', 0)); if(isNaN(code)){ Editor.WarnMsg('改行コードの入力が無いので、ファイルを保存しません。'); return; } // 名前を指定して保存 var fileName = Editor.GetFilename() + '.chop'; Editor.FileSaveAs(fileName, 0, code); }
// ----------------------------------------------- // 0x00(NUL)~0x1f(US)を0x20(SPC)に変更する // 0x0a(LF),0x0d(CR)除く // ----------------------------------------------- var isSelected = Editor.IsTextSelected(); if(isSelected == 0){ // ----------------------- // 非選択状態(0) // ----------------------- // 全て選択 Editor.SelectAll(); } else { // ----------------------- // 選択中(1),矩形選択中(2) // ----------------------- } // 置換 // 第3引数 正規表現(0x004=4),選択範囲(0x080=128) Editor.ReplaceAll('[\\x00\\x00-\\x1f\\x00&&[^\\x0a\\x00\\x0d\\x00]]', '\\x20', 132); Editor.ReDraw(0); // 再描画
// ----------------------------------------------- // コードの置換 // 置換前のコードと置換後のコードはコロン(:)で区切る // 複数置換の場合はカンマ(,)で区切る // 0x00と0x01を0x20に置換する場合の入力例 00:20,01:20 // ----------------------------------------------- main(); function main() { var txt = Editor.InputBox('制御コード(16進2桁)を入力して下さい。'); if(!txt) return; var arr = txt.split(','); for(var key in arr){ var hexArr = arr[key].split(':'); if(hexArr.length == 2) { var before = '\\x' + hexArr[0] + '\\x00'; var after = '\\x' + hexArr[1]; Editor.ReplaceAll(before,after,4); } } // 再描画 Editor.ReDraw(0); }
// ----------------------------------------------- // 固定長の〇文字目から?文字でソートする // ----------------------------------------------- main(); function main() { // 〇文字目から var startPos = parseInt(Editor.InputBox('何文字目から?', 1)); if(isNaN(startPos)) return; // ?文字 var maxLen = parseInt(Editor.InputBox('何文字でソート', 1)); if(isNaN(maxLen)) return; // カーソル移動 Editor.MoveCursor(1, startPos, 0); // 矩形範囲選択開始 Editor.BeginBoxSelect(0); // 範囲選択 for(var col = 1; col < maxLen+1; col++) { Editor.Right_Sel(0); } var rowCnt = Editor.GetLineCount(0); for(var row = 1; row < rowCnt; row++) { Editor.Down_Sel(0); } // 選択行の昇順ソート Editor.SortAsc(0); }
// ----------------------------------------------- // 複数キーのソート // [入力方法]{開始位置}:{文字長},{開始位置}:{文字長},asc desc // ----------------------------------------------- main(); function main() { // キー var input = Editor.InputBox('{開始位置}:{文字長},{開始位置}:{文字長},asc desc'); if(!input) return; var keys = []; var inputWords = input.split(','); var orderWords = inputWords[inputWords.length-1].split(' '); if(inputWords.length - 1 == orderWords.length) { for(var i=0; i<inputWords.length-1; i++){ var words = inputWords[i].split(':'); if(words.length == 2){ var pos = 0; var len = 0; var order = ''; pos = parseInt(words[0]); len = parseInt(words[1]); order = orderWords[i]; var obj = new Key(pos, len, order); keys.push(obj); } } } else { Editor.ErrorMsg('キーの数とソート順の数があっていません。'); return; } // 行 var items = []; for(var i=1; i<=Editor.GetLineCount(0); i++){ var line = GetLineStr(i); var itemKeys = []; for(var j=0; j<keys.length; j++){ itemKeys[j] = line.substr(keys[j].pos-1, keys[j].len); } var objItem = new Item(i, itemKeys); items.push(objItem); } // ソート items.sort(function(a, b) { for(var i=0; i<a.key.length; i++){ if(a.key[i] !== b.key[i]) { if (a.key[i] < b.key[i]) { return (keys[i].order.toUpperCase() == 'DESC') ? 1 : -1; } if (a.key[i] > b.key[i]) { return (keys[i].order.toUpperCase() == 'DESC') ? -1 : 1; } } } return 0; }); var sortTxt = ''; for(var i=0; i<items.length; i++){ sortTxt += GetLineStr(items[i].lineNo); } // 上書き Editor.SelectAll(); Editor.InsText(sortTxt); } function Key(pos, len, order) { this.pos = pos; this.len = len; this.order = order; } function Item(lineNo, key) { this.lineNo = lineNo; this.key = key; }
// ----------------------------------------------- // バイナリーを16進ASCIIに変換 // ----------------------------------------------- main(); function main() { var isSelected = Editor.IsTextSelected(); if(isSelected == 0) { Editor.MessageBox('範囲を選択して下さい。'); return; } var colFrom = GetSelectColumnFrom(); // 選択開始桁 var colTo = GetSelectColumnTo(); // 選択終了桁 var lineFrom = GetSelectLineFrom(); // 選択開始行 var lineTo = GetSelectLineTo(); // 選択終了行 // 選択範囲の文字列取得 var selectText = GetSelectedString(0); // 最後の改行削除 selectText = selectText.replace(/\r\n$/, ''); // 改行で分割 var selectArr = selectText.split('\r\n'); for(var i=0; i<selectArr.length; i++){ var changeText = ''; for(var j=0; j<selectArr[i].length; j++) { changeText += ('00' + selectArr[i].charCodeAt(j).toString(16)).slice(-2); } // 範囲選択 Editor.MoveCursor(lineFrom + i, colFrom, 0); for(var col=colFrom; col < colTo; col++) { Editor.Right_Sel(0); } // 上書き Editor.InsText(changeText); } }
// ----------------------------------------------- // 16進ASCIIをバイナリーに変換 // ----------------------------------------------- main(); function main() { var isSelected = Editor.IsTextSelected(); if(isSelected == 0) { Editor.MessageBox('範囲を選択して下さい。'); return; } var colFrom = GetSelectColumnFrom(); // 選択開始桁 var colTo = GetSelectColumnTo(); // 選択終了桁 var lineFrom = GetSelectLineFrom(); // 選択開始行 var lineTo = GetSelectLineTo(); // 選択終了行 // 選択範囲の文字列取得 var selectText = GetSelectedString(0); // 最後の改行削除 selectText = selectText.replace(/\r\n$/, ''); // 改行で分割 var selectArr = selectText.split('\r\n'); loop: for(var i=0; i<selectArr.length; i++){ // 2文字ずつに分ける var hexArr = selectArr[i].match(/.{2}/g); if(!hexArr) continue; var changeText = ''; for (var j=0; j<hexArr.length; j++) { if(hexArr[j].toUpperCase() == '0A' || hexArr[j].toLowerCase() == '0D') { Editor.WarnMsg('「0A」または「0D」が入っています'); break loop; } changeText += String.fromCharCode(parseInt(hexArr[j], 16)); } // 範囲選択 Editor.MoveCursor(lineFrom + i, colFrom, 0); for(var col=colFrom; col < colTo; col++) { Editor.Right_Sel(0); } // 上書き Editor.InsText(changeText); } }
// ----------------------------------------------- // ルーラー追加 // ----------------------------------------------- // 1行目の文字列取得(改行なし) var txt = Editor.GetLineStr(1).replace(/\r\n/,''); // カーソル移動 Editor.MoveCursor(1, 1, 0); // 改行追加 Editor.Char(13); Editor.Char(13); var rowOne = ''; var rowTwo = ''; for(var j = 1; j <= txt.length; j++) { rowTwo += String(j % 10); if((j % 10)==0){ rowOne += (' ' + String(j/10)).slice(-10); } } // 1行目 Editor.MoveCursor(1, 1, 0); Editor.InsText(rowOne); // 2行目 Editor.MoveCursor(2, 1, 0); Editor.InsText(rowTwo);
// ----------------------------------------------- // パック10進をゾーン10進に変換 // ----------------------------------------------- main(); function main() { var isSelected = Editor.IsTextSelected(); if(isSelected == 0) { Editor.MessageBox('範囲を選択して下さい。'); return; } var colFrom = GetSelectColumnFrom(); // 選択開始桁 var colTo = GetSelectColumnTo(); // 選択終了桁 var lineFrom = GetSelectLineFrom(); // 選択開始行 var lineTo = GetSelectLineTo(); // 選択終了行 // 選択範囲の文字列取得 var selectText = GetSelectedString(0); // 最後の改行削除 selectText = selectText.replace(/\r\n$/, ''); // 改行で分割 var selectArr = selectText.split('\r\n'); Editor.CancelMode(); for(var i=0; i<selectArr.length; i++){ var changeText = ''; for(var j=0; j<selectArr[i].length; j++) { changeText += ('00' + selectArr[i].charCodeAt(j).toString(16)).slice(-2); } var change = ''; for(var k=0; k<changeText.length; k++){ var char = changeText.charAt(k).toUpperCase(); if(char == 'D'){ change = '-' + change; } else if(char == 'C') { change = '+' + change; } else if(char == 'A' || char == 'B' || char == 'E' || char == 'F') { change = ' ' + change; } else { change += char; } } // 範囲選択 Editor.MoveCursor(lineFrom + i, colFrom, 0); for(var col=colFrom; col < colTo; col++) { Editor.Right_Sel(0); } // 上書き Editor.InsText(change); } }
// ----------------------------------------------- // 選択範囲のコメント行を抽出 // コメント行とは7桁目に「*」または「/」をもつ行 // ----------------------------------------------- main() function main(){ var isSelected = Editor.IsTextSelected(); if(isSelected == 1) { // 行選択しているか var txt = Editor.GetSelectedString(0); var lines = txt.match(/^\d{6}[\s\S]*(\n|\r\n|\r)$/); if(!lines){ Editor.MessageBox('行を選択して下さい'); return; } }else{ Editor.MessageBox('行を選択して下さい'); return; } // 選択範囲の文字列取得 var allText = GetSelectedString(0); var arr = allText.match(/\d{6}(\*|\/).*(\n|\r\n|\r)/g); if(arr){ // 通常コピー Editor.SetClipboard(0, arr.join('')); Editor.MessageBox('クリップボードにコピーしました'); } else { // コメント無し Editor.MessageBox('コメント行はありません'); } }
// ----------------------------------------------- // 選択範囲のコメント行を除く // コメント行とは7桁目に「*」または「/」をもつ行 // ----------------------------------------------- main() function main(){ var isSelected = Editor.IsTextSelected(); if(isSelected == 1) { // 行選択しているか var txt = Editor.GetSelectedString(0); var lines = txt.match(/^\d{6}[\s\S]*(\n|\r\n|\r)$/); if(!lines){ Editor.MessageBox('行を選択して下さい'); return; } }else{ Editor.MessageBox('行を選択して下さい'); return; } // 選択範囲の文字列取得 var allText = GetSelectedString(0); var arr = allText.match(/\d{6}(?!\*|\/).*(\n|\r\n|\r)/g); if(arr){ // 通常コピー Editor.SetClipboard(0, arr.join('')); Editor.MessageBox('クリップボードにコピーしました'); } }
// ----------------------------------------------- // pic句のバイト数を集計 // PICTURE文字列がN, CR, DBはサポートしていません。 // REDEFINES と OCCURS は未サポートです。 // ・出現した時は警告を出します。 // ・出てきた数を数えて警告に表示します。 // ----------------------------------------------- var fileName = null; var occursNumber = 0; var redefinesNumber = 0; main(); function main() { var isSelected = Editor.IsTextSelected(); if(isSelected == 1) { // 行選択しているか var txt = Editor.GetSelectedString(0); var lines = txt.match(/^\d{6}[\s\S]*(\n|\r\n|\r)$/); if(!lines){ Editor.MessageBox('行を選択して下さい'); return; } }else{ Editor.MessageBox('行を選択して下さい'); return; } var lineFrom = Editor.GetSelectLineFrom(); // 選択開始行 var lineTo = Editor.GetSelectLineTo(); // 選択終了行 var picArr = []; var note = ''; for(var i=lineFrom; i<lineTo; i++){ // 行取得 var txt = Editor.GetLineStr(i); // コメント行 var arr = txt.match(/\d{6}(\*|\/)/); if(arr){ note = getNote(txt); continue; } // PicObj取得 var pic = getPic(txt, note); if(!pic) continue; // バイト数計算 var byte = getByte(pic.type, pic.option); if(byte == 0) { return; } pic.byte = byte; // 位置計算 if(picArr.length > 0) { pic.position = getPosition(picArr[picArr.length - 1].byte, picArr[picArr.length - 1].position); } else { pic.position = 1; } // 配列に入れる picArr.push(pic); note = ''; } // 出力 output(picArr); // REDEFINEとOCCURSの数 if(occursNumber > 0 || redefinesNumber > 0) { var msg = ''; if(occursNumber > 0) { msg += 'OCCURS が ' + occursNumber + ' 箇所あります。'; } if(redefinesNumber > 0) { if(msg) msg += '\n'; msg += 'REDEFINES が ' + redefinesNumber + ' 箇所あります。'; } Editor.MessageBox(msg); } } function Pic(no, name, type, option, byte, position, note) { this.no = no; this.name = name; this.type = type; this.option = option; this.byte = byte; this.position = position; this.note = note; } /** * コメント行の備考を取得 */ function getNote(line) { var note = ''; var words = line.split(';'); if(words.length == 2) { var wds = words[1].split(/\s/); if(wds.length == 2) { note = wds[1]; } } return note; } /** * 1行をPicにいれて返す */ function getPic(line, note) { var pic = null; // インラインコメント削除 var commentIndex = line.indexOf(';'); if(commentIndex > 0) line = line.substring(0, commentIndex); commentIndex = line.indexOf('*>'); if(commentIndex > 0) line = line.substring(0, commentIndex); var found = line.match(/\s\d{2}\s.+/); if(found){ // スペースで区切る var words = found[0].split(/\s/); // 最後のピリオド削除 words[words.length-1] = words[words.length-1].replace(/.$/, ''); // 最初の変数名をファイル名とする if(!fileName) { if(words && words.length >= 1) fileName = words[1]; } // PICは何番目か取得 var picPos = 0; for(var index in words){ if(words[index] == 'PIC' || words[index] == 'PICTURE'){ picPos = Number(index); } } // オプション(レベル、変数名以外) var option = []; var j = 0; for(var i=2; i<words.length; i++){ option[j++] = words[i]; if(words[i].toUpperCase() == 'REDEFINES'){ redefinesNumber++; } if(words[i].toUpperCase() == 'OCCURS'){ occursNumber++; } } if(picPos > 1) { pic = new Pic(words[0], words[1], words[picPos+1], option, 0, 0, note); } } return pic; } /** * 型からバイト数計算 */ function getByte(type, option){ var byte = 0; var state = 0; // 状態 var beforeType = ''; // 型 var byteStr = ''; // バイト数(文字列) for(var i=0; i<type.length; i++){ // 1文字取得 var char = type.charAt(i); switch(char){ case 'A': case 'X': case '/': case 'Z': case ',': case '.': case '*': case '+': case '-': beforeType = char; byte += 1; break; case 'N': Editor.WarnMsg('PIC文字[N]はサポートしていません。'); return 0; case 'D': case 'C': beforeType = char; break; case 'R': if(beforeType == 'C'){ Editor.WarnMsg('PIC文字[CR]はサポートしていません。'); return 0; } break; case 'B': if(beforeType == 'D'){ Editor.WarnMsg('PIC文字[DB]はサポートしていません。'); return 0; } else { beforeType = char; byte += 1; } break; case '0': case '9': if(state ==1){ byteStr += char; } else { beforeType = char; byte += 1; } break; case '(': if(beforeType){ state = 1; } break; case ')': if(state == 1){ byte += Number(byteStr) - 1; state = 0; beforeType = ''; byteStr = ''; } break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': if(state == 1) { byteStr += char; } break; } } // PACKED-DECIMAL or COMP-3 or COMPUTATIONAL-3 if(isOptions(option, 'PACKED-DECIMAL') || isOptions(option, 'COMP-3') || isOptions(option, 'COMPUTATIONAL-3')) { byte = Math.floor(byte / 2 + 1); } // BINARY or COMP or COMPUTATIONAL if(isOptions(option, 'BINARY') || isOptions(option, 'COMP') || isOptions(option, 'COMPUTATIONAL')) { if(1<=byte && byte<=4) { byte = 2; } else if(5<=byte && byte<=9) { byte = 4; } else if(10<=byte && byte<=18) { byte = 8; } } return byte; } /** * 位置計算 * @param beforeByte 1つ前のバイト数 * @param beforePos 1つ前の位置 */ function getPosition(beforeByte, beforePos){ return beforePos + beforeByte; } /** * オプション中に指定文字列があるか * @param array option * @param string str * @return true/false */ function isOptions(option, str) { var flg = false; for(var index in option) { if(option[index].toUpperCase() == str){ flg = true; break; } } return flg; } /** * 出力 */ function output(picArr){ // ファイルに保存かクリップボードに保存かキャンセル var result = Editor.MessageBox('ファイル出力の場合は[はい]をクリップボードの場合は[いいえ]を押して下さい。',3); if(result == 6){ // 全選択 Editor.SelectAll(); // 上書き Editor.InsText(changeText(picArr)); // 名前を指定して保存(開いているファイルのパス) Editor.FileSaveAs(fileName); }else if(result == 7){ // クリップボードにコピー Editor.SetClipboard(0, changeText(picArr)); Editor.MessageBox('クリップボードにコピーしました'); } } /** * オプション */ function getOption(option) { for(var index in option) { if(option[index]=='PACKED-DECIMAL' || option[index]=='COMP-3' || option[index]=='COMPUTATIONAL-3' || option[index]=='BINARY' || option[index]=='COMP' || option[index]=='COMPUTATIONAL'){ return option[index]; } } return ''; } /** * Pic配列を文字列に変換 */ function changeText(picArr) { var txt = ""; for(var i=0; i<picArr.length; i++){ txt += picArr[i].no txt += '\t'; txt += picArr[i].name; txt += '\t'; txt += picArr[i].type; var option = getOption(picArr[i].option) if(option){ txt += ' ' + getOption(picArr[i].option); } txt += '\t'; txt += picArr[i].byte; txt += '\t'; txt += picArr[i].position; txt += '\t'; txt += picArr[i].note; txt += '\r\n'; } return txt; }