Water Sunlight

軽量プログラミングの文法 - JavaScript/Python

ユーザ用ツール

サイト用ツール


サイドバー

メインメニュー

メタ
sakura-macro

sakura macro

y2sunlight 2021-12-02

マクロの使用方法

設置

マクロを以下フォルダに設置する。

{ユーザフォルダ}\AppData\Roaming\sakura

マクロにショートカットキーを割り当てる

マクロ一覧に登録
  1. sakuraメニュー[設定][共通設定]の[マクロ]タブ押下
  2. 名前入力、File、Id選択後[設定]押下
  3. 一覧に表示される
  4. [OK]押下
キー割り当ての登録
  1. sakuraメニュー[設定][共通設定]の[キー割り当て]タブ押下
  2. 以下を設定
    • 種別:[外部マクロ]選択
    • 機能:マクロ一覧に登録したマクロから選択
    • キー:割り当てたいキーを選択
  3. [割付]
  4. [OK]

以上でショートカットキーでマクロを実行することが出来るようになります。 ショートカットキー以外で実行する時は、[ツール][名前を指定してマクロ実行]を押し、マクロを選択します。


chop.js

// -----------------------------------------------
// 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);
}


z2sp.js

// -----------------------------------------------
// 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);	// 再描画


repc.js

// -----------------------------------------------
// コードの置換
// 置換前のコードと置換後のコードはコロン(:)で区切る
// 複数置換の場合はカンマ(,)で区切る
// 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);
}


qsort.js

// -----------------------------------------------
// 固定長の〇文字目から?文字でソートする
// -----------------------------------------------
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);
}


xsort.js

// -----------------------------------------------
// 複数キーのソート
// [入力方法]{開始位置}:{文字長},{開始位置}:{文字長},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;
}


dump.js

// -----------------------------------------------
// バイナリーを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);
	}
}


rdump.js

// -----------------------------------------------
// 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);
	}
}


ruler.js

// -----------------------------------------------
// ルーラー追加
// -----------------------------------------------

// 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);


p2z.js

// -----------------------------------------------
// パック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);
	}
}


cb_cget.js

// -----------------------------------------------
// 選択範囲のコメント行を抽出
// コメント行とは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('コメント行はありません');
	}
}


cb_crem.js

// -----------------------------------------------
// 選択範囲のコメント行を除く
// コメント行とは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('クリップボードにコピーしました');
	}
}


cb_pic.js

// -----------------------------------------------
// 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;
}


sakura-macro.txt · 最終更新: 2022/02/01 10:31 by tanaka