sakuraエディタマクロ（json整形、マークダウン形式変換、改行統一、デコード、ディレクトリを開く、Grep結果整形、ディレクトリ配下に一括実行）

# サクラのマクロ

## サクラエディタのマクロについて
サクラエディタでは、下記のファイルをマクロとして実行することができる。
https://sakura-editor.github.io/help/HLP000204.html

| 拡張子 | 種類 |
|--------------------|--------|
| mac | キーマクロ |
| ppa | PPAマクロ |
| js | WSH:Jscriptマクロ |
| vbs | WSH:VBScriptマクロ |
| その他 | WSH:他にWSHが認識できるものであれば使える |

## 設定方法・利用方法
https://qiita.com/t_ookubo/items/6ad844ab04fc0170b4eb

## 利用しているマクロ
（あくまで支援目的なので、細かい精査とかエラーハンドリングとかはしてないです。）

### jsonファイル整形
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/a1c79460-90af-c19d-dcd2-771d1e0c578e.png)

```jsonFormat.js
// 行数を取得
var cnt = GetLineCount(0);
// 改行を除いた行文字列を取得
var textAll = "";
for (var i = 1; i <= cnt; i++) {
    var str = GetLineStr(i).replace(/\r\n/,"").replace(/\n/,"");
    textAll += str;
}
var editJson = "";
var innerFlg = false;
var intentLv = 0;
var quoteType = [];
var blockType = [];
var preChr = "";
for (var i = 0; i < textAll.length; i++) {
    var prefix = "";
    var suffix = "";
    var c = textAll.substring(i, i + 1);
    if (!innerFlg) {
        if (c == " ") {
            continue;
        }
        if (c == "\"" || c == "'"){
            innerFlg = true;
            quoteType[quoteType.length] = c;
            // JSON または 配列の1つ目の要素の時はスペース1個を追加
            var chkText = editJson.replace(/( |\t|\r\n|\n)/g, "");
            if (chkText.length > 0) {
                var preChar = chkText.substring(chkText.length - 1, chkText.length);
                if (preChar == "[" || preChar == "{") {
                    c = " " + c;
                }
            }
        } else {
            if (c == "{" || c == "[") {
                suffix = "\r\n";
                intentLv = intentLv + 1;
                blockType[blockType.length] = c;
                for (var j = 0; j < intentLv; j++) {
                    suffix = suffix + "\t";
                }
            }
            if (c == "}" || c == "]") {
                prefix = "\r\n";
                suffix = "\r\n";
                intentLv = intentLv - 1;
                blockType.pop(1);
            }
            if (c == ",") {
                prefix = "\r\n";
            }
        }
    } else {
        if (quoteType.length > 0 && c == quoteType[quoteType.length - 1]){
            innerFlg = false;
        }
    }
    if (prefix != "") {
        for (var j = 0; j < intentLv; j++) {
            prefix = prefix + "\t";
        }
    }
    var line = "" + prefix + c + suffix;
    if (preChr == "\r\n" && line.substring(0, 1) == "\r\n") {
        line = line.substring(1);
    }
    editJson = editJson + "" + line;
    preChr = line.substring(line.length - 1, line.length);
}
SelectAll(0);
InsText(editJson + "\r\n");

```

### CRLF改行統一
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/e821822a-cb32-22aa-c48f-e6a43bd4787a.png)

```CRLF.mac
S_SelectAll(0);	// すべて選択
S_CopyCRLF(0);	// CRLF改行でコピー
S_Paste(0);	// 貼り付け
```

### タブ区切りをMarkdown形式のテーブルに変換
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/87a1f922-0fc8-304c-28da-0b70a57e1723.png)

```toMarkdownTable.js
var selStRow;
var selEdRow;
var result = ''; 

// 行非選択状態の場合
if(IsTextSelected === 0 ) {
	selStRow = 0;
	selEdRow = GetLineCount(0);
	SelectAll(0);
} else {
	selStRow = GetSelectLineFrom; // 選択開始行取得
	selEdRow = GetSelectLineTo;   // 選択終了行取得
}

// 項目数を取得
var colCount = GetLineStr(selStRow).split(/\t/).length;

for (var i = selStRow; i <= selEdRow; i++) {
	// i行目を取得し、先頭・終了・タブをパイプラインで置き換える
	result +=  '| ' + GetLineStr(i).split(/\t/).join(' | ').replace( /\r?\n/g , ' |') + '\r\n';
	
	// 選択1行目の場合は、header行を追加する
	if (i === selStRow) {
		result += '|';
		for (var j = 1;  j <= colCount ; j++) {
			result += '--------|';
		}
		result += '\r\n';
	}
}
InsText(result);
```


### 「¥uXXXX」形式ユニコードをアンエスケープ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/4e0054f4-72ff-dbc3-d26c-1ef196d2edb5.png)

```unicodeUnescape.js
// 行数を取得
var cnt = GetLineCount(0);
var result = ''; 

for (var i = 1; i <= cnt; i++) {
	// i行目を取得
	var str = GetLineStr(i);
	// \u.... の文字列の配列で取得、大文字小文字は問わない
	uniArray = str.match(/\\u.{4}/ig);
	if (uniArray) { 
		for (var j = 0, len = uniArray.length; j < len; j++) {
			str = str.replace(uniArray[j], String.fromCharCode(uniArray[j].replace('\\u', '0x')))
		}
	}
	result += str;
}
SelectAll(0);
InsText(result);
```

### URLデコード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/110d31ae-a445-369a-c2a1-5ec24a542653.png)

```decodePercent.js
// 行数を取得
var cnt = GetLineCount(0);
var result = ''; 

for (var i = 1; i <= cnt; i++) {
	// i行目を取得
	var str = GetLineStr(i);
	str = decodeURI(str);
	
	result += str;
}
SelectAll(0);
InsText(result);
```

### 開いているファイルのディレクトリをエクスプローラで開く

``` execExplorer.mac
S_ExecCommand('explorer /select,"$F"', 0);
```


### Grep結果をタブ区切りにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/115a839e-7752-c312-8fea-c1007e5ce383.png)

``` Grep結果整形.mac
SetDrawSwitch(0);
AddRefUndoBuffer(); // Redo用

// Grep結果以外の部分を削除
S_GoFileTop(0);	// ファイルの先頭に移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Down_Sel(0);	// (選択)カーソル下移動
S_Delete(0);	// 削除
S_GoFileEnd(0);	// ファイルの最後に移動
S_Up_Sel(0);	// (選択)カーソル上移動
S_Delete(0);	// 削除


// 整形処理
S_ReplaceAll('\\t', '    ', 44);	// すべて置換
S_ReplaceAll('(^.*?)\\(', '$1\\t', 44);	// すべて置換
S_ReplaceAll('(^.+\\\\)([^\\\\]+)\\t', '$2\\t$1$2\\t', 44);	// すべて置換
S_ReplaceAll('(^.*?)\\)', '$1\\t', 44);	// すべて置換
S_ReplaceAll(' +(\\[SJIS\\]|\\[UTF-8\\]): +', '$1\\t', 44);	// TODO SJISとUTF-8のみ対応 他の文字コードの必要があれば更新
S_GoFileTop(0);	// ファイルの先頭に移動


// ヘッダー書き込み
S_GoFileTop(0);	// ファイルの先頭に移動
S_InsText('ファイル名	フルパス	行数,桁数	文字コード	内容');	// テキストを貼り付け


S_SelectAll(0);	// すべて選択
S_Copy(0);	// コピー
S_CancelMode(0);	// 各種モードの取り消し

S_SearchClearMark(0);	// 検索マークの切替え
SetDrawSwitch(1);
SetUndoBuffer();
S_ReDraw(0);	// 再描画


```


### 特定ディレクトリ配下すべて実行する

``` .bat
@echo off

REM 実行対象ディレクトリ
set targetDir=.\test
REM 実行するマクロ（マクロ事態に保存して閉じる処理を入れておくこと S_FileSave(); S_WinClose();）
REM ちなみに、マージ結果のダイアログは非表示にできないらしい。https://sakura-editor.github.io/bbslog/sf/macro/635.html#638
set targetMacro=.\hoge.mac

cd %targetDir%

for %%t in (*) do (call:method %%t)
exit
:method
"C:\Program Files (x86)\sakura\sakura.exe"  %1 -M=%targetMacro%
goto :eof

```

### 選択範囲に項番追加
https://qiita.com/t_o01/items/6b6aa687eaa59c383f4f
``` javascript
// 選択範囲の行に項番を追加するマクロ
var lines = Editor.GetSelectedString(0).split("\n");
for (var i = 0; i < lines.length; i++) {
    lines[i] = (i + 1) + ". " + lines[i];
}
Editor.InsText(lines.join("\n"));
```