nadesiko3 3.7.21 → 3.7.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/batch/command.txt +370 -334
- package/batch/jsplugin2text.nako3 +1 -1
- package/batch/pickup_command.nako3 +12 -0
- package/core/command/snako.mts +5 -1
- package/core/deno/snako.ts +5 -1
- package/core/package-lock.json +382 -21
- package/core/package.json +4 -4
- package/core/src/nako3.mts +178 -614
- package/core/src/nako_basic_plugins.mts +39 -0
- package/core/src/nako_core_version.mts +2 -2
- package/core/src/nako_csv.mts +0 -1
- package/core/src/nako_event.mts +49 -0
- package/core/src/nako_gen.mts +291 -202
- package/core/src/nako_indent_inline.mts +2 -2
- package/core/src/nako_lex_rules.mts +1 -1
- package/core/src/nako_parser3.mts +106 -165
- package/core/src/nako_parser_async.mts +97 -0
- package/core/src/nako_parser_base.mts +4 -55
- package/core/src/nako_parser_message.mts +105 -0
- package/core/src/nako_parser_operator.mts +93 -0
- package/core/src/nako_plugin_manager.mts +260 -0
- package/core/src/nako_require.mts +292 -0
- package/core/src/nako_runner.mts +191 -0
- package/core/src/nako_tokenizer.mts +221 -0
- package/core/src/plugin_csv.mts +1 -1
- package/core/src/plugin_system.mts +34 -3259
- package/core/src/plugin_system_array.mts +699 -0
- package/core/src/plugin_system_datetime.mts +368 -0
- package/core/src/plugin_system_debug.mts +403 -0
- package/core/src/plugin_system_dict.mts +85 -0
- package/core/src/plugin_system_json.mts +73 -0
- package/core/src/plugin_system_math.mts +383 -0
- package/core/src/plugin_system_regexp.mts +120 -0
- package/core/src/plugin_system_stdio.mts +86 -0
- package/core/src/plugin_system_string.mts +666 -0
- package/core/src/plugin_system_timer.mts +152 -0
- package/core/src/plugin_system_types.mts +151 -0
- package/core/src/plugin_system_url.mts +193 -0
- package/core/src/plugin_toml.mts +3 -3
- package/core/test/fixtures/README.md +39 -0
- package/core/test/fixtures/make_parser_ast_golden.mjs +31 -0
- package/core/test/fixtures/parser_ast_golden.json +8027 -0
- package/core/test/fixtures/parser_corpus.mjs +120 -0
- package/core/test/indent_test.mjs +6 -0
- package/core/test/nako_basic_plugins_test.mjs +44 -0
- package/core/test/nako_event_test.mjs +85 -0
- package/core/test/nako_gen_perf_test.mjs +178 -0
- package/core/test/nako_parser_async_test.mjs +112 -0
- package/core/test/nako_parser_test.mjs +160 -0
- package/core/test/nako_plugin_manager_test.mjs +185 -0
- package/core/test/nako_require_test.mjs +153 -0
- package/core/test/nako_runner_test.mjs +114 -0
- package/core/test/nako_tokenizer_test.mjs +115 -0
- package/core/test/plugin_system_debug_test.mjs +141 -0
- package/core/test/plugin_system_split_test.mjs +179 -0
- package/core/test/plugin_system_test.mjs +6 -0
- package/core/tsconfig.json +0 -1
- package/package.json +17 -21
- package/release/_hash.txt +36 -36
- package/release/_script-tags.txt +16 -16
- package/release/command.json +1 -1
- package/release/command.json.js +1 -1
- package/release/command_cnako3.json +1 -1
- package/release/command_list.json +1 -1
- package/release/edit_main.js +6 -6
- package/release/edit_main.js.map +3 -3
- package/release/editor.js +6 -6
- package/release/plugin_keigo.js.map +3 -3
- package/release/plugin_markup.js +46 -46
- package/release/plugin_markup.js.map +3 -3
- package/release/plugin_weykturtle3d.js +1 -1
- package/release/plugin_weykturtle3d.js.map +3 -3
- package/release/version.js +2 -2
- package/release/version_main.js +2 -2
- package/release/version_main.js.map +1 -1
- package/release/wnako3.js +186 -213
- package/release/wnako3.js.map +4 -4
- package/release/wnako3webworker.js +172 -199
- package/release/wnako3webworker.js.map +4 -4
- package/src/cnako3mod.mjs +7 -2
- package/src/cnako3mod.mts +7 -2
- package/src/nako_version.mjs +2 -2
- package/src/nako_version.mts +2 -2
- package/src/plugin_browser_ajax.mjs +4 -4
- package/src/plugin_browser_ajax.mts +4 -4
- package/src/plugin_browser_audio.mjs +10 -10
- package/src/plugin_browser_audio.mts +10 -10
- package/src/plugin_browser_camera.mjs +4 -4
- package/src/plugin_browser_camera.mts +4 -4
- package/src/plugin_browser_canvas.mjs +2 -2
- package/src/plugin_browser_canvas.mts +2 -2
- package/src/plugin_browser_crypto.mjs +3 -3
- package/src/plugin_browser_crypto.mts +3 -3
- package/src/plugin_browser_dom_event.mjs +1 -1
- package/src/plugin_browser_dom_event.mts +1 -1
- package/src/plugin_browser_geolocation.mjs +1 -1
- package/src/plugin_browser_geolocation.mts +1 -1
- package/src/plugin_browser_hotkey.mjs +1 -1
- package/src/plugin_browser_hotkey.mts +1 -1
- package/src/plugin_browser_html.mjs +1 -1
- package/src/plugin_browser_html.mts +1 -1
- package/src/plugin_browser_location.mjs +1 -1
- package/src/plugin_browser_location.mts +1 -1
- package/src/plugin_browser_speech.mjs +1 -1
- package/src/plugin_browser_speech.mts +1 -1
- package/src/plugin_browser_storage.mjs +2 -2
- package/src/plugin_browser_storage.mts +2 -2
- package/src/plugin_httpserver.mjs +3 -3
- package/src/plugin_httpserver.mts +3 -3
- package/src/plugin_keigo.mjs +2 -2
- package/src/plugin_keigo.mts +2 -2
- package/src/plugin_node.mjs +48 -48
- package/src/plugin_node.mts +53 -53
- package/src/plugin_weykturtle3d.mjs +56 -56
- package/src/plugin_weykturtle3d.mts +56 -56
- package/src/wnako3.mjs +1 -1
- package/src/wnako3.mts +1 -1
- package/src/wnako3_editor.mjs +5 -5
- package/src/wnako3_editor.mts +5 -5
- package/src/wnako3mod.mjs +2 -2
- package/src/wnako3mod.mts +2 -2
- package/core/src/nako3.mjs +0 -1021
- package/core/src/nako_ast.mjs +0 -4
- package/core/src/nako_colors.mjs +0 -77
- package/core/src/nako_core_version.mjs +0 -8
- package/core/src/nako_csv.mjs +0 -193
- package/core/src/nako_errors.mjs +0 -166
- package/core/src/nako_from_dncl.mjs +0 -285
- package/core/src/nako_from_dncl2.mjs +0 -347
- package/core/src/nako_gen.mjs +0 -2500
- package/core/src/nako_global.mjs +0 -138
- package/core/src/nako_indent.mjs +0 -442
- package/core/src/nako_indent_chars.mjs +0 -29
- package/core/src/nako_indent_inline.mjs +0 -361
- package/core/src/nako_josi_list.mjs +0 -47
- package/core/src/nako_lex_rules.mjs +0 -319
- package/core/src/nako_lexer.mjs +0 -794
- package/core/src/nako_logger.mjs +0 -221
- package/core/src/nako_parser3.mjs +0 -3250
- package/core/src/nako_parser_base.mjs +0 -403
- package/core/src/nako_parser_const.mjs +0 -37
- package/core/src/nako_prepare.mjs +0 -329
- package/core/src/nako_reserved_words.mjs +0 -42
- package/core/src/nako_source_mapping.mjs +0 -207
- package/core/src/nako_test.mjs +0 -37
- package/core/src/nako_token.mjs +0 -1
- package/core/src/nako_tools.mjs +0 -53
- package/core/src/nako_types.mjs +0 -14
- package/core/src/plugin_api.mjs +0 -4
- package/core/src/plugin_csv.mjs +0 -97
- package/core/src/plugin_math.mjs +0 -352
- package/core/src/plugin_promise.mjs +0 -102
- package/core/src/plugin_system.mjs +0 -3810
- package/core/src/plugin_test.mjs +0 -52
- package/core/src/plugin_toml.mjs +0 -39
package/core/src/nako_global.mjs
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { NakoColors } from './nako_colors.mjs';
|
|
2
|
-
/**
|
|
3
|
-
* コンパイルされたなでしこのプログラムで、グローバル空間のthisが指すオブジェクト
|
|
4
|
-
*/
|
|
5
|
-
export class NakoGlobal {
|
|
6
|
-
/**
|
|
7
|
-
* @param compiler
|
|
8
|
-
* @param gen
|
|
9
|
-
*/
|
|
10
|
-
constructor(compiler, gen, guid = 0) {
|
|
11
|
-
this.guid = guid;
|
|
12
|
-
this.lastJSCode = '';
|
|
13
|
-
// ユーザーのプログラムから編集される変数
|
|
14
|
-
this.__locals = new Map();
|
|
15
|
-
this.__varslist = [
|
|
16
|
-
compiler.newVaiables(compiler.__varslist[0]), // system
|
|
17
|
-
compiler.newVaiables(compiler.__varslist[1]), // global
|
|
18
|
-
compiler.newVaiables(compiler.__varslist[2]) // local [2][3][4][5] ...
|
|
19
|
-
];
|
|
20
|
-
this.numFailures = 0;
|
|
21
|
-
this.index = 0;
|
|
22
|
-
this.nextIndex = -1;
|
|
23
|
-
this.__code = [];
|
|
24
|
-
this.__callstack = [];
|
|
25
|
-
this.__stack = [];
|
|
26
|
-
this.__labels = [];
|
|
27
|
-
this.__genMode = gen.genMode;
|
|
28
|
-
// バージョン情報の引き継ぎ
|
|
29
|
-
this.version = compiler.version;
|
|
30
|
-
this.coreVersion = compiler.coreVersion;
|
|
31
|
-
// PluginSystemとdestroy()から参照するため
|
|
32
|
-
this.__module = { ...compiler.__module }; // shallow copy
|
|
33
|
-
this.pluginfiles = { ...compiler.getPluginfiles() };
|
|
34
|
-
// PluginWorkerでユーザー定義関数のJavaScriptコードをworkerのコンパイラのインスタンスへコピーするため
|
|
35
|
-
this.gen = gen;
|
|
36
|
-
// 以下のメソッドで使うため
|
|
37
|
-
this.logger = compiler.getLogger();
|
|
38
|
-
this.compiler = compiler;
|
|
39
|
-
this.josiList = compiler.josiList;
|
|
40
|
-
this.reservedWords = compiler.reservedWords;
|
|
41
|
-
}
|
|
42
|
-
clearLog() {
|
|
43
|
-
this.__varslist[0].set('表示ログ', '');
|
|
44
|
-
}
|
|
45
|
-
get log() {
|
|
46
|
-
let s = this.__varslist[0].get('表示ログ');
|
|
47
|
-
s = s.replace(/\s+$/, '');
|
|
48
|
-
return s;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* システム変数を設定する
|
|
52
|
-
* @param name システム変数名
|
|
53
|
-
* @param value 設定したい値
|
|
54
|
-
*/
|
|
55
|
-
__setSysVar(name, value) {
|
|
56
|
-
this.__varslist[0].set(name, value);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* システム変数を取得する
|
|
60
|
-
* @param name システム変数名
|
|
61
|
-
* @returns システム変数の値
|
|
62
|
-
*/
|
|
63
|
-
__getSysVar(name) {
|
|
64
|
-
return this.__varslist[0].get(name);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* 「ナデシコ」命令のためのメソッド
|
|
68
|
-
*/
|
|
69
|
-
runEx(code, fname, opts, preCode = '') {
|
|
70
|
-
// スコープを共有して実行
|
|
71
|
-
opts.preCode = preCode;
|
|
72
|
-
opts.nakoGlobal = this;
|
|
73
|
-
return this.compiler.runSync(code, fname, opts);
|
|
74
|
-
}
|
|
75
|
-
async runAsync(code, fname, opts, preCode = '') {
|
|
76
|
-
// スコープを共有して実行
|
|
77
|
-
opts.preCode = preCode;
|
|
78
|
-
opts.nakoGlobal = this;
|
|
79
|
-
return await this.compiler.runAsync(code, fname, opts);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* テスト実行のためのメソッド
|
|
83
|
-
* @param {{ name: string, f: () => void }[]} tests
|
|
84
|
-
*/
|
|
85
|
-
_runTests(tests) {
|
|
86
|
-
let text = `${NakoColors.color.bold}テストの実行結果${NakoColors.color.reset}\n`;
|
|
87
|
-
let pass = 0;
|
|
88
|
-
let numFailures = 0;
|
|
89
|
-
for (const t of tests) {
|
|
90
|
-
try {
|
|
91
|
-
t.f();
|
|
92
|
-
text += `${NakoColors.color.green}✔${NakoColors.color.reset} ${t.name}\n`;
|
|
93
|
-
pass++;
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
const errorMessage = (err instanceof Error) ? err.message : String(err);
|
|
97
|
-
text += `${NakoColors.color.red}☓${NakoColors.color.reset} ${t.name}: ${errorMessage}\n`;
|
|
98
|
-
numFailures++;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (numFailures > 0) {
|
|
102
|
-
text += `${NakoColors.color.green}成功 ${pass}件 ${NakoColors.color.red}失敗 ${numFailures}件`;
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
text += `${NakoColors.color.green}成功 ${pass}件`;
|
|
106
|
-
}
|
|
107
|
-
this.numFailures = numFailures;
|
|
108
|
-
this.logger.stdout(text);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* 毎プラグインの「!クリア」関数を実行
|
|
112
|
-
*/
|
|
113
|
-
clearPlugins() {
|
|
114
|
-
// 実行している関数をすべて終了させる
|
|
115
|
-
// プラグインのクリア関数を呼び出す
|
|
116
|
-
const clearName = '!クリア';
|
|
117
|
-
for (const pname in this.pluginfiles) {
|
|
118
|
-
const po = this.__module[pname];
|
|
119
|
-
if (po[clearName] && po[clearName].fn) {
|
|
120
|
-
try {
|
|
121
|
-
po[clearName].fn(this);
|
|
122
|
-
}
|
|
123
|
-
catch (e) {
|
|
124
|
-
this.logger.error(`プラグイン『${pname}』のクリア関数でエラーが発生しました:` + String(e.message));
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* 各種リセット処理
|
|
131
|
-
*/
|
|
132
|
-
reset() {
|
|
133
|
-
this.clearPlugins();
|
|
134
|
-
}
|
|
135
|
-
destroy() {
|
|
136
|
-
this.reset();
|
|
137
|
-
}
|
|
138
|
-
}
|
package/core/src/nako_indent.mjs
DELETED
|
@@ -1,442 +0,0 @@
|
|
|
1
|
-
import { NakoIndentError } from './nako_errors.mjs';
|
|
2
|
-
import { NakoPrepare, checkNakoMode } from './nako_prepare.mjs';
|
|
3
|
-
// インデント構文のキーワード
|
|
4
|
-
const INDENT_MODE_KEYWORDS = ['!インデント構文', '!ここまでだるい'];
|
|
5
|
-
/**
|
|
6
|
-
* インデント構文指定があればコードを変換する
|
|
7
|
-
*/
|
|
8
|
-
function convert(code, filename = 'main.nako3') {
|
|
9
|
-
// インデント構文の適用が必要か?
|
|
10
|
-
if (checkNakoMode(code, INDENT_MODE_KEYWORDS)) {
|
|
11
|
-
return convertForIndentMode(code, filename);
|
|
12
|
-
}
|
|
13
|
-
return { code, insertedLines: [], deletedLines: [] };
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* インデント構文指定があるかチェックする
|
|
17
|
-
*/
|
|
18
|
-
function isIndentSyntaxEnabled(code) {
|
|
19
|
-
return checkNakoMode(code, INDENT_MODE_KEYWORDS);
|
|
20
|
-
}
|
|
21
|
-
/** ありえない改行マークを定義 */
|
|
22
|
-
const defSpecialRetMark = '🍷🍷改行🍹黐黑鼘鼶齈▨🍺🍺🍶🍶';
|
|
23
|
-
let SpecialRetMark = defSpecialRetMark;
|
|
24
|
-
/** code中にありえない改行マーク生成しモジュール内の変数SpecialRetMarkに設定 */
|
|
25
|
-
export function checkSpecialRetMark(code) {
|
|
26
|
-
SpecialRetMark = defSpecialRetMark;
|
|
27
|
-
while (code.indexOf(SpecialRetMark) >= 0) {
|
|
28
|
-
// 適当な文字を足してユニークにする(一応漢字領域で生成)
|
|
29
|
-
const c = String.fromCodePoint(Math.floor(Math.random() * 40952) + 0x4E00);
|
|
30
|
-
SpecialRetMark += c + c;
|
|
31
|
-
}
|
|
32
|
-
return SpecialRetMark;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* ソースコードのある1行の中のコメントを全て取り除く。
|
|
36
|
-
* 事前にreplaceRetMarkによって文字列や範囲コメント内の改行文字が置換されている必要がある。
|
|
37
|
-
*/
|
|
38
|
-
export function removeCommentsFromLine(src) {
|
|
39
|
-
const prepare = NakoPrepare.getInstance(); // `※`, `//`, `/*` といったパターン全てに対応するために必要
|
|
40
|
-
const len = src.length;
|
|
41
|
-
let result = '';
|
|
42
|
-
let eos = '';
|
|
43
|
-
let i = 0;
|
|
44
|
-
let isComment = false;
|
|
45
|
-
while (i < len) {
|
|
46
|
-
const c = src.charAt(i);
|
|
47
|
-
const ch2 = src.substring(i, 2);
|
|
48
|
-
const cPrepared = prepare.convert1ch(c);
|
|
49
|
-
const ch2Prepared = ch2.split('').map((c) => prepare.convert1ch(c)).join('');
|
|
50
|
-
// eosか?
|
|
51
|
-
if (eos !== '') {
|
|
52
|
-
// srcのi文字目以降がeosで始まるなら文字列を終了、そうでなければ1文字進める
|
|
53
|
-
if (eos === (eos.length === 1 ? cPrepared : ch2Prepared)) {
|
|
54
|
-
if (!isComment) {
|
|
55
|
-
result += src.substr(i, eos.length);
|
|
56
|
-
}
|
|
57
|
-
i += eos.length;
|
|
58
|
-
isComment = false;
|
|
59
|
-
eos = '';
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
if (!isComment) {
|
|
63
|
-
result += c;
|
|
64
|
-
}
|
|
65
|
-
i++;
|
|
66
|
-
}
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
// 文字列の改行も無視する
|
|
70
|
-
switch (cPrepared) {
|
|
71
|
-
case '"':
|
|
72
|
-
case '\'':
|
|
73
|
-
eos = c;
|
|
74
|
-
result += c;
|
|
75
|
-
i++;
|
|
76
|
-
continue;
|
|
77
|
-
case '「':
|
|
78
|
-
eos = '」';
|
|
79
|
-
result += c;
|
|
80
|
-
i++;
|
|
81
|
-
continue;
|
|
82
|
-
case '『':
|
|
83
|
-
eos = '』';
|
|
84
|
-
result += c;
|
|
85
|
-
i++;
|
|
86
|
-
continue;
|
|
87
|
-
case '“':
|
|
88
|
-
eos = '”';
|
|
89
|
-
result += c;
|
|
90
|
-
i++;
|
|
91
|
-
continue;
|
|
92
|
-
case '{':
|
|
93
|
-
eos = '}';
|
|
94
|
-
result += c;
|
|
95
|
-
i++;
|
|
96
|
-
continue;
|
|
97
|
-
case '[':
|
|
98
|
-
eos = ']';
|
|
99
|
-
result += c;
|
|
100
|
-
i++;
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
switch (ch2) {
|
|
104
|
-
case '🌴':
|
|
105
|
-
eos = '🌴';
|
|
106
|
-
result += ch2;
|
|
107
|
-
i += 2;
|
|
108
|
-
continue;
|
|
109
|
-
case '🌿':
|
|
110
|
-
eos = '🌿';
|
|
111
|
-
result += ch2;
|
|
112
|
-
i += 2;
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
// 行コメント
|
|
116
|
-
if (cPrepared === '#') {
|
|
117
|
-
eos = '\n';
|
|
118
|
-
isComment = true;
|
|
119
|
-
i++;
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
if (ch2Prepared === '//') {
|
|
123
|
-
eos = '\n';
|
|
124
|
-
isComment = true;
|
|
125
|
-
i += 2;
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
// 範囲コメント
|
|
129
|
-
if (ch2Prepared === '/*') {
|
|
130
|
-
eos = '*/';
|
|
131
|
-
isComment = true;
|
|
132
|
-
i += 2;
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
result += c;
|
|
136
|
-
i++;
|
|
137
|
-
}
|
|
138
|
-
return result;
|
|
139
|
-
}
|
|
140
|
-
/** インデントモードのための変換処理 */
|
|
141
|
-
function convertForIndentMode(code, filename) {
|
|
142
|
-
// returns => {{ code: string, insertedLines: number[], deletedLines: { lineNumber: number, len: number }[] }}
|
|
143
|
-
const insertedLines = [];
|
|
144
|
-
const deletedLines = [];
|
|
145
|
-
const END = 'ここまで‰';
|
|
146
|
-
const code2 = replaceRetMark(code); // 文字列の中などの改行を置換
|
|
147
|
-
const lines = code2.split('\n');
|
|
148
|
-
const lines2 = [];
|
|
149
|
-
const indentStack = [];
|
|
150
|
-
let lastIndent = 0;
|
|
151
|
-
// 元ソースコードの中に特殊改行マークが含まれるかチェックして含まれるならもっと複雑な特殊マークを動的に生成
|
|
152
|
-
checkSpecialRetMark(code);
|
|
153
|
-
let lineCount = -1;
|
|
154
|
-
lines.forEach((line) => {
|
|
155
|
-
lineCount += line.split(SpecialRetMark).length;
|
|
156
|
-
// trim line
|
|
157
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
158
|
-
if (/^[ ・\t]*$/.test(line)) {
|
|
159
|
-
deletedLines.push({ lineNumber: lines2.length, len: line.length });
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
163
|
-
const lineTrimed = removeCommentsFromLine(line).replace(/^[ ・\t]+/, '').replace(/\s+$/, '');
|
|
164
|
-
if (lineTrimed === '') {
|
|
165
|
-
lines2.push(line);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (lineTrimed === 'ここまで') {
|
|
169
|
-
throw new NakoIndentError('インデント構文が有効化されているときに『ここまで』を使うことはできません。', lineCount, filename);
|
|
170
|
-
}
|
|
171
|
-
// check indent
|
|
172
|
-
const indent = countIndent(line);
|
|
173
|
-
if (lastIndent === indent) {
|
|
174
|
-
lines2.push(line);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
// indent
|
|
178
|
-
if (lastIndent < indent) {
|
|
179
|
-
indentStack.push(lastIndent);
|
|
180
|
-
lastIndent = indent;
|
|
181
|
-
lines2.push(line);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
// unindent
|
|
185
|
-
if (lastIndent > indent) {
|
|
186
|
-
// 5回
|
|
187
|
-
// 3回
|
|
188
|
-
// 1を表示
|
|
189
|
-
// |
|
|
190
|
-
// |
|
|
191
|
-
lastIndent = indent;
|
|
192
|
-
while (indentStack.length > 0) {
|
|
193
|
-
const n = indentStack.pop() || 0;
|
|
194
|
-
if (n === indent) {
|
|
195
|
-
if (lineTrimed.substring(0, 3) !== '違えば') {
|
|
196
|
-
insertedLines.push(lines2.length);
|
|
197
|
-
lines2.push(makeIndent(n) + END);
|
|
198
|
-
}
|
|
199
|
-
lines2.push(line);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
if (indent < n) {
|
|
203
|
-
insertedLines.push(lines2.length);
|
|
204
|
-
lines2.push(makeIndent(n) + END);
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
// 残りのインデントを処理
|
|
211
|
-
while (indentStack.length > 0) {
|
|
212
|
-
const n = indentStack.pop() || 0;
|
|
213
|
-
insertedLines.push(lines2.length);
|
|
214
|
-
lines2.push(makeIndent(n) + END);
|
|
215
|
-
}
|
|
216
|
-
// 特別マーカーを改行に置換
|
|
217
|
-
const lines3 = [];
|
|
218
|
-
for (let i = 0; i < lines2.length; i++) {
|
|
219
|
-
if (lines2[i].includes(SpecialRetMark)) {
|
|
220
|
-
const lines4 = lines2[i].split(SpecialRetMark);
|
|
221
|
-
// 置換されたマーカーの数だけ、それ以降の行数をずらす。
|
|
222
|
-
// unindentによって挿入された行がSpecialRetMarkを含むことはない。
|
|
223
|
-
for (let j = 0; j < insertedLines.length; j++) {
|
|
224
|
-
if (lines3.length < insertedLines[j]) {
|
|
225
|
-
insertedLines[j] += lines4.length - 1;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
for (let j = 0; j < deletedLines.length; j++) {
|
|
229
|
-
if (lines3.length < deletedLines[j].lineNumber) {
|
|
230
|
-
deletedLines[j].lineNumber += lines4.length - 1;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
lines3.push(...lines4);
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
lines3.push(lines2[i]);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return { code: lines3.join('\n'), insertedLines, deletedLines };
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* count分だけ字下げする
|
|
243
|
-
* @param {number} count
|
|
244
|
-
*/
|
|
245
|
-
function makeIndent(count) {
|
|
246
|
-
let s = '';
|
|
247
|
-
for (let i = 0; i < count; i++) {
|
|
248
|
-
s += ' ';
|
|
249
|
-
}
|
|
250
|
-
return s;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* インデント部分を取り出す
|
|
254
|
-
*/
|
|
255
|
-
export function getIndent(line) {
|
|
256
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
257
|
-
const m = /^([ ・\t]*)/.exec(removeCommentsFromLine(line));
|
|
258
|
-
if (!m) {
|
|
259
|
-
return '';
|
|
260
|
-
}
|
|
261
|
-
return m[1];
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* インデントの個数を数える
|
|
265
|
-
*/
|
|
266
|
-
export function countIndent(line) {
|
|
267
|
-
let cnt = 0;
|
|
268
|
-
for (let i = 0; i < line.length; i++) {
|
|
269
|
-
const ch = line.charAt(i);
|
|
270
|
-
if (ch === ' ') {
|
|
271
|
-
cnt++;
|
|
272
|
-
continue;
|
|
273
|
-
}
|
|
274
|
-
if (ch === ' ') {
|
|
275
|
-
cnt += 2;
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
if (ch === '・') {
|
|
279
|
-
cnt += 2;
|
|
280
|
-
continue;
|
|
281
|
-
}
|
|
282
|
-
if (ch === '\t') {
|
|
283
|
-
cnt += 4;
|
|
284
|
-
continue;
|
|
285
|
-
}
|
|
286
|
-
break;
|
|
287
|
-
}
|
|
288
|
-
return cnt;
|
|
289
|
-
}
|
|
290
|
-
export function replaceRetMark(src) {
|
|
291
|
-
const prepare = NakoPrepare.getInstance(); // `※`, `//`, `/*` といったパターン全てに対応するために必要
|
|
292
|
-
const len = src.length;
|
|
293
|
-
let result = '';
|
|
294
|
-
let eos = '';
|
|
295
|
-
let i = 0;
|
|
296
|
-
while (i < len) {
|
|
297
|
-
const c = src.charAt(i);
|
|
298
|
-
const ch2 = src.substr(i, 2);
|
|
299
|
-
const cPrepared = prepare.convert1ch(c);
|
|
300
|
-
const ch2Prepared = ch2.split('').map((c) => prepare.convert1ch(c)).join('');
|
|
301
|
-
// eosか?
|
|
302
|
-
if (eos !== '') {
|
|
303
|
-
// srcのi文字目以降がeosで始まるなら文字列を終了、そうでなければ1文字進める
|
|
304
|
-
if (eos === (eos.length === 1 ? cPrepared : ch2Prepared)) {
|
|
305
|
-
result += src.substr(i, eos.length);
|
|
306
|
-
i += eos.length;
|
|
307
|
-
eos = '';
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
if (c === '\n') {
|
|
311
|
-
result += SpecialRetMark;
|
|
312
|
-
}
|
|
313
|
-
else {
|
|
314
|
-
result += c;
|
|
315
|
-
}
|
|
316
|
-
i++;
|
|
317
|
-
}
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
// 文字列の改行も無視する
|
|
321
|
-
switch (cPrepared) {
|
|
322
|
-
case '"':
|
|
323
|
-
case '\'':
|
|
324
|
-
eos = c;
|
|
325
|
-
result += c;
|
|
326
|
-
i++;
|
|
327
|
-
continue;
|
|
328
|
-
case '「':
|
|
329
|
-
eos = '」';
|
|
330
|
-
result += c;
|
|
331
|
-
i++;
|
|
332
|
-
continue;
|
|
333
|
-
case '『':
|
|
334
|
-
eos = '』';
|
|
335
|
-
result += c;
|
|
336
|
-
i++;
|
|
337
|
-
continue;
|
|
338
|
-
case '“':
|
|
339
|
-
eos = '”';
|
|
340
|
-
result += c;
|
|
341
|
-
i++;
|
|
342
|
-
continue;
|
|
343
|
-
case '{':
|
|
344
|
-
eos = '}';
|
|
345
|
-
result += c;
|
|
346
|
-
i++;
|
|
347
|
-
continue;
|
|
348
|
-
case '[':
|
|
349
|
-
eos = ']';
|
|
350
|
-
result += c;
|
|
351
|
-
i++;
|
|
352
|
-
continue;
|
|
353
|
-
}
|
|
354
|
-
switch (ch2) {
|
|
355
|
-
case '🌴':
|
|
356
|
-
eos = '🌴';
|
|
357
|
-
result += ch2;
|
|
358
|
-
i += 2;
|
|
359
|
-
continue;
|
|
360
|
-
case '🌿':
|
|
361
|
-
eos = '🌿';
|
|
362
|
-
result += ch2;
|
|
363
|
-
i += 2;
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
// 行コメント
|
|
367
|
-
if (cPrepared === '#') {
|
|
368
|
-
eos = '\n';
|
|
369
|
-
result += c;
|
|
370
|
-
i++;
|
|
371
|
-
continue;
|
|
372
|
-
}
|
|
373
|
-
if (ch2Prepared === '//') {
|
|
374
|
-
eos = '\n';
|
|
375
|
-
result += ch2;
|
|
376
|
-
i += 2;
|
|
377
|
-
continue;
|
|
378
|
-
}
|
|
379
|
-
// 範囲コメント
|
|
380
|
-
if (ch2Prepared === '/*') {
|
|
381
|
-
eos = '*/';
|
|
382
|
-
result += ch2;
|
|
383
|
-
i += 2;
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
result += c;
|
|
387
|
-
i++;
|
|
388
|
-
}
|
|
389
|
-
return result;
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* コードのインデントの構造を取得する。
|
|
393
|
-
* 空白行や複数行にまたがる構文を考慮する。
|
|
394
|
-
* インデント構文が有効化されていない場合にも使われる。
|
|
395
|
-
*/
|
|
396
|
-
export function getBlockStructure(code) {
|
|
397
|
-
const result = {
|
|
398
|
-
lines: [], // 各行のインデント量
|
|
399
|
-
pairs: [],
|
|
400
|
-
parents: [], // 各行の親の行
|
|
401
|
-
spaces: [] // 各行のインデントの文字列
|
|
402
|
-
};
|
|
403
|
-
const lines = replaceRetMark(code).split('\n');
|
|
404
|
-
const stack = [];
|
|
405
|
-
let lineCount = 0;
|
|
406
|
-
let prev = countIndent(lines[0]);
|
|
407
|
-
for (const line of lines) {
|
|
408
|
-
const numLines = line.split(SpecialRetMark).length;
|
|
409
|
-
const line2 = removeCommentsFromLine(line);
|
|
410
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
411
|
-
const current = (line2.replace(/^[ ・\t]+/, '') === '')
|
|
412
|
-
? prev
|
|
413
|
-
: countIndent(line2);
|
|
414
|
-
result.lines.push(...Array(numLines).fill(current));
|
|
415
|
-
result.spaces.push(...Array(numLines).fill(getIndent(line2)));
|
|
416
|
-
if (prev < current) {
|
|
417
|
-
stack.push(lineCount - 1);
|
|
418
|
-
}
|
|
419
|
-
else if (prev > current) {
|
|
420
|
-
const last = stack.pop();
|
|
421
|
-
if (last !== undefined) {
|
|
422
|
-
result.pairs.push([last, lineCount]);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
const parent = stack[stack.length - 1] !== undefined ? stack[stack.length - 1] : null;
|
|
426
|
-
result.parents.push(...Array(numLines).fill(parent));
|
|
427
|
-
prev = current;
|
|
428
|
-
lineCount += numLines;
|
|
429
|
-
}
|
|
430
|
-
// スタックが余ったらコードの末尾とペアにする。
|
|
431
|
-
for (const item of stack) {
|
|
432
|
-
result.pairs.push([item, lineCount]);
|
|
433
|
-
}
|
|
434
|
-
return result;
|
|
435
|
-
}
|
|
436
|
-
export default {
|
|
437
|
-
convert,
|
|
438
|
-
getBlockStructure,
|
|
439
|
-
getIndent,
|
|
440
|
-
countIndent,
|
|
441
|
-
isIndentSyntaxEnabled
|
|
442
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* なでしこ3で行頭インデントに使える文字とインデントカウント数
|
|
3
|
-
*/
|
|
4
|
-
export function isIndentChars(ch) {
|
|
5
|
-
const code = ch.charCodeAt(0);
|
|
6
|
-
// 特別なコード
|
|
7
|
-
if (ch === '\t') {
|
|
8
|
-
return 4;
|
|
9
|
-
}
|
|
10
|
-
if (ch === ' ' || ch === '|') {
|
|
11
|
-
return 1;
|
|
12
|
-
}
|
|
13
|
-
if (ch === '・' || ch === ' ') {
|
|
14
|
-
return 2;
|
|
15
|
-
}
|
|
16
|
-
if (ch === '⏋' || ch === '⏌') {
|
|
17
|
-
return 2;
|
|
18
|
-
} // 0x23CB, 0x23CC
|
|
19
|
-
// 罫線から --- https://github.com/kujirahand/unicode-sheets/blob/main/box-drawing.md
|
|
20
|
-
if (code >= 0x2500 && code <= 0x257F) {
|
|
21
|
-
return 2;
|
|
22
|
-
}
|
|
23
|
-
// 記号から --- https://github.com/kujirahand/unicode-sheets/blob/main/misc-technical.md
|
|
24
|
-
if ((code >= 0x23A0 && code <= 0x23AF) ||
|
|
25
|
-
(code >= 0x23B8 && code <= 0x23BF)) {
|
|
26
|
-
return 2;
|
|
27
|
-
}
|
|
28
|
-
return 0;
|
|
29
|
-
}
|