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.
Files changed (155) hide show
  1. package/batch/command.txt +370 -334
  2. package/batch/jsplugin2text.nako3 +1 -1
  3. package/batch/pickup_command.nako3 +12 -0
  4. package/core/command/snako.mts +5 -1
  5. package/core/deno/snako.ts +5 -1
  6. package/core/package-lock.json +382 -21
  7. package/core/package.json +4 -4
  8. package/core/src/nako3.mts +178 -614
  9. package/core/src/nako_basic_plugins.mts +39 -0
  10. package/core/src/nako_core_version.mts +2 -2
  11. package/core/src/nako_csv.mts +0 -1
  12. package/core/src/nako_event.mts +49 -0
  13. package/core/src/nako_gen.mts +291 -202
  14. package/core/src/nako_indent_inline.mts +2 -2
  15. package/core/src/nako_lex_rules.mts +1 -1
  16. package/core/src/nako_parser3.mts +106 -165
  17. package/core/src/nako_parser_async.mts +97 -0
  18. package/core/src/nako_parser_base.mts +4 -55
  19. package/core/src/nako_parser_message.mts +105 -0
  20. package/core/src/nako_parser_operator.mts +93 -0
  21. package/core/src/nako_plugin_manager.mts +260 -0
  22. package/core/src/nako_require.mts +292 -0
  23. package/core/src/nako_runner.mts +191 -0
  24. package/core/src/nako_tokenizer.mts +221 -0
  25. package/core/src/plugin_csv.mts +1 -1
  26. package/core/src/plugin_system.mts +34 -3259
  27. package/core/src/plugin_system_array.mts +699 -0
  28. package/core/src/plugin_system_datetime.mts +368 -0
  29. package/core/src/plugin_system_debug.mts +403 -0
  30. package/core/src/plugin_system_dict.mts +85 -0
  31. package/core/src/plugin_system_json.mts +73 -0
  32. package/core/src/plugin_system_math.mts +383 -0
  33. package/core/src/plugin_system_regexp.mts +120 -0
  34. package/core/src/plugin_system_stdio.mts +86 -0
  35. package/core/src/plugin_system_string.mts +666 -0
  36. package/core/src/plugin_system_timer.mts +152 -0
  37. package/core/src/plugin_system_types.mts +151 -0
  38. package/core/src/plugin_system_url.mts +193 -0
  39. package/core/src/plugin_toml.mts +3 -3
  40. package/core/test/fixtures/README.md +39 -0
  41. package/core/test/fixtures/make_parser_ast_golden.mjs +31 -0
  42. package/core/test/fixtures/parser_ast_golden.json +8027 -0
  43. package/core/test/fixtures/parser_corpus.mjs +120 -0
  44. package/core/test/indent_test.mjs +6 -0
  45. package/core/test/nako_basic_plugins_test.mjs +44 -0
  46. package/core/test/nako_event_test.mjs +85 -0
  47. package/core/test/nako_gen_perf_test.mjs +178 -0
  48. package/core/test/nako_parser_async_test.mjs +112 -0
  49. package/core/test/nako_parser_test.mjs +160 -0
  50. package/core/test/nako_plugin_manager_test.mjs +185 -0
  51. package/core/test/nako_require_test.mjs +153 -0
  52. package/core/test/nako_runner_test.mjs +114 -0
  53. package/core/test/nako_tokenizer_test.mjs +115 -0
  54. package/core/test/plugin_system_debug_test.mjs +141 -0
  55. package/core/test/plugin_system_split_test.mjs +179 -0
  56. package/core/test/plugin_system_test.mjs +6 -0
  57. package/core/tsconfig.json +0 -1
  58. package/package.json +17 -21
  59. package/release/_hash.txt +36 -36
  60. package/release/_script-tags.txt +16 -16
  61. package/release/command.json +1 -1
  62. package/release/command.json.js +1 -1
  63. package/release/command_cnako3.json +1 -1
  64. package/release/command_list.json +1 -1
  65. package/release/edit_main.js +6 -6
  66. package/release/edit_main.js.map +3 -3
  67. package/release/editor.js +6 -6
  68. package/release/plugin_keigo.js.map +3 -3
  69. package/release/plugin_markup.js +46 -46
  70. package/release/plugin_markup.js.map +3 -3
  71. package/release/plugin_weykturtle3d.js +1 -1
  72. package/release/plugin_weykturtle3d.js.map +3 -3
  73. package/release/version.js +2 -2
  74. package/release/version_main.js +2 -2
  75. package/release/version_main.js.map +1 -1
  76. package/release/wnako3.js +186 -213
  77. package/release/wnako3.js.map +4 -4
  78. package/release/wnako3webworker.js +172 -199
  79. package/release/wnako3webworker.js.map +4 -4
  80. package/src/cnako3mod.mjs +7 -2
  81. package/src/cnako3mod.mts +7 -2
  82. package/src/nako_version.mjs +2 -2
  83. package/src/nako_version.mts +2 -2
  84. package/src/plugin_browser_ajax.mjs +4 -4
  85. package/src/plugin_browser_ajax.mts +4 -4
  86. package/src/plugin_browser_audio.mjs +10 -10
  87. package/src/plugin_browser_audio.mts +10 -10
  88. package/src/plugin_browser_camera.mjs +4 -4
  89. package/src/plugin_browser_camera.mts +4 -4
  90. package/src/plugin_browser_canvas.mjs +2 -2
  91. package/src/plugin_browser_canvas.mts +2 -2
  92. package/src/plugin_browser_crypto.mjs +3 -3
  93. package/src/plugin_browser_crypto.mts +3 -3
  94. package/src/plugin_browser_dom_event.mjs +1 -1
  95. package/src/plugin_browser_dom_event.mts +1 -1
  96. package/src/plugin_browser_geolocation.mjs +1 -1
  97. package/src/plugin_browser_geolocation.mts +1 -1
  98. package/src/plugin_browser_hotkey.mjs +1 -1
  99. package/src/plugin_browser_hotkey.mts +1 -1
  100. package/src/plugin_browser_html.mjs +1 -1
  101. package/src/plugin_browser_html.mts +1 -1
  102. package/src/plugin_browser_location.mjs +1 -1
  103. package/src/plugin_browser_location.mts +1 -1
  104. package/src/plugin_browser_speech.mjs +1 -1
  105. package/src/plugin_browser_speech.mts +1 -1
  106. package/src/plugin_browser_storage.mjs +2 -2
  107. package/src/plugin_browser_storage.mts +2 -2
  108. package/src/plugin_httpserver.mjs +3 -3
  109. package/src/plugin_httpserver.mts +3 -3
  110. package/src/plugin_keigo.mjs +2 -2
  111. package/src/plugin_keigo.mts +2 -2
  112. package/src/plugin_node.mjs +48 -48
  113. package/src/plugin_node.mts +53 -53
  114. package/src/plugin_weykturtle3d.mjs +56 -56
  115. package/src/plugin_weykturtle3d.mts +56 -56
  116. package/src/wnako3.mjs +1 -1
  117. package/src/wnako3.mts +1 -1
  118. package/src/wnako3_editor.mjs +5 -5
  119. package/src/wnako3_editor.mts +5 -5
  120. package/src/wnako3mod.mjs +2 -2
  121. package/src/wnako3mod.mts +2 -2
  122. package/core/src/nako3.mjs +0 -1021
  123. package/core/src/nako_ast.mjs +0 -4
  124. package/core/src/nako_colors.mjs +0 -77
  125. package/core/src/nako_core_version.mjs +0 -8
  126. package/core/src/nako_csv.mjs +0 -193
  127. package/core/src/nako_errors.mjs +0 -166
  128. package/core/src/nako_from_dncl.mjs +0 -285
  129. package/core/src/nako_from_dncl2.mjs +0 -347
  130. package/core/src/nako_gen.mjs +0 -2500
  131. package/core/src/nako_global.mjs +0 -138
  132. package/core/src/nako_indent.mjs +0 -442
  133. package/core/src/nako_indent_chars.mjs +0 -29
  134. package/core/src/nako_indent_inline.mjs +0 -361
  135. package/core/src/nako_josi_list.mjs +0 -47
  136. package/core/src/nako_lex_rules.mjs +0 -319
  137. package/core/src/nako_lexer.mjs +0 -794
  138. package/core/src/nako_logger.mjs +0 -221
  139. package/core/src/nako_parser3.mjs +0 -3250
  140. package/core/src/nako_parser_base.mjs +0 -403
  141. package/core/src/nako_parser_const.mjs +0 -37
  142. package/core/src/nako_prepare.mjs +0 -329
  143. package/core/src/nako_reserved_words.mjs +0 -42
  144. package/core/src/nako_source_mapping.mjs +0 -207
  145. package/core/src/nako_test.mjs +0 -37
  146. package/core/src/nako_token.mjs +0 -1
  147. package/core/src/nako_tools.mjs +0 -53
  148. package/core/src/nako_types.mjs +0 -14
  149. package/core/src/plugin_api.mjs +0 -4
  150. package/core/src/plugin_csv.mjs +0 -97
  151. package/core/src/plugin_math.mjs +0 -352
  152. package/core/src/plugin_promise.mjs +0 -102
  153. package/core/src/plugin_system.mjs +0 -3810
  154. package/core/src/plugin_test.mjs +0 -52
  155. package/core/src/plugin_toml.mjs +0 -39
@@ -1,9 +1,21 @@
1
1
 
2
- import { NakoRuntimeError } from './nako_errors.mjs'
3
- import { NakoGlobal } from './nako_global.mjs'
4
2
  import { NakoSystem } from './plugin_api.mjs'
5
-
6
- export default {
3
+ // plugin_system.mts は肥大化していたため、内容ごとに複数ファイルへ分割している (#2351)
4
+ // いずれも単独のプラグインではなく、実行時にこの plugin_system へマージされる
5
+ import PluginSystemDebug from './plugin_system_debug.mjs' // 特殊命令・デバッグ支援・プラグイン管理
6
+ import PluginSystemMath from './plugin_system_math.mjs' // 四則演算・論理演算・ビット演算
7
+ import PluginSystemString from './plugin_system_string.mjs' // 文字列処理・置換/トリム・文字変換・指定形式・文字種類
8
+ import PluginSystemArray from './plugin_system_array.mjs' // 配列操作・二次元配列処理
9
+ import PluginSystemDatetime from './plugin_system_datetime.mjs' // 日時処理(簡易)
10
+ import PluginSystemUrl from './plugin_system_url.mjs' // URLエンコード・パラメータ・BASE64・パス操作
11
+ import PluginSystemTypes from './plugin_system_types.mjs' // 型変換
12
+ import PluginSystemJson from './plugin_system_json.mjs' // JSON
13
+ import PluginSystemRegexp from './plugin_system_regexp.mjs' // 正規表現
14
+ import PluginSystemDict from './plugin_system_dict.mjs' // 辞書型変数の操作・ハッシュ
15
+ import PluginSystemStdio from './plugin_system_stdio.mjs' // 標準出力
16
+ import PluginSystemTimer from './plugin_system_timer.mjs' // タイマー
17
+
18
+ const PluginSystem = {
7
19
  'meta': {
8
20
  type: 'const',
9
21
  value: {
@@ -175,7 +187,7 @@ export default {
175
187
  sys.__evalJS = (src: string, sys?: NakoSystem) => {
176
188
  try {
177
189
  // まず従来通りevalで評価(式の値を返す互換性を維持)
178
- return eval(src)
190
+ return eval(src) // oxlint-disable-line no-eval
179
191
  } catch (e) {
180
192
  // return文によるSyntaxErrorの場合のみIIFEで再試行 (#NE-006)
181
193
  if (e instanceof SyntaxError && e.message.includes('return')) {
@@ -311,375 +323,6 @@ export default {
311
323
  }
312
324
  },
313
325
 
314
- // @標準出力
315
- '表示': { // @Sを表示 // @ひょうじ
316
- type: 'func',
317
- josi: [['を', 'と']],
318
- pure: true,
319
- fn: function(s: string, sys: any) {
320
- // 継続表示の一時プールを出力
321
- s = String(sys.__printPool) + s
322
- sys.__printPool = ''
323
- //
324
- sys.__setSysVar('表示ログ', String(sys.__getSysVar('表示ログ')) + s + '\n')
325
- sys.logger.send('stdout', s + '')
326
- },
327
- return_none: true
328
- },
329
- '継続表示': { // @Sを改行なしで表示(ただし「表示」命令を使うことで画面出力される) // @けいぞくひょうじ
330
- type: 'func',
331
- josi: [['を', 'と']],
332
- pure: true,
333
- fn: function(s: string, sys: any) {
334
- sys.__printPool += s
335
- },
336
- return_none: true
337
- },
338
- '連続表示': { // @引数に指定した引数を全て表示する // @れんぞくひょうじ
339
- type: 'func',
340
- josi: [['と', 'を']],
341
- isVariableJosi: true,
342
- pure: true,
343
- fn: function(...a: any) {
344
- const sys = a.pop()
345
- const v = a.join('')
346
- sys.__exec('表示', [v, sys])
347
- },
348
- return_none: true
349
- },
350
- '連続無改行表示': { // @引数に指定した引数を全て表示する(改行しない) // @れんぞくむかいぎょうひょうじ
351
- type: 'func',
352
- josi: [['と', 'を']],
353
- isVariableJosi: true,
354
- pure: true,
355
- fn: function(...a: any) {
356
- const sys = a.pop()
357
- const v = a.join('')
358
- sys.__exec('継続表示', [v, sys])
359
- },
360
- return_none: true
361
- },
362
- '表示ログ': { type: 'const', value: '' }, // @ひょうじろぐ
363
- '表示ログクリア': { // @表示ログを空にする // @ひょうじろぐくりあ
364
- type: 'func',
365
- josi: [],
366
- pure: true,
367
- fn: function(sys: NakoSystem) {
368
- sys.__setSysVar('表示ログ', '')
369
- },
370
- return_none: true
371
- },
372
- '言': { // @Sを表示 // @いう
373
- type: 'func',
374
- josi: [['を', 'と']],
375
- pure: true,
376
- fn: function(s: string, sys: any) {
377
- sys.logger.send('stdout', s + '')
378
- },
379
- return_none: true
380
- },
381
- 'コンソール表示': { // @Sをコンソール表示する(console.log) // @こんそーるひょうじ
382
- type: 'func',
383
- josi: [['を', 'と']],
384
- pure: true,
385
- fn: function(s: string) {
386
- console.log(s)
387
- },
388
- return_none: true
389
- },
390
-
391
- // @四則演算
392
- '足': { // @AとBを足す(算術演算を行う) // @たす
393
- type: 'func',
394
- josi: [['に', 'と'], ['を']],
395
- isVariableJosi: false,
396
- pure: true,
397
- fn: function(a: any, b: any) {
398
- if (typeof (a) === 'bigint' || typeof (b) === 'bigint') {
399
- return BigInt(a) + BigInt(b)
400
- }
401
- return parseFloat(a) + parseFloat(b)
402
- }
403
- },
404
- '合計': { // @引数(可変)に指定した値を全て合計して返す // @ごうけい
405
- type: 'func',
406
- josi: [['と', 'を', 'の']],
407
- isVariableJosi: true,
408
- pure: true,
409
- fn: function(...a: any) {
410
- const sys = a.pop() // remove NakoSystem
411
- if (a.length >= 1 && a[0] instanceof Array) {
412
- return sys.__exec('配列合計', [a[0], sys])
413
- }
414
- let isBigInt = false
415
- let sum = 0
416
- for (const v of a) {
417
- if (typeof (v) === 'bigint') {
418
- isBigInt = true
419
- break
420
- }
421
- sum += parseFloat(v)
422
- }
423
- if (isBigInt) {
424
- let bigsum = 0n
425
- for (const v of a) {
426
- bigsum += BigInt(v)
427
- }
428
- return bigsum
429
- }
430
- return sum
431
- }
432
- },
433
- '引': { // @AからBを引く // @ひく
434
- type: 'func',
435
- josi: [['から'], ['を']],
436
- pure: true,
437
- fn: function(a: any, b: any) {
438
- return a - b
439
- }
440
- },
441
- '掛': { // @AにBを掛ける // @かける
442
- type: 'func',
443
- josi: [['に', 'と'], ['を']],
444
- pure: true,
445
- fn: function(a: any, b: any) {
446
- // 数値の掛け算
447
- if (typeof a === 'number') {
448
- return a * b
449
- }
450
- // 文字列の掛け算(文字列の繰り返し)
451
- if (typeof a === 'string') {
452
- let s = ''
453
- for (let i = 0; i < parseInt(b); i++) {
454
- s += a
455
- }
456
- return s
457
- }
458
- // 配列の繰り返し
459
- if (a instanceof Array) {
460
- const aa: any[] = []
461
- for (let i = 0; i < parseInt(b); i++) {
462
- aa.push(...a)
463
- }
464
- return aa
465
- }
466
- return a * b
467
- }
468
- },
469
- '倍': { // @AのB倍を求める // @ばい
470
- type: 'func',
471
- josi: [['の', 'を'], ['']],
472
- pure: true,
473
- fn: function(a: any, b: any) {
474
- return a * b
475
- }
476
- },
477
- '割': { // @AをBで割る // @わる
478
- type: 'func',
479
- josi: [['を'], ['で']],
480
- pure: true,
481
- fn: function(a: any, b: any) {
482
- return a / b
483
- }
484
- },
485
- '割余': { // @AをBで割った余りを求める // @わったあまり
486
- type: 'func',
487
- josi: [['を'], ['で']],
488
- pure: true,
489
- fn: function(a: any, b: any) {
490
- return a % b
491
- }
492
- },
493
- '偶数': { // @Aが偶数なら真を返す // @ぐうすう
494
- type: 'func',
495
- josi: [['が']],
496
- pure: true,
497
- fn: function(a: any) {
498
- return (parseInt(a) % 2 === 0)
499
- }
500
- },
501
- '奇数': { // @Aが奇数なら真を返す // @きすう
502
- type: 'func',
503
- josi: [['が']],
504
- pure: true,
505
- fn: function(a: any) {
506
- return (parseInt(a) % 2 === 1)
507
- }
508
- },
509
- '二乗': { // @Aを二乗する // @にじょう
510
- type: 'func',
511
- josi: [['の', 'を']],
512
- pure: true,
513
- fn: function(a: any) {
514
- return a * a
515
- }
516
- },
517
- 'べき乗': { // @AのB乗を求める // @べきじょう
518
- type: 'func',
519
- josi: [['の'], ['の']],
520
- pure: true,
521
- fn: function(a: any, b: any) {
522
- return Math.pow(a, b)
523
- }
524
- },
525
- '以上': { // @AがB以上か // @いじょう
526
- type: 'func',
527
- josi: [['が'], ['']],
528
- pure: true,
529
- fn: function(a: any, b: any) {
530
- return a >= b
531
- }
532
- },
533
- '以下': { // @AがB以下か // @いか
534
- type: 'func',
535
- josi: [['が'], ['']],
536
- pure: true,
537
- fn: function(a: any, b: any) {
538
- return a <= b
539
- }
540
- },
541
- '未満': { // @AがB未満か // @みまん
542
- type: 'func',
543
- josi: [['が'], ['']],
544
- pure: true,
545
- fn: function(a: any, b: any) {
546
- return a < b
547
- }
548
- },
549
- '超': { // @AがB超か // @ちょう
550
- type: 'func',
551
- josi: [['が'], ['']],
552
- pure: true,
553
- fn: function(a: any, b: any) {
554
- return a > b
555
- }
556
- },
557
- '等': { // @AがBと等しいか // @ひとしい
558
- type: 'func',
559
- josi: [['が'], ['と']],
560
- pure: true,
561
- fn: function(a: any, b: any) {
562
- return a === b
563
- }
564
- },
565
- '等無': { // @AがBと等しくないか // @ひとしくない
566
- type: 'func',
567
- josi: [['が'], ['と']],
568
- pure: true,
569
- fn: function(a: any, b: any) {
570
- return a !== b
571
- }
572
- },
573
- '一致': { // @AがBと一致するか(配列や辞書も比較可能) // @いっち
574
- type: 'func',
575
- josi: [['が'], ['と']],
576
- pure: true,
577
- fn: function(a: any, b: any) {
578
- // オブジェクトの場合、JSONに変換して比較
579
- if (typeof (a) === 'object') {
580
- const jsonA = JSON.stringify(a)
581
- const jsonB = JSON.stringify(b)
582
- return jsonA === jsonB
583
- }
584
- return a === b
585
- }
586
- },
587
- '不一致': { // @AがBと不一致か(配列や辞書も比較可能) // @ふいっち
588
- type: 'func',
589
- josi: [['が'], ['と']],
590
- pure: true,
591
- fn: function(a: any, b: any) {
592
- // オブジェクトの場合、JSONに変換して比較
593
- if (typeof (a) === 'object') {
594
- const jsonA = JSON.stringify(a)
595
- const jsonB = JSON.stringify(b)
596
- return jsonA !== jsonB
597
- }
598
- return a !== b
599
- }
600
- },
601
- '範囲内': { // @VがAからBの範囲内か // @はんいない
602
- type: 'func',
603
- josi: [['が'], ['から'], ['の', 'までの']],
604
- pure: true,
605
- fn: function(v: any, a: any, b: any) {
606
- return (a <= v) && (v <= b)
607
- }
608
- },
609
- '範囲': { // @AからBの範囲を表現する範囲オブジェクトを返す // @はんい
610
- type: 'func',
611
- josi: [['から'], ['の', 'までの']],
612
- pure: true,
613
- fn: function(a: any, b: any) {
614
- return {
615
- '先頭': a,
616
- '末尾': b
617
- }
618
- }
619
- },
620
- '連続加算': { // @A1+A2+A3...にBを足す // @れんぞくかさん
621
- type: 'func',
622
- josi: [['を'], ['に', 'と']],
623
- isVariableJosi: true,
624
- pure: true,
625
- fn: function(b: any, ...a: any) {
626
- a.pop() // 必ず末尾に sys があるので、末尾のシステム変数を除外
627
- a.push(b)
628
-
629
- return a.reduce((p: any, c: any) => p + c)
630
- }
631
- },
632
- 'MAX': { // @2個以上の数値のうち最大値を返す。// @MAX
633
- type: 'func',
634
- josi: [['の'], ['と']],
635
- isVariableJosi: true,
636
- pure: true,
637
- fn: function(b: number, ...a: any): number {
638
- const sys = a.pop()
639
- return sys.__exec('最大値', [b, ...a, sys])
640
- }
641
- },
642
- '最大値': { // @2個以上の数値のうち最大値を返す。// @さいだいち
643
- type: 'func',
644
- josi: [['の'], ['と']],
645
- isVariableJosi: true,
646
- pure: true,
647
- fn: function(b: number, ...a: any): number {
648
- a.pop() // 必ず末尾に sys があるので、末尾のシステム変数を除外
649
- a.push(b)
650
- return a.reduce((p: number, c: number) => Math.max(p, c))
651
- }
652
- },
653
- 'MIN': { // @2個以上の数値のうち最小値を返す。// @MIN
654
- type: 'func',
655
- josi: [['の'], ['と']],
656
- isVariableJosi: true,
657
- pure: true,
658
- fn: function(b: number, ...a: any): number {
659
- const sys = a.pop()
660
- return sys.__exec('最小値', [b, ...a, sys])
661
- }
662
- },
663
- '最小値': { // @2個以上の数値のうち最小値を返す。// @さいしょうち
664
- type: 'func',
665
- josi: [['の'], ['と']],
666
- isVariableJosi: true,
667
- pure: true,
668
- fn: function(b: number, ...a: any): number {
669
- a.pop() // 必ず末尾に sys があるので、末尾のシステム変数を除外
670
- a.push(b)
671
- return a.reduce((p: number, c: number) => Math.min(p, c))
672
- }
673
- },
674
- 'CLAMP': { // @数値を下限から上限の範囲内に収めた値を返す。// @CLAMP
675
- type: 'func',
676
- josi: [['の', 'を'], ['から'], ['までの', 'で']],
677
- pure: true,
678
- fn: function(x: number, a: number, b: number): number {
679
- return Math.min(Math.max(x, a), b)
680
- }
681
- },
682
-
683
326
  // @敬語
684
327
  'ください': { // @敬語対応のため // @ください
685
328
  type: 'func',
@@ -739,2889 +382,21 @@ export default {
739
382
  }
740
383
  },
741
384
 
742
- // @特殊命令
743
- 'JS実行': { // @JavaScriptのコードSRCを実行する(変数sysでなでしこシステムを参照できる) // @JSじっこう
744
- type: 'func',
745
- josi: [['を', 'で']],
746
- pure: true,
747
- fn: function(src: string, sys: NakoSystem) {
748
- return sys.__evalJS(src, sys) // #1733
749
- }
750
- },
751
- 'JSオブジェクト取得': { // @なでしこで定義した関数や変数nameのJavaScriptオブジェクトを取得する // @JSおぶじぇくとしゅとく
752
- type: 'func',
753
- josi: [['の']],
754
- pure: false,
755
- fn: function(name: string, sys: any) {
756
- return sys.__findVar(name, null)
757
- }
758
- },
759
- 'JS関数実行': { // @JavaScriptの関数NAMEを引数ARGS(配列)で実行する // @JSかんすうじっこう
760
- type: 'func',
761
- josi: [['を'], ['で']],
762
- fn: function(name: any, args: any, sys: NakoSystem) {
763
- // nameが文字列ならevalして関数を得る
764
-
765
- if (typeof name === 'string') { name = sys.__evalJS(name, sys) }
766
- if (typeof name !== 'function') { throw new Error('JS関数取得で実行できません。') }
767
-
768
- // argsがArrayでなければArrayに変換する
769
- if (!(args instanceof Array)) { args = [args] }
770
-
771
- // 実行
772
- // eslint-disable-next-line prefer-spread
773
- return name.apply(null, args)
774
- }
775
- },
776
- 'ASYNC': { // @なでしこのユーザー関数定義でASYNC(非同期関数である)ことを宣言する // @ASYNC
777
- type: 'func',
778
- josi: [],
779
- asyncFn: true,
780
- pure: true,
781
- fn: async function() {
782
- // empty
783
- },
784
- return_none: true
785
- },
786
- 'AWAIT実行': { // @JavaScriptの非同期関数(Promise/async関数)のFを引数ARGSでawait実行する // @AWAITじっこう
787
- type: 'func',
788
- josi: [['を'], ['で']],
789
- pure: true,
790
- asyncFn: true,
791
- fn: async function(f: any, args: any, sys: any) {
792
- // nameが文字列ならevalして関数を得る
793
- if (typeof f === 'string') { f = sys.__findFunc(f, 'AWAIT実行') }
794
- if (!(f instanceof Function)) { throw new Error('『AWAIT実行』の第一引数はなでしこ関数名かFunction型で指定してください。') }
795
- // 実行
796
- return await f(...args)
797
- }
798
- },
799
- 'JSメソッド実行': { // @JavaScriptのオブジェクトOBJのメソッドMを引数ARGS(配列)で実行する // @JSめそっどじっこう
800
- type: 'func',
801
- josi: [['の'], ['を'], ['で']],
802
- fn: function(obj: any, m: any, args: any, sys: NakoSystem) {
803
- // objが文字列ならevalして関数を得る
804
-
805
- if (typeof obj === 'string') { obj = sys.__evalJS(obj, sys) }
806
- if (typeof obj !== 'object') { throw new Error('JSオブジェクトを取得できませんでした。') }
807
-
808
- // method を求める
809
- if (typeof m !== 'function') {
810
- m = obj[m]
811
- }
812
-
813
- // argsがArrayでなければArrayに変換する
814
- if (!(args instanceof Array)) { args = [args] }
815
-
816
- // 実行
817
- return m.apply(obj, args)
818
- }
819
- },
820
-
821
- 'ナデシコ': { // @なでしこのコードCODEを実行する // @なでしこする
822
- type: 'func',
823
- josi: [['を', 'で']],
824
- pure: false,
825
- asyncFn: true,
826
- fn: async function(code: string, sys: any) {
827
- const options = {
828
- resetEnv: false,
829
- resetAll: true,
830
- nakoGlobal: sys
831
- }
832
- const tmpLog = String(sys.__getSysVar('表示ログ', ''))
833
- sys.__setSysVar('表示ログ', '')
834
- await sys.__self.runAsync(code, sys.__modName, options)
835
- const outLog = String(sys.__getSysVar('表示ログ'))
836
- sys.__setSysVar('表示ログ', tmpLog + outLog)
837
- return outLog
838
- }
839
- },
840
- 'ナデシコ続': { // @なでしこのコードCODEを実行する // @なでしこつづける
841
- type: 'func',
842
- josi: [['を', 'で']],
843
- pure: false,
844
- asyncFn: true,
845
- fn: async function(code: string, sys: any) {
846
- const options = {
847
- resetEnv: false,
848
- resetAll: false,
849
- nakoGlobal: sys.__self
850
- }
851
- const tmpLog = sys.__getSysVar('表示ログ', '')
852
- sys.__setSysVar('表示ログ', '')
853
- await sys.__self.runAsync(code, sys.__modName, options)
854
- const outLog = String(sys.__getSysVar('表示ログ'))
855
- if (outLog) {
856
- sys.logger.trace(outLog)
857
- }
858
- sys.__setSysVar('表示ログ', tmpLog + outLog)
859
- return outLog
860
- }
861
- },
862
- '実行': { // @ 無名関数(あるいは、文字列で関数名を指定)Fを実行する(Fが関数でなければ無視する) // @じっこう
863
- type: 'func',
864
- josi: [['を', 'に', 'で']],
865
- pure: false,
866
- fn: function(f: any, sys: any) {
867
- // #938 の規則に従って処理
868
- // 引数が関数なら実行
869
- if (typeof f === 'function') { return f(sys) }
870
- // 文字列なら関数に変換できるか判定して実行
871
- if (typeof f === 'string') {
872
- const tf = sys.__findFunc(f, '実行')
873
- if (typeof tf === 'function') {
874
- return tf(sys)
875
- }
876
- }
877
- // それ以外ならそのまま値を返す
878
- return f
879
- }
880
- },
881
- '実行時間計測': { // @ 関数Fを実行して要した時間をミリ秒で返す // @じっこうじかんけいそく
882
- type: 'func',
883
- josi: [['の']],
884
- pure: false,
885
- fn: function(f: any, sys: any) {
886
- if (typeof f === 'string') { f = sys.__findFunc(f, '実行時間計測') }
887
- //
888
- if (performance && performance.now) {
889
- const t1 = performance.now()
890
- f(sys)
891
- const t2 = performance.now()
892
- return (t2 - t1)
893
- } else {
894
- const t1 = Date.now()
895
- f(sys)
896
- const t2 = Date.now()
897
- return (t2 - t1)
898
- }
899
- }
900
- },
901
- '終': { // @終わる // @おわる
902
- type: 'func',
903
- josi: [],
904
- pure: true,
905
- fn: function(sys: NakoSystem) {
906
- // デバッグモードでなければ例外を投げることでプログラムを終了させる
907
- sys.__setSysVar('__forceClose', true)
908
- if (!sys.__getSysVar('__useDebug')) { throw new Error('__終わる__') }
909
- }
910
- },
385
+ }
911
386
 
912
- // @型変換
913
- '変数型確認': { // @変数Vの型を返す // @へんすうかたかくにん
914
- type: 'func',
915
- josi: [['の']],
916
- pure: true,
917
- fn: function(v: any) {
918
- return (typeof v)
919
- }
920
- },
921
- 'TYPEOF': { // @変数Vの型を返す // @TYPEOF
922
- type: 'func',
923
- josi: [['の']],
924
- pure: true,
925
- fn: function(v: any) {
926
- return (typeof v)
927
- }
928
- },
929
- '文字列変換': { // @値Vを文字列に変換 // @もじれつへんかん
930
- type: 'func',
931
- josi: [['を']],
932
- pure: true,
933
- fn: function(v: any): string {
934
- return String(v)
935
- }
936
- },
937
- 'TOSTR': { // @値Vを文字列に変換 // @TOSTR
938
- type: 'func',
939
- josi: [['を']],
940
- pure: true,
941
- fn: function(v: any): string {
942
- return String(v)
943
- }
944
- },
945
- '整数変換': { // @値Vを整数に変換 // @せいすうへんかん
946
- type: 'func',
947
- josi: [['を']],
948
- pure: true,
949
- fn: function(v: any): number {
950
- return parseInt(v)
951
- }
952
- },
953
- 'TOINT': { // @値Vを整数に変換 // @TOINT
954
- type: 'func',
955
- josi: [['を']],
956
- pure: true,
957
- fn: function(v: any): number {
958
- return parseInt(v)
959
- }
960
- },
961
- '実数変換': { // @値Vを実数に変換 // @じっすうへんかん
962
- type: 'func',
963
- josi: [['を']],
964
- pure: true,
965
- fn: function(v: any): number {
966
- return parseFloat(v)
967
- }
968
- },
969
- 'TOFLOAT': { // @値Vを実数に変換 // @TOFLOAT
970
- type: 'func',
971
- josi: [['を']],
972
- pure: true,
973
- fn: function(v: any): number {
974
- return parseFloat(v)
975
- }
976
- },
977
- 'INT': { // @値Vを整数に変換 // @INT
978
- type: 'func',
979
- josi: [['の']],
980
- pure: true,
981
- fn: function(v: any): number {
982
- return parseInt(v)
983
- }
984
- },
985
- 'FLOAT': { // @値Vを実数に変換 // @FLOAT
986
- type: 'func',
987
- josi: [['の']],
988
- pure: true,
989
- fn: function(v: any): number {
990
- return parseFloat(v)
991
- }
992
- },
993
- 'NAN判定': { // @値VがNaNかどうかを判定(命令『非数判定』を使う事を推奨) // @NANはんてい
994
- type: 'func',
995
- josi: [['を']],
996
- pure: true,
997
- fn: function(v: any): boolean {
998
- return isNaN(v)
999
- }
1000
- },
1001
- '非数判定': { // @値Vが非数かどうかを判定(NAN判定より堅牢) // @ひすうはんてい
1002
- type: 'func',
1003
- josi: [['を']],
1004
- pure: true,
1005
- fn: function(v: any): boolean {
1006
- // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
1007
- return Number.isNaN(v)
1008
- }
1009
- },
1010
- 'HEX': { // @値Vを16進数に変換 // @HEX
1011
- type: 'func',
1012
- josi: [['の']],
1013
- pure: true,
1014
- fn: function(a: any): string {
1015
- return parseInt(a).toString(16)
1016
- }
1017
- },
1018
- '進数変換': { // @値VをN進数に変換 // @しんすうへんかん
1019
- type: 'func',
1020
- josi: [['を', 'の'], ['']],
1021
- pure: true,
1022
- fn: function(v: any, n: number): string {
1023
- return parseInt(v).toString(n)
1024
- }
1025
- },
1026
- '二進': { // @値Vを2進数に変換 // @にしん
1027
- type: 'func',
1028
- josi: [['を', 'の', 'から']],
1029
- pure: true,
1030
- fn: function(v: any): string {
1031
- return parseInt(v).toString(2)
1032
- }
1033
- },
1034
- '二進表示': { // @値Vを2進数に変換して表示 // @にしんひょうじ
1035
- type: 'func',
1036
- josi: [['を', 'の', 'から']],
1037
- pure: true,
1038
- fn: function(v: any, sys: any) {
1039
- const s = parseInt(v).toString(2)
1040
- sys.__exec('表示', [s, sys])
1041
- }
1042
- },
1043
- 'RGB': { // @HTML用のカラーコードを返すRGB(R,G,B)で各値は0-255 // @RGB
1044
- type: 'func',
1045
- josi: [['と'], ['の'], ['で']],
1046
- pure: true,
1047
- fn: function(r: any, g: any, b: any): string {
1048
- const z2 = (v: any): string => {
1049
- const v2: string = '00' + (parseInt(String(v)).toString(16))
1050
- return v2.substring(v2.length - 2, v2.length)
1051
- }
1052
- return '#' + z2(r) + z2(g) + z2(b)
1053
- }
1054
- },
1055
-
1056
- // @論理演算
1057
- '論理OR': { // @AとBの論理和を返す(v1非互換)。 // @ろんりOR
1058
- type: 'func',
1059
- josi: [['と'], ['の']],
1060
- pure: true,
1061
- fn: function(a: any, b: any): any {
1062
- return (a || b)
1063
- }
1064
- },
1065
- '論理AND': { // @AとBの論理積を返す(v1非互換)。日本語の「AかつB」に相当する // @ろんりAND
1066
- type: 'func',
1067
- josi: [['と'], ['の']],
1068
- pure: true,
1069
- fn: function(a: any, b: any): boolean {
1070
- return (a && b)
1071
- }
1072
- },
1073
- '論理NOT': { // @値Vが0や空ならばtrue、それ以外ならばfalseを返す(v1非互換) // @ろんりNOT
1074
- type: 'func',
1075
- josi: [['の']],
1076
- pure: true,
1077
- fn: function(v: any): boolean {
1078
- return (!v)
1079
- }
1080
- },
1081
-
1082
- // @ビット演算
1083
- 'OR': { // @(ビット演算で)AとBの論理和を返す。 // @OR
1084
- type: 'func',
1085
- josi: [['と'], ['の']],
1086
- pure: true,
1087
- fn: function(a: any, b: any): any {
1088
- return (a | b)
1089
- }
1090
- },
1091
- 'AND': { // @(ビット演算で)AとBの論理積を返す。日本語の「AかつB」に相当する // @AND
1092
- type: 'func',
1093
- josi: [['と'], ['の']],
1094
- pure: true,
1095
- fn: function(a: any, b: any): any {
1096
- return (a & b)
1097
- }
1098
- },
1099
- 'XOR': { // @(ビット演算で)AとBの排他的論理和を返す。// @XOR
1100
- type: 'func',
1101
- josi: [['と'], ['の']],
1102
- pure: true,
1103
- fn: function(a: any, b: any): any {
1104
- return (a ^ b)
1105
- }
1106
- },
1107
- 'NOT': { // @(ビット演算で)Vの各ビットを反転して返す。// @NOT
1108
- type: 'func',
1109
- josi: [['の']],
1110
- pure: true,
1111
- fn: function(v: any): any {
1112
- return (~v)
1113
- }
1114
- },
1115
- 'SHIFT_L': { // @VをAビット左へシフトして返す // @SHIFT_L
1116
- type: 'func',
1117
- josi: [['を'], ['で']],
1118
- pure: true,
1119
- fn: function(v: number, a: number): number {
1120
- return (v << a)
1121
- }
1122
- },
1123
- 'SHIFT_R': { // @VをAビット右へシフトして返す(符号を維持する) // @SHIFT_R
1124
- type: 'func',
1125
- josi: [['を'], ['で']],
1126
- pure: true,
1127
- fn: function(v: number, a: number): number {
1128
- return (v >> a)
1129
- }
1130
- },
1131
- 'SHIFT_UR': { // @VをAビット右へシフトして返す(符号を維持しない、0で埋める) // @SHIFT_UR
1132
- type: 'func',
1133
- josi: [['を'], ['で']],
1134
- pure: true,
1135
- fn: function(v: number, a: number): number {
1136
- return (v >>> a)
1137
- }
1138
- },
1139
-
1140
- // @文字列処理
1141
- '文字数': { // @文字列Vの文字数を返す // @もじすう
1142
- type: 'func',
1143
- josi: [['の']],
1144
- pure: true,
1145
- fn: function(v: any): number {
1146
- if (!Array.from) { return String(v).length }
1147
- // Unicodeのサロゲートペアを考慮して文字数をカウント #1954 を参照
1148
- return Array.from(v).length
1149
- }
1150
- },
1151
- '何文字目': { // @文字列SでAが何文字目にあるか調べて返す。見つからなければ0を返す。 // @なんもじめ
1152
- type: 'func',
1153
- josi: [['で', 'の'], ['が']],
1154
- pure: true,
1155
- fn: function(s: string, a: string): number {
1156
- // Unicodeのサロゲートペアを考慮して、文字列を検索 #1954 を参照
1157
- // return String(s).indexOf(a) + 1 // サロゲートペアを無視した場合
1158
- const strArray = Array.from(s)
1159
- const searchArray = Array.from(a)
1160
- for (let i = 0; i < strArray.length; i++) {
1161
- if (strArray.slice(i, i + searchArray.length).join('') === searchArray.join('')) {
1162
- return i + 1
1163
- }
1164
- }
1165
- return 0
1166
- }
1167
- },
1168
- 'CHR': { // @文字コードV(あるいは文字列配列)から文字を返す // @CHR
1169
- type: 'func',
1170
- josi: [['の']],
1171
- pure: true,
1172
- fn: function(v: number|number[]): string|string[] {
1173
- // 数値のとき
1174
- if (typeof v === 'number') {
1175
- if (!String.fromCodePoint) { return String.fromCharCode(v) }
1176
- return String.fromCodePoint(v)
1177
- }
1178
- // 配列のとき
1179
- const res: string[] = []
1180
- for (const s of v) {
1181
- if (!String.fromCodePoint) { res.push(String.fromCharCode(s)) }
1182
- res.push(String.fromCodePoint(s))
1183
- }
1184
- return res
1185
- }
1186
- },
1187
- 'ASC': { // @文字列V(あるいは文字列配列)の最初の文字の文字コードを返す // @ASC
1188
- type: 'func',
1189
- josi: [['の']],
1190
- pure: true,
1191
- fn: function(v: string|string[]): number|number[] {
1192
- if (typeof v === 'string') {
1193
- if (!String.prototype.codePointAt) { return String(v).charCodeAt(0) }
1194
- return String(v).codePointAt(0) || 0
1195
- }
1196
- const res: number[] = []
1197
- for (const s of v) {
1198
- if (!String.prototype.codePointAt) { res.push(String(s).charCodeAt(0)) }
1199
- res.push(String(s).codePointAt(0) || 0)
1200
- }
1201
- return res
1202
- }
1203
- },
1204
- '文字挿入': { // @文字列SのI文字目に文字列Aを挿入する // @もじそうにゅう
1205
- type: 'func',
1206
- josi: [['で', 'の'], ['に', 'へ'], ['を']],
1207
- pure: true,
1208
- fn: function(s: string, i: number, a: string): string {
1209
- if (i <= 0) { i = 1 }
1210
- const strArray = Array.from(s)
1211
- strArray.splice(i - 1, 0, a)
1212
- return strArray.join('')
1213
- }
1214
- },
1215
- '文字検索': { // @文字列SでA文字目から文字列Bを検索。見つからなければ0を返す。(類似命令に『何文字目』がある)(v1非互換) // @もじけんさく
1216
- type: 'func',
1217
- josi: [['で', 'の'], ['から'], ['を']],
1218
- pure: true,
1219
- fn: function(s: string, a: number, b: string): number {
1220
- // サロゲートペアを考慮して文字列を検索する
1221
- // return String(s).indexOf(b, a - 1) + 1
1222
- if (a <= 0) { a = 1 }
1223
- const strArray = Array.from(s)
1224
- const searchArray = Array.from(b)
1225
- // Unicode単位で検索
1226
- for (let i = a - 1; i < strArray.length; i++) {
1227
- if (strArray.slice(i, i + searchArray.length).join('') === searchArray.join('')) {
1228
- // 合致した
1229
- return i + 1
1230
- }
1231
- }
1232
- return 0
1233
- }
1234
- },
1235
- '追加': { // @文字列または配列SにAを追加して返す(v1非互換) // @ついか
1236
- type: 'func',
1237
- josi: [['で', 'に', 'へ'], ['を']],
1238
- pure: true,
1239
- fn: function(s: any, a: any): any {
1240
- if (s instanceof Array) {
1241
- s.push(a)
1242
- return s
1243
- }
1244
- return String(s) + String(a)
1245
- }
1246
- },
1247
- '一行追加': { // @文字列または配列SにAと改行を追加して返す(v1非互換) // @いちぎょうついか
1248
- type: 'func',
1249
- josi: [['で', 'に', 'へ'], ['を']],
1250
- pure: true,
1251
- fn: function(s: any, a: any): any {
1252
- if (s instanceof Array) {
1253
- s.push(a)
1254
- return s
1255
- }
1256
- return String(s) + String(a) + '\n'
1257
- }
1258
- },
1259
- '連結': { // @引数(可変)に指定した文字列を連結して文字列を返す // @れんけつ
1260
- type: 'func',
1261
- josi: [['と', 'を']],
1262
- pure: true,
1263
- isVariableJosi: true,
1264
- fn: function(...a: any) {
1265
- a.pop() // NakoSystemを取り除く
1266
- return a.join('')
1267
- }
1268
- },
1269
- '文字列連結': { // @引数(可変)に指定した文字列を連結して文字列を返す // @もじれつれんけつ
1270
- type: 'func',
1271
- josi: [['と', 'を']],
1272
- pure: true,
1273
- isVariableJosi: true,
1274
- fn: function(...a: any) {
1275
- a.pop() // NakoSystemを取り除く
1276
- return a.join('')
1277
- }
1278
- },
1279
- '文字列分解': { // @文字列Vを一文字ずつに分解して返す // @もじれつぶんかい
1280
- type: 'func',
1281
- josi: [['を', 'の', 'で']],
1282
- pure: true,
1283
- fn: function(v: any) {
1284
- if (!Array.from) { return String(v).split('') }
1285
- return Array.from(v)
1286
- }
1287
- },
1288
- 'リフレイン': { // @文字列VをCNT回繰り返す(v1非互換) // @りふれいん
1289
- type: 'func',
1290
- josi: [['を', 'の'], ['で']],
1291
- pure: true,
1292
- fn: function(v: any, cnt: number): string {
1293
- let s = ''
1294
- for (let i = 0; i < cnt; i++) { s += String(v) }
1295
- return s
1296
- }
1297
- },
1298
- '出現回数': { // @文字列SにAが何回出現するか数える // @しゅつげんかいすう
1299
- type: 'func',
1300
- josi: [['で'], ['の']],
1301
- pure: true,
1302
- fn: function(s: string, a: string) {
1303
- s = '' + s
1304
- a = '' + a
1305
- return s.split(a).length - 1
1306
- }
1307
- },
1308
- 'MID': { // @文字列SのA文字目からCNT文字を抽出する(『文字抜出』と同じ) // @MID
1309
- type: 'func',
1310
- josi: [['で', 'の'], ['から'], ['を']],
1311
- pure: true,
1312
- fn: function(s: any, a: any, cnt: number, sys: NakoSystem) {
1313
- return sys.__exec('文字抜出', [s, a, cnt])
1314
- }
1315
- },
1316
- '文字抜出': { // @文字列SのA文字目からCNT文字を抽出する(Aが0未満の時は後ろからA文字目からCNT文字を抽出) // @もじぬきだす
1317
- type: 'func',
1318
- josi: [['で', 'の'], ['から'], ['を', '']],
1319
- pure: true,
1320
- fn: function(s: any, a: number, cnt: number) {
1321
- // 引数の型チェック #1995
1322
- if (typeof a === 'string') { a = parseInt(a) }
1323
- if (typeof cnt === 'string') { cnt = parseInt(cnt) }
1324
- // もし、cntが0以下なら空文字を返す
1325
- if (cnt <= 0) { return '' }
1326
- // サロゲートペアを考慮した処理を行う
1327
- const strArray = Array.from(s)
1328
- // もし、aの値が0未満の時は後ろからa文字目からcnt文字を抽出
1329
- if (a < 0) {
1330
- a = strArray.length + a + 1
1331
- if (a < 0) { a = 1 }
1332
- }
1333
- return strArray.slice(a - 1, a + cnt - 1).join('')
1334
- }
1335
- },
1336
- 'LEFT': { // @文字列Sの左端からCNT文字を抽出する // @LEFT
1337
- type: 'func',
1338
- josi: [['の', 'で'], ['だけ']],
1339
- pure: true,
1340
- fn: function(s: string, cnt: number, sys: NakoSystem): string {
1341
- return sys.__exec('文字左部分', [s, cnt])
1342
- }
1343
- },
1344
- '文字左部分': { // @文字列Sの左端からCNT文字を抽出する // @もじひだりぶぶん
1345
- type: 'func',
1346
- josi: [['の', 'で'], ['だけ', '']],
1347
- pure: true,
1348
- fn: function(s: string, cnt: number): string {
1349
- // return (String(s).substring(0, cnt))
1350
- // サロゲートペアを考慮
1351
- const strArray = Array.from(s)
1352
- return strArray.slice(0, cnt).join('')
1353
- }
1354
- },
1355
- 'RIGHT': { // @文字列Sの右端からCNT文字を抽出する(『文字右部分』と同じ) // @RIGHT
1356
- type: 'func',
1357
- josi: [['の', 'で'], ['だけ']],
1358
- pure: true,
1359
- fn: function(s: string, cnt: number, sys: NakoSystem): string {
1360
- return sys.__exec('文字右部分', [s, cnt])
1361
- }
1362
- },
1363
- '文字右部分': { // @文字列Sの右端からCNT文字を抽出する // @もじみぎぶぶん
1364
- type: 'func',
1365
- josi: [['の', 'で'], ['だけ', '']],
1366
- pure: true,
1367
- fn: function(s: string, cnt: number): string {
1368
- // return (s.substring(s.length - cnt, s.length))
1369
- // サロゲートペアを考慮
1370
- const strArray = Array.from(s)
1371
- let index = strArray.length - cnt
1372
- if (index < 0) { index = 0 }
1373
- return strArray.slice(index, strArray.length).join('')
1374
- }
1375
- },
1376
- '区切': { // @文字列Sを区切り文字Aで区切って配列で返す // @くぎる
1377
- type: 'func',
1378
- josi: [['の', 'を'], ['で']],
1379
- pure: true,
1380
- fn: function(s: string, a: string) {
1381
- return ('' + s).split('' + a)
1382
- }
1383
- },
1384
- '文字列分割': { // @文字列Sを区切り文字Aで分割して配列で返す // @もじれつぶんかつ
1385
- type: 'func',
1386
- josi: [['を'], ['で']],
1387
- pure: true,
1388
- fn: function(s: string, a: string) {
1389
- s = '' + s
1390
- a = '' + a
1391
- const i = s.indexOf(a)
1392
- if (i < 0) {
1393
- return [s]
1394
- }
1395
- return [s.substring(0, i), s.substring(i + a.length)]
1396
- }
1397
- },
1398
- '切取': { // @文字列Sから文字列Aまでの部分を抽出する。切り取った残りは特殊変数『対象』に代入される。(v1非互換) // @きりとる
1399
- type: 'func',
1400
- josi: [['から', 'の'], ['まで', 'を']],
1401
- pure: true,
1402
- fn: function(s: string, a: string, sys: any) {
1403
- s = String(s)
1404
- const i = s.indexOf(a)
1405
- if (i < 0) {
1406
- sys.__setSysVar('対象', '')
1407
- return s
1408
- }
1409
- sys.__setSysVar('対象', s.substring(i + a.length))
1410
- return s.substring(0, i)
1411
- }
1412
- },
1413
- '範囲切取': { // @文字列Sで文字列AからBまでの部分を抽出して返す。切り取った残りは特殊変数『対象』に代入される。(v1非互換) // @はんいきりとる
1414
- type: 'func',
1415
- josi: [['で', 'の'], ['から'], ['まで', 'を']],
1416
- pure: true,
1417
- fn: function(s: string, a: string, b: string, sys: any) {
1418
- s = String(s)
1419
- let mae = ''
1420
- let usiro = ''
1421
- const i = s.indexOf(a)
1422
- if (i < 0) {
1423
- sys.__setSysVar('対象', s)
1424
- return ''
1425
- }
1426
- mae = s.substring(0, i)
1427
- const subS = s.substring(i + a.length)
1428
- const j = subS.indexOf(b)
1429
- if (j < 0) {
1430
- sys.__setSysVar('対象', mae)
1431
- return subS
1432
- }
1433
- const result = subS.substring(0, j)
1434
- usiro = subS.substring(j + b.length)
1435
- sys.__setSysVar('対象', mae + usiro)
1436
- return result
1437
- }
1438
- },
1439
- '文字削除': { // @文字列SのA文字目からB文字分を削除して返す // @もじさくじょ
1440
- type: 'func',
1441
- josi: [['の'], ['から'], ['だけ', 'を', '']],
1442
- pure: true,
1443
- fn: function(s: string, a: number, b: number): string {
1444
- // サロゲートペアを考慮
1445
- const strArray = Array.from(s)
1446
- strArray.splice(a - 1, b)
1447
- return strArray.join('')
1448
- }
1449
- },
1450
- '文字始': { // @文字列SがAから始まるならば真を返す // @もじはじまる
1451
- type: 'func',
1452
- josi: [['が'], ['で', 'から']],
1453
- pure: true,
1454
- fn: function(s: string, a: string): boolean {
1455
- return s.startsWith(a)
1456
- }
1457
- },
1458
- '文字終': { // @文字列SがAで終わるならば真を返す // @もじおわる
1459
- type: 'func',
1460
- josi: [['が'], ['で']],
1461
- pure: true,
1462
- fn: function(s: string, a: string): boolean {
1463
- return s.endsWith(a)
1464
- }
1465
- },
1466
- '出現': { // @文字列(配列)SにAが出現する場合に真を返す // @しゅつげん
1467
- type: 'func',
1468
- josi: [['に','で'], ['が']],
1469
- pure: true,
1470
- fn: function(s: any, a: string): boolean {
1471
- if (typeof(s) === 'string') {
1472
- return s.includes(a)
1473
- }
1474
- if (s instanceof Array) {
1475
- return s.includes(a)
1476
- }
1477
- const ss = String(s)
1478
- return ss.includes(a)
1479
- }
1480
- },
1481
-
1482
- // @置換・トリム
1483
- '置換': { // @文字列Sのうち文字列AをBに全部置換して返す // @ちかん
1484
- type: 'func',
1485
- josi: [['の', 'で'], ['を', 'から'], ['に', 'へ']],
1486
- pure: true,
1487
- fn: function(s: string, a: string, b: string) {
1488
- return String(s).split(a).join(b)
1489
- }
1490
- },
1491
- '単置換': { // @文字列Sのうち、最初に出現するAだけをBに置換して返す // @たんちかん
1492
- type: 'func',
1493
- josi: [['の', 'で'], ['を'], ['に', 'へ']],
1494
- pure: true,
1495
- fn: function(s: string, a: string, b: string) {
1496
- // replaceは最初の一度だけ置換する
1497
- return String(s).replace(a, b)
1498
- }
1499
- },
1500
- 'トリム': { // @文字列Sの前後にある空白を削除する // @とりむ
1501
- type: 'func',
1502
- josi: [['の', 'を']],
1503
- pure: true,
1504
- fn: function(s: string): string {
1505
- return String(s).replace(/^\s+/, '').replace(/\s+$/, '')
1506
- }
1507
- },
1508
- '空白除去': { // @文字列Sの前後にある空白を削除する // @くうはくじょきょ
1509
- type: 'func',
1510
- josi: [['の', 'を']],
1511
- pure: true,
1512
- fn: function(s: string): string {
1513
- return String(s).replace(/^\s+/, '').replace(/\s+$/, '')
1514
- }
1515
- },
1516
- '右トリム': { // @文字列Sの末尾にある空白を削除する // @みぎとりむ
1517
- type: 'func',
1518
- josi: [['の', 'を']],
1519
- pure: true,
1520
- fn: function(s: string): string {
1521
- return String(s).replace(/\s+$/, '')
1522
- }
1523
- },
1524
- '左トリム': { // @文字列Sの先頭にある空白を削除する // @ひだりとりむ
1525
- type: 'func',
1526
- josi: [['の', 'を']],
1527
- pure: true,
1528
- fn: function(s: string): string {
1529
- return String(s).replace(/^\s+/, '')
1530
- }
1531
- },
1532
- '末尾空白除去': { // @文字列Sの末尾にある空白を削除する // @まつびくうはくじょきょ
1533
- type: 'func',
1534
- josi: [['の', 'を']],
1535
- pure: true,
1536
- fn: function(s: string): string {
1537
- return String(s).replace(/\s+$/, '')
1538
- }
1539
- },
1540
-
1541
- // @文字変換
1542
- '大文字変換': { // @アルファベットの文字列Sを大文字に変換 // @おおもじへんかん
1543
- type: 'func',
1544
- josi: [['の', 'を']],
1545
- pure: true,
1546
- fn: function(s: string): string {
1547
- return String(s).toUpperCase()
1548
- }
1549
- },
1550
- '小文字変換': { // @アルファベットの文字列Sを小文字に変換 // @こもじへんかん
1551
- type: 'func',
1552
- josi: [['の', 'を']],
1553
- pure: true,
1554
- fn: function(s: string): string {
1555
- return String(s).toLowerCase()
1556
- }
1557
- },
1558
- '平仮名変換': { // @文字列Sのカタカナをひらがなに変換 // @ひらがなへんかん
1559
- type: 'func',
1560
- josi: [['の', 'を']],
1561
- pure: true,
1562
- fn: function(s: string): string {
1563
- const kanaToHira = (str: string) => {
1564
- return String(str).replace(/[\u30a1-\u30f6]/g, function(m: string) {
1565
- const chr = m.charCodeAt(0) - 0x60
1566
- return String.fromCharCode(chr)
1567
- })
1568
- }
1569
- return kanaToHira('' + s)
1570
- }
1571
- },
1572
- 'カタカナ変換': { // @文字列Sのひらがなをカタカナに変換 // @かたかなへんかん
1573
- type: 'func',
1574
- josi: [['の', 'を']],
1575
- pure: true,
1576
- fn: function(s: string): string {
1577
- const hiraToKana = (str: string) => {
1578
- return String(str).replace(/[\u3041-\u3096]/g, function(m: string) {
1579
- const chr = m.charCodeAt(0) + 0x60
1580
- return String.fromCharCode(chr)
1581
- })
1582
- }
1583
- return hiraToKana('' + s)
1584
- }
1585
- },
1586
- '英数全角変換': { // @文字列Sの半角英数文字を全角に変換 // @えいすうぜんかくへんかん
1587
- type: 'func',
1588
- josi: [['の', 'を']],
1589
- pure: true,
1590
- fn: function(s: string): string {
1591
- return String(s).replace(/[A-Za-z0-9]/g, function(v: string) {
1592
- return String.fromCharCode(v.charCodeAt(0) + 0xFEE0)
1593
- })
1594
- }
1595
- },
1596
- '英数半角変換': { // @文字列Sの全角英数文字を半角に変換 // @えいすうはんかくへんかん
1597
- type: 'func',
1598
- josi: [['の', 'を']],
1599
- pure: true,
1600
- fn: function(s: string): string {
1601
- return String(s).replace(/[A-Za-z0-9]/g, function(v: string) {
1602
- return String.fromCharCode(v.charCodeAt(0) - 0xFEE0)
1603
- })
1604
- }
1605
- },
1606
- '英数記号全角変換': { // @文字列Sの半角英数記号文字を全角に変換 // @えいすうきごうぜんかくへんかん
1607
- type: 'func',
1608
- josi: [['の', 'を']],
1609
- pure: true,
1610
- fn: function(s: string): string {
1611
- return String(s).replace(/[\x20-\x7E]/g, function(v: string) {
1612
- if (v === ' ') { return ' ' } // 半角スペース(0x20)を全角スペース(U+3000)に
1613
- return String.fromCharCode(v.charCodeAt(0) + 0xFEE0)
1614
- })
1615
- }
1616
- },
1617
- '英数記号半角変換': { // @文字列Sの記号文字を半角に変換 // @えいすうきごうはんかくへんかん
1618
- type: 'func',
1619
- josi: [['の', 'を']],
1620
- pure: true,
1621
- fn: function(s: string): string {
1622
- return String(s).replace(/[\u3000\uFF00-\uFF5F]/g, function(v: string) {
1623
- if (v === ' ') { return ' ' } // 全角スペース(U+3000)を半角スペース(U+0020)
1624
- return String.fromCharCode(v.charCodeAt(0) - 0xFEE0)
1625
- })
1626
- }
1627
- },
1628
- 'カタカナ全角変換': { // @文字列Sの半角カタカナを全角に変換 // @かたかなぜんかくへんかん
1629
- type: 'func',
1630
- josi: [['の', 'を']],
1631
- pure: true,
1632
- fn: function(s: string, sys: any) {
1633
- // 半角カタカナ
1634
- const zen1 = sys.__getSysVar('全角カナ一覧')
1635
- const han1 = sys.__getSysVar('半角カナ一覧')
1636
- const zen2 = sys.__getSysVar('全角カナ濁音一覧')
1637
- const han2 = sys.__getSysVar('半角カナ濁音一覧')
1638
- let str = ''
1639
- let i = 0
1640
- while (i < s.length) {
1641
- // 濁点の変換
1642
- const c2 = s.substring(i, i + 2)
1643
- const n2 = han2.indexOf(c2)
1644
- if (n2 >= 0) {
1645
- str += zen2.charAt(n2 / 2)
1646
- i += 2
1647
- continue
1648
- }
1649
- // 濁点以外の変換
1650
- const c = s.charAt(i)
1651
- const n = han1.indexOf(c)
1652
- if (n >= 0) {
1653
- str += zen1.charAt(n)
1654
- i++
1655
- continue
1656
- }
1657
- str += c
1658
- i++
1659
- }
1660
- return str
1661
- }
1662
- },
1663
- 'カタカナ半角変換': { // @文字列Sの全角カタカナを半角に変換 // @かたかなはんかくへんかん
1664
- type: 'func',
1665
- josi: [['の', 'を']],
1666
- pure: true,
1667
- fn: function(s: string, sys: any) {
1668
- // 半角カタカナ
1669
- const zen1 = sys.__getSysVar('全角カナ一覧')
1670
- const han1 = sys.__getSysVar('半角カナ一覧')
1671
- const zen2 = sys.__getSysVar('全角カナ濁音一覧')
1672
- const han2 = sys.__getSysVar('半角カナ濁音一覧')
1673
- return s.split('').map((c) => {
1674
- const i = zen1.indexOf(c)
1675
- if (i >= 0) {
1676
- return han1.charAt(i)
1677
- }
1678
- const j = zen2.indexOf(c)
1679
- if (j >= 0) {
1680
- return han2.substring(j * 2, j * 2 + 2)
1681
- }
1682
- return c
1683
- }).join('')
1684
- }
1685
- },
1686
- '全角変換': { // @文字列Sの半角文字を全角に変換 // @ぜんかくへんかん
1687
- type: 'func',
1688
- josi: [['の', 'を']],
1689
- pure: false,
1690
- fn: function(s: string, sys: any) {
1691
- let result = s
1692
- result = sys.__exec('カタカナ全角変換', [result, sys])
1693
- result = sys.__exec('英数記号全角変換', [result, sys])
1694
- return result
1695
- }
1696
- },
1697
- '半角変換': { // @文字列Sの全角文字を半角に変換 // @はんかくへんかん
1698
- type: 'func',
1699
- josi: [['の', 'を']],
1700
- pure: false,
1701
- fn: function(s: string, sys: any) {
1702
- let result = s
1703
- result = sys.__exec('カタカナ半角変換', [result, sys])
1704
- result = sys.__exec('英数記号半角変換', [result, sys])
1705
- return result
1706
- }
1707
- },
1708
- '全角カナ一覧': { type: 'const', value: 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォャュョッ、。ー「」' }, // @ぜんかくかないちらん
1709
- '全角カナ濁音一覧': { type: 'const', value: 'ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ' }, // @ぜんかくかなだくおんいちらん
1710
- '半角カナ一覧': { type: 'const', value: 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォャュョッ、。ー「」゙゚' }, // @はんかくかないちらん
1711
- '半角カナ濁音一覧': { type: 'const', value: 'ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ' }, // @はんかくかなだくおんいちらん
1712
-
1713
- // @JSON
1714
- 'JSON変換': { // @オブジェクトVをJSON形式の文字列に変換して返す // @JSONへんかん
1715
- type: 'func',
1716
- josi: [['を', 'の', 'から']],
1717
- pure: true,
1718
- fn: function(v: any) {
1719
- return JSON.stringify(v)
1720
- }
1721
- },
1722
- 'JSON取得': { // @JSON文字列をパースして、なでしこのオブジェクトとして返す // @JSONしゅとく
1723
- type: 'func',
1724
- josi: [['を', 'の', 'から']],
1725
- pure: true,
1726
- fn: function(v: any) {
1727
- return JSON.parse(v)
1728
- }
1729
- },
1730
- 'JSONエンコード': { // @オブジェクトVをJSON形式に変換して返す(『JSON変換』と同じ) // @JSONえんこーど
1731
- type: 'func',
1732
- josi: [['を', 'の']],
1733
- pure: true,
1734
- fn: function(v: any) {
1735
- return JSON.stringify(v)
1736
- }
1737
- },
1738
- 'JSONエンコード整形': { // @オブジェクトVをJSON形式の文字列(整形済み)に変換して整形して返す // @JSONえんこーどせいけい
1739
- type: 'func',
1740
- josi: [['を', 'の']],
1741
- pure: true,
1742
- fn: function(v: any) {
1743
- return JSON.stringify(v, null, 2)
1744
- }
1745
- },
1746
- 'JSONデコード': { // @JSON文字列Sをオブジェクトにして返す(『JSON取得』と同じ) // @JSONでこーど
1747
- type: 'func',
1748
- josi: [['を', 'の', 'から']],
1749
- pure: true,
1750
- fn: function(s: string): string {
1751
- return JSON.parse(s)
1752
- }
1753
- },
1754
- 'JSON_E': { // @オブジェクトVをJSON形式の文字列に変換して返す(『JSON変換』と同じ) // @JSON_E
1755
- type: 'func',
1756
- josi: [['を', 'の']],
1757
- pure: true,
1758
- fn: function(v: any) {
1759
- return JSON.stringify(v)
1760
- }
1761
- },
1762
- 'JSON_ES': { // @オブジェクトVをJSON形式の文字列(整形済み)に変換して返す(『JSONエンコード整形』と同じ) // @JSON_ES
1763
- type: 'func',
1764
- josi: [['を', 'の']],
1765
- pure: true,
1766
- fn: function(v: any) {
1767
- return JSON.stringify(v, null, 2)
1768
- }
1769
- },
1770
- 'JSON_D': { // @JSON文字列Sをオブジェクトにして返す(『JSON取得』と同じ) // @JSON_D
1771
- type: 'func',
1772
- josi: [['を', 'の', 'から']],
1773
- pure: true,
1774
- fn: function(s: string): string {
1775
- return JSON.parse(s)
1776
- }
1777
- },
1778
-
1779
- // @正規表現
1780
- '正規表現マッチ': { // @文字列Aを正規表現パターンBでマッチして結果を返す(パターンBは「/pat/opt」の形式で指定。optにgの指定がなければ部分マッチが『抽出文字列』に入る) // @せいきひょうげんまっち
1781
- type: 'func',
1782
- josi: [['を', 'が'], ['で', 'に']],
1783
- pure: true,
1784
- fn: function(a: string, b: string, sys: any): string {
1785
- let re
1786
- const f = ('' + b).match(/^\/(.+)\/([a-zA-Z]*)$/)
1787
- // パターンがない場合
1788
- if (f === null) { re = new RegExp(b, 'g') } else { re = new RegExp(f[1], f[2]) }
1789
- const sa: any[] = sys.__getSysVar('抽出文字列')
1790
- sa.splice(0, sa.length) // clear
1791
- const m = String(a).match(re)
1792
- let result: any = m
1793
- if (re.global) {
1794
- // no groups
1795
- } else if (m) {
1796
- // has group?
1797
- if (m.length > 0) {
1798
- result = m[0]
1799
- for (let i = 1; i < m.length; i++) { sa[i - 1] = m[i] }
1800
- }
1801
- }
1802
- return result
1803
- }
1804
- },
1805
- '正規表現抽出': { // @文字列Sを正規表現パターンREで正規表現マッチし、すべてのキャプチャグループ( )を一次元配列として返す。抽出文字列には二次元配列を返す// @せいきひょうげんちゅうしゅつ
1806
- type: 'func',
1807
- josi: [['から','を'], ['で']],
1808
- pure: true,
1809
- fn: function(a: string, b: string, sys: any): any[] {
1810
- let pattern = '' + b
1811
- let flags = 'g'
1812
- const f = pattern.match(/^\/(.+)\/([a-zA-Z]*)$/)
1813
- if (f) {
1814
- pattern = f[1]
1815
- flags = f[2] || ''
1816
- }
1817
- if (!flags.includes('g')) flags += 'g'
1818
-
1819
- const re = new RegExp(pattern, flags)
1820
-
1821
- const sa: any[] = sys.__getSysVar('抽出文字列')
1822
- sa.splice(0, sa.length) // clear
1823
-
1824
- const result: any[] = [] // 一次元配列
1825
- const caps2d: any[] = [] // 二次元配列(sa に入れる)
1826
-
1827
- for (const m of String(a).matchAll(re)) {
1828
-
1829
- // ★ 名前付きキャプチャがある場合
1830
- if (m.groups && Object.keys(m.groups).length > 0) {
1831
- const row: Record<string, string> = {}
1832
-
1833
- for (const [key, val] of Object.entries(m.groups)) {
1834
- row[key] = val
1835
- result.push(val) // result は平坦化
1836
- }
1837
-
1838
- caps2d.push(row)
1839
- continue
1840
- }
1841
-
1842
- // ★ 通常キャプチャ(従来どおり)
1843
- let caps = [...m].slice(1)
1844
-
1845
- if (caps.length === 0) {
1846
- caps = [m[0]] //キャプチャがない場合
1847
- }
1848
-
1849
- caps2d.push(caps)
1850
- result.push(...caps)
1851
- }
1852
-
1853
- // マッチなし → 両方空のまま
1854
- if (caps2d.length === 0) {
1855
- return result
1856
- }
1857
-
1858
- // sa に二次元配列をコピー
1859
- for (const row of caps2d) {
1860
- sa.push(row)
1861
- }
1862
-
1863
- return result
1864
- }
1865
- },
1866
- '抽出文字列': { type: 'const', value: [] }, // @ちゅうしゅつもじれつ
1867
- '正規表現置換': { // @文字列Sの正規表現パターンAをBに置換して結果を返す(パターンAは/pat/optで指定) // @せいきひょうげんちかん
1868
- type: 'func',
1869
- josi: [['の'], ['を', 'から'], ['で', 'に', 'へ']],
1870
- pure: true,
1871
- fn: function(s: string, a: string, b: string): string {
1872
- let re
1873
- const f = a.match(/^\/(.+)\/([a-zA-Z]*)/)
1874
- if (f === null) { re = new RegExp(a, 'g') } else { re = new RegExp(f[1], f[2]) }
1875
-
1876
- return String(s).replace(re, b)
1877
- }
1878
- },
1879
- '正規表現区切': { // @文字列Sを正規表現パターンAで区切って配列で返す(パターンAは/pat/optで指定) // @せいきひょうげんくぎる
1880
- type: 'func',
1881
- josi: [['を'], ['で']],
1882
- pure: true,
1883
- fn: function(s: any, a: any) {
1884
- let re
1885
- const f = a.match(/^\/(.+)\/([a-zA-Z]*)/)
1886
- if (f === null) { re = new RegExp(a, 'g') } else { re = new RegExp(f[1], f[2]) }
1887
-
1888
- return String(s).split(re)
1889
- }
1890
- },
1891
-
1892
- // @指定形式
1893
- '通貨形式': { // @数値Vを三桁ごとにカンマで区切る // @つうかけいしき
1894
- type: 'func',
1895
- josi: [['を', 'の']],
1896
- pure: true,
1897
- fn: function(v: any) {
1898
- return String(v).replace(/(?<!\.\d*?)(\d)(?=(\d\d\d)+(?!\d))/g, '$1,')
1899
- }
1900
- },
1901
- 'ゼロ埋': { // @数値VをA桁の0で埋める // @ぜろうめ
1902
- type: 'func',
1903
- josi: [['を'], ['で']],
1904
- pure: true,
1905
- fn: function(v: any, a: any): string {
1906
- v = String(v)
1907
- let z = '0'
1908
- for (let i = 0; i < a; i++) { z += '0' }
1909
- a = parseInt(a)
1910
- if (a < v.length) { a = v.length }
1911
- const s = z + String(v)
1912
- return s.substring(s.length - a, s.length)
1913
- }
1914
- },
1915
- '空白埋': { // @文字列VをA桁の空白で埋める // @くうはくうめ
1916
- type: 'func',
1917
- josi: [['を'], ['で']],
1918
- pure: true,
1919
- fn: function(v: any, a: any): string {
1920
- v = String(v)
1921
- let z = ' '
1922
- for (let i = 0; i < a; i++) { z += ' ' }
1923
- a = parseInt(a)
1924
- if (a < v.length) { a = v.length }
1925
- const s = z + String(v)
1926
- return s.substring(s.length - a, s.length)
1927
- }
1928
- },
1929
-
1930
- // @文字種類
1931
- 'かなか判定': { // @文字列Sの1文字目がひらがなか判定 // @かなかはんてい
1932
- type: 'func',
1933
- josi: [['を', 'の', 'が']],
1934
- pure: true,
1935
- fn: function(s: any): boolean {
1936
- const c = String(s).charCodeAt(0)
1937
- return (c >= 0x3041 && c <= 0x309F)
1938
- }
1939
- },
1940
- 'カタカナ判定': { // @文字列Sの1文字目がカタカナか判定 // @かたかなかはんてい
1941
- type: 'func',
1942
- josi: [['を', 'の', 'が']],
1943
- pure: true,
1944
- fn: function(s: any): boolean {
1945
- const c = String(s).charCodeAt(0)
1946
- return (c >= 0x30A1 && c <= 0x30FA)
1947
- }
1948
- },
1949
- '数字判定': { // @文字列Sの1文字目が数字か判定 // @すうじかはんてい
1950
- type: 'func',
1951
- josi: [['を', 'が']],
1952
- pure: true,
1953
- fn: function(s: any): boolean {
1954
- const c = String(s).charAt(0)
1955
- return ((c >= '0' && c <= '9') || (c >= '0' && c <= '9'))
1956
- }
1957
- },
1958
- '数列判定': { // @文字列S全部が数字か判定 // @すうれつかはんてい
1959
- type: 'func',
1960
- josi: [['を', 'が']],
1961
- pure: true,
1962
- fn: function(s: any): boolean {
1963
- const checkerRE = /^[+\-+-]?([0-90-9]*)(([..][0-90-9]+)?|([..][0-90-9]+[eEeE][+\-+-]?[0-90-9]+)?)$/
1964
- if (s === '') { return false } // 空文字列はfalse
1965
- return String(s).match(checkerRE) !== null
1966
- }
1967
- },
1968
-
1969
- // @配列操作
1970
- '配列結合': { // @配列Aを文字列Sでつなげて文字列で返す // @はいれつけつごう
1971
- type: 'func',
1972
- josi: [['を'], ['で']],
1973
- pure: true,
1974
- fn: function(a: any, s: string): string {
1975
- // 配列ならOK
1976
- if (a instanceof Array) { return a.join('' + s) }
1977
-
1978
- const a2 = String(a).split('\n') // 配列でなければ無理矢理改行で区切ってみる
1979
- return a2.join('' + s)
1980
- }
1981
- },
1982
- '配列只結合': { // @配列Aの要素をただ結合して文字列で返す。(「」で配列結合と同じ) // @はいれつただけつごう
1983
- type: 'func',
1984
- josi: [['を']],
1985
- pure: true,
1986
- fn: function(a: any): string {
1987
- if (a instanceof Array) { return a.join('') }
1988
- const a2 = String(a).split('\n') // 配列でなければ無理矢理改行で区切ってみる
1989
- return a2.join('')
1990
- }
1991
- },
1992
- '配列検索': { // @配列Aから文字列Sを探してインデックス番号(0起点)を返す。見つからなければ-1を返す。 // @はいれつけんさく
1993
- type: 'func',
1994
- josi: [['の', 'から'], ['を']],
1995
- pure: true,
1996
- fn: function(a: any, s: any) {
1997
- if (a instanceof Array) { return a.indexOf(s) }// 配列ならOK
1998
-
1999
- return -1
2000
- }
2001
- },
2002
- '配列要素数': { // @配列Aの要素数を返す // @はいれつようそすう
2003
- type: 'func',
2004
- josi: [['の']],
2005
- pure: true,
2006
- fn: function(a: any) {
2007
- if (a instanceof Array) { return a.length }// 配列ならOK
2008
- if (a instanceof Object) { return Object.keys(a).length } // オブジェクト
2009
- if (typeof a === 'string') { return String(a).length } // 文字列
2010
- return 1
2011
- }
2012
- },
2013
- '要素数': { // @Aの要素数を返す。Aには配列/辞書型/文字列を指定する。 // @ようそすう
2014
- type: 'func',
2015
- josi: [['の']],
2016
- pure: true,
2017
- fn: function(a: any, sys: any) {
2018
- return sys.__exec('配列要素数', [a])
2019
- }
2020
- },
2021
- 'LEN': { // @Aの要素数を返す。Aには配列/辞書型/文字列を指定する。 // @LEN
2022
- type: 'func',
2023
- josi: [['の']],
2024
- pure: true,
2025
- fn: function(a: any, sys: any) {
2026
- return sys.__exec('配列要素数', [a])
2027
- }
2028
- },
2029
- '配列挿入': { // @配列AのI番目(0起点)に要素Sを追加して返す(v1非互換) // @はいれつそうにゅう
2030
- type: 'func',
2031
- josi: [['の'], ['に', 'へ'], ['を']],
2032
- pure: true,
2033
- fn: function(a: any, i: any, s: any) {
2034
- if (a instanceof Array) { return a.splice(i, 0, s) } // 配列ならOK
2035
-
2036
- throw new Error('『配列挿入』で配列以外の要素への挿入。')
2037
- }
2038
- },
2039
- '配列一括挿入': { // @配列AのI番目(0起点)に配列bを追加して返す(v1非互換) // @はいれついっかつそうにゅう
2040
- type: 'func',
2041
- josi: [['の'], ['に', 'へ'], ['を']],
2042
- pure: true,
2043
- fn: function(a: any, i: number, b: any) {
2044
- if (a instanceof Array && b instanceof Array) { // 配列ならOK
2045
- for (let j = 0; j < b.length; j++) { a.splice(i + j, 0, b[j]) }
2046
-
2047
- return a
2048
- }
2049
- throw new Error('『配列一括挿入』で配列以外の要素への挿入。')
2050
- }
2051
- },
2052
- '配列ソート': { // @配列Aをソートして返す(A自体を変更) // @はいれつそーと
2053
- type: 'func',
2054
- josi: [['の', 'を']],
2055
- pure: true,
2056
- fn: function(a: any) {
2057
- if (a instanceof Array) { return a.sort() } // 配列ならOK
2058
-
2059
- throw new Error('『配列ソート』で配列以外が指定されました。')
2060
- }
2061
- },
2062
- '配列数値変換': { // @配列Aの各要素を数値に変換して返す(変数A自体を変更) // @はいれつすうちへんかん
2063
- type: 'func',
2064
- josi: [['の', 'を']],
2065
- pure: true,
2066
- fn: function(a: any) {
2067
- // 配列ならOK
2068
- if (a instanceof Array) {
2069
- for (let i = 0; i < a.length; i++) {
2070
- a[i] = parseFloat(a[i])
2071
- }
2072
- return a
2073
- }
2074
- throw new Error('『配列数値変換』で配列以外が指定されました。')
2075
- }
2076
- },
2077
- '配列数値ソート': { // @配列Aをソートして返す(A自体を変更) // @はいれつすうちそーと
2078
- type: 'func',
2079
- josi: [['の', 'を']],
2080
- pure: true,
2081
- fn: function(a: any) {
2082
- // 配列ならOK
2083
- if (a instanceof Array) {
2084
- return a.sort((a, b) => {
2085
- return parseFloat(a) - parseFloat(b)
2086
- })
2087
- }
2088
-
2089
- throw new Error('『配列数値ソート』で配列以外が指定されました。')
2090
- }
2091
- },
2092
- '配列カスタムソート': { // @関数Fで配列Aをソートして返す(引数A自体を変更) // @はいれつかすたむそーと
2093
- type: 'func',
2094
- josi: [['で'], ['の', 'を']],
2095
- pure: false,
2096
- fn: function(f: any, a: any, sys: any) {
2097
- let ufunc = f
2098
- if (typeof f === 'string') {
2099
- ufunc = sys.__findFunc(f, '配列カスタムソート')
2100
- }
2101
- if (a instanceof Array) {
2102
- return a.sort(ufunc)
2103
- }
2104
- throw new Error('『配列カスタムソート』で配列以外が指定されました。')
2105
- }
2106
- },
2107
- '配列逆順': { // @配列Aを逆にして返す。Aを書き換える(A自体を変更)。 // @はいれつぎゃくじゅん
2108
- type: 'func',
2109
- josi: [['の', 'を']],
2110
- pure: true,
2111
- fn: function(a: any) {
2112
- if (a instanceof Array) { return a.reverse() } // 配列ならOK
2113
- throw new Error('『配列ソート』で配列以外が指定されました。')
2114
- }
2115
- },
2116
- '配列シャッフル': { // @配列Aをシャッフルして返す。Aを書き換える // @はいれつしゃっふる
2117
- type: 'func',
2118
- josi: [['の', 'を']],
2119
- pure: true,
2120
- fn: function(a: any) {
2121
- if (a instanceof Array) { // 配列ならOK
2122
- for (let i = a.length - 1; i > 0; i--) {
2123
- const r = Math.floor(Math.random() * (i + 1))
2124
- const tmp = a[i]
2125
- a[i] = a[r]
2126
- a[r] = tmp
2127
- }
2128
- return a
2129
- }
2130
- throw new Error('『配列シャッフル』で配列以外が指定されました。')
2131
- }
2132
- },
2133
- '配列削除': { // @配列AのI番目(0起点)の要素を削除して返す。Aの内容を書き換える。辞書型変数ならキーIを削除する。 // @はいれつさくじょ
2134
- type: 'func',
2135
- josi: [['の', 'から'], ['を']],
2136
- pure: true,
2137
- fn: function(a: any, i: any, sys: any) {
2138
- return sys.__exec('配列切取', [a, i, sys])
2139
- }
2140
- },
2141
- '配列切取': { // @配列AのI番目(0起点)の要素を切り取って返す。Aの内容を書き換える。引数Iには範囲オブジェクトを指定できる。その場合戻り値は配列型となる。辞書型変数ならキーIを削除する。 // @はいれつきりとる
2142
- type: 'func',
2143
- josi: [['の', 'から'], ['を']],
2144
- pure: true,
2145
- fn: function(a: any, i: any) {
2146
- // 配列変数のとき
2147
- if (a instanceof Array) {
2148
- if (typeof i === 'number') {
2149
- const b = a.splice(i, 1)
2150
- if (b instanceof Array) { return b[0] } // 切り取った戻り値は必ずArrayになるので。
2151
- }
2152
- if (typeof i === 'object' && typeof i['先頭'] === 'number') {
2153
- const idx = i['先頭']
2154
- const cnt = i['末尾'] - i['先頭'] + 1
2155
- return a.splice(idx, cnt)
2156
- }
2157
- return null
2158
- }
2159
- // 辞書型変数のとき
2160
- if (a instanceof Object && typeof (i) === 'string') { // 辞書型変数も許容
2161
- if (a[i]) {
2162
- const old = a[i]
2163
- delete a[i]
2164
- return old
2165
- }
2166
- return undefined
2167
- }
2168
- throw new Error('『配列切取』で配列以外を指定。')
2169
- }
2170
- },
2171
- '配列取出': { // @配列AのI番目(0起点)からCNT個の要素を取り出して返す。Aの内容を書き換える // @はいれつとりだし
2172
- type: 'func',
2173
- josi: [['の'], ['から'], ['を']],
2174
- pure: true,
2175
- fn: function(a: any, i: any, cnt: any) {
2176
- if (a instanceof Array) { return a.splice(i, cnt) }
2177
- throw new Error('『配列取出』で配列以外を指定。')
2178
- }
2179
- },
2180
- '配列ポップ': { // @配列Aの末尾を取り出して返す。Aの内容を書き換える。 // @はいれつぽっぷ
2181
- type: 'func',
2182
- josi: [['の', 'から']],
2183
- pure: true,
2184
- fn: function(a: any) {
2185
- if (a instanceof Array) { return a.pop() }
2186
- throw new Error('『配列ポップ』で配列以外の処理。')
2187
- }
2188
- },
2189
- '配列プッシュ': { // @配列Aの末尾にNを追加。Aの内容を書き換える。(『配列追加』と同じ) // @はいれつぷっしゅ
2190
- type: 'func',
2191
- josi: [['に', 'へ'], ['を']],
2192
- pure: true,
2193
- fn: function(a: any, b: any, sys: any) {
2194
- return sys.__exec('配列追加', [a, b, sys])
2195
- }
2196
- },
2197
- '配列追加': { // @配列Aの末尾にBを追加して返す。Aの内容を書き換える。 // @はいれつついか
2198
- type: 'func',
2199
- josi: [['に', 'へ'], ['を']],
2200
- pure: true,
2201
- fn: function(a: any, b: any) {
2202
- if (a instanceof Array) { // 配列ならOK
2203
- a.push(b)
2204
- return a
2205
- }
2206
- throw new Error('『配列追加』で配列以外の処理。')
2207
- }
2208
- },
2209
- '配列複製': { // @配列Aを複製して返す。 // @はいれつふくせい
2210
- type: 'func',
2211
- josi: [['を']],
2212
- pure: true,
2213
- fn: function(a: any) {
2214
- return JSON.parse(JSON.stringify(a))
2215
- }
2216
- },
2217
- '配列範囲コピー': { // @配列Aの範囲I(数値化範囲オブジェクト)を複製して返す。 // @はいれつはんいこぴー
2218
- type: 'func',
2219
- josi: [['の', 'から'], ['を']],
2220
- pure: true,
2221
- fn: function(a: any, i: any) {
2222
- if (!Array.isArray(a)) {
2223
- throw new Error('『配列範囲コピー』で配列以外の値が指定されました。')
2224
- }
2225
- if (typeof i === 'number') {
2226
- if (typeof a[i] === 'object') {
2227
- return JSON.parse(JSON.stringify(a[i]))
2228
- }
2229
- return a[i]
2230
- }
2231
- // 範囲オブジェクトのとき
2232
- if (typeof i === 'object' && typeof i['先頭'] === 'number') {
2233
- const start = i['先頭']
2234
- const last = Number(i['末尾']) + 1
2235
- return JSON.parse(JSON.stringify(a.slice(start, last)))
2236
- }
2237
- return undefined
2238
- }
2239
- },
2240
- '参照': { // @値A(配列/文字列/辞書型)の範囲I(キーまたは範囲オブジェクト)を参照して(コピーせず)返す // @さんしょう
2241
- type: 'func',
2242
- josi: [['から', 'の'], ['を']],
2243
- pure: true,
2244
- fn: function(a: any, i: any, sys: any) {
2245
- // 文字列のとき
2246
- if (typeof a === 'string') {
2247
- if (typeof i === 'number') {
2248
- return a.charAt(i)
2249
- }
2250
- // 範囲オブジェクトのとき
2251
- if (typeof i === 'object' && typeof i['先頭'] === 'number') {
2252
- const start = i['先頭']
2253
- const last = Number(i['末尾']) + 1
2254
- return a.substring(start, last)
2255
- }
2256
- throw new Error(`『参照』で文字列型の範囲指定(${JSON.stringify(i)})が不正です。`)
2257
- }
2258
- // 配列型のとき
2259
- if (Array.isArray(a)) {
2260
- if (typeof i === 'number') {
2261
- return a[i]
2262
- }
2263
- // 範囲オブジェクトのとき
2264
- if (typeof i === 'object' && typeof i['先頭'] === 'number') {
2265
- const start = i['先頭']
2266
- const last = Number(i['末尾']) + 1
2267
- return a.slice(start, last)
2268
- }
2269
- }
2270
- // 辞書型のとき
2271
- if (typeof a === 'object') {
2272
- return a[i]
2273
- }
2274
- throw new Error('『参照』で文字列/配列/辞書型以外の値が指定されました。')
2275
- }
2276
- },
2277
- '配列参照': { // @値A(配列/文字列/辞書型)の範囲I(キーまたは範囲オブジェクト)を参照して(コピーせず)返す(『参照』と同じ) // @はいれつはんいさんしょう
2278
- type: 'func',
2279
- josi: [['の', 'から'], ['を']],
2280
- pure: true,
2281
- fn: function(a: any, i: any, sys: any) {
2282
- return sys.__exec('参照', [a, i, sys])
2283
- }
2284
- },
2285
- '配列足': { // @配列Aに配列Bを足し合わせて返す。 // @はいれつたす
2286
- type: 'func',
2287
- josi: [['に', 'へ', 'と'], ['を']],
2288
- pure: true,
2289
- fn: function(a: any, b: any) {
2290
- if (a instanceof Array) {
2291
- return a.concat(b)
2292
- }
2293
- return JSON.parse(JSON.stringify(a))
2294
- }
2295
- },
2296
- '配列最大値': { // @配列Aの値の最大値を調べて返す。 // @はいれつさいだいち
2297
- type: 'func',
2298
- josi: [['の']],
2299
- pure: true,
2300
- fn: function(a: any) {
2301
- return a.reduce((x: any, y: any) => Math.max(x, y))
2302
- }
2303
- },
2304
- '配列最小値': { // @配列Aの値の最小値を調べて返す。 // @はいれつさいしょうち
2305
- type: 'func',
2306
- josi: [['の']],
2307
- pure: true,
2308
- fn: function(a: any) {
2309
- return a.reduce((x: any, y: any) => Math.min(x, y))
2310
- }
2311
- },
2312
- '配列合計': { // @配列Aの値を全て足して返す。配列の各要素を数値に変換して計算する。数値に変換できない文字列は0になる。 // @はいれつごうけい
2313
- type: 'func',
2314
- josi: [['の']],
2315
- pure: true,
2316
- fn: function(a: any) {
2317
- if (a instanceof Array) {
2318
- let v = 0
2319
- a.forEach((n) => {
2320
- const nn = parseFloat(n)
2321
- if (isNaN(nn)) { return }
2322
- v += nn
2323
- })
2324
- return v
2325
- }
2326
- throw new Error('『配列合計』で配列変数以外の値が指定されました。')
2327
- }
2328
- },
2329
- '配列入替': { // @配列Aの(0から数えて)I番目とJ番目の要素を入れ替えて返す。Aの内容を書き換える。// @はいれついれかえ
2330
- type: 'func',
2331
- josi: [['の'], ['と'], ['を']],
2332
- pure: true,
2333
- fn: function(a: any, i: number, j: number) {
2334
- if (!(a instanceof Array)) {
2335
- throw new Error('『配列入替』の第1引数には配列を指定してください。')
2336
- }
2337
- const tmp = a[i]
2338
- a[i] = a[j]
2339
- a[j] = tmp
2340
- return a
2341
- }
2342
- },
2343
- '配列連番作成': { // @AからBまでの連番配列を生成して返す。 // @はいれつれんばんさくせい
2344
- type: 'func',
2345
- josi: [['から'], ['までの', 'まで', 'の']],
2346
- pure: true,
2347
- fn: function(a: number, b: number) {
2348
- const result: number[] = []
2349
- for (let i = a; i <= b; i++) {
2350
- result.push(i)
2351
- }
2352
- return result
2353
- }
2354
- },
2355
- '配列要素作成': { // @値AをB個持つ配列を生成して返す。引数Bに配列を指定すると二次元以上の配列を生成する。// @はいれつようそさくせい
2356
- type: 'func',
2357
- josi: [['を'], ['だけ', 'で']],
2358
- pure: true,
2359
- fn: function(a: any, b: number | number[]) {
2360
- // value が配列やオブジェクトでも深くコピーするヘルパー
2361
- const cloneValue = (v: any): any => {
2362
- if (Array.isArray(v)) {
2363
- return (v).map(item => cloneValue(item)) as any
2364
- }
2365
- if (v instanceof Date) {
2366
- return new Date(v.getTime())
2367
- }
2368
- if (typeof v === 'object' && v !== null) {
2369
- return JSON.parse(JSON.stringify(v))
2370
- }
2371
- return v
2372
- }
2373
- // 再帰的に配列を生成する関数
2374
- const full = function(value: any, shape: number | number[]): any {
2375
- // 1次元:shape が数値
2376
- if (!Array.isArray(shape)) {
2377
- return Array.from({ length: shape }, () => cloneValue(value))
2378
- }
2379
- // 1次元:shape が数値
2380
- if (Array.isArray(shape) && shape.length === 1) {
2381
- return Array.from({ length: shape[0] }, () => cloneValue(value))
2382
- }
2383
- // 多次元:shape が配列
2384
- const [first, ...rest] = shape
2385
- return Array.from(
2386
- { length: first },
2387
- () => full(cloneValue(value), rest)
2388
- )
2389
- }
2390
- return full(a, b)
2391
- }
2392
- },
2393
- '配列関数適用': { // @引数を1つ持つ関数Fを、配列Aの全要素に適用した、新しい配列を返す。 // @はいれつかんすうてきよう
2394
- type: 'func',
2395
- josi: [['を'], ['へ', 'に']],
2396
- pure: true,
2397
- fn: function(f: any, a: any, sys: any) {
2398
- let ufunc: any = f
2399
- if (typeof f === 'string') { ufunc = sys.__findFunc(f, '配列関数適用') }
2400
- const result: any = []
2401
- for (const e of a) {
2402
- result.push(ufunc(e))
2403
- }
2404
- return result
2405
- }
2406
- },
2407
- '配列マップ': { // @引数を1つ持つ関数Fを、配列Aの全要素に適用した、新しい配列を返す。(『配列関数適用』と同じ) // @はいれつまっぷ
2408
- type: 'func',
2409
- josi: [['を'], ['へ', 'に']],
2410
- pure: true,
2411
- fn: function(f: any, a: any, sys: any) {
2412
- return sys.__exec('配列関数適用', [f, a, sys])
2413
- }
2414
- },
2415
- '配列フィルタ': { // @引数を1つ持ち真偽を返す関数Fを利用して、配列Aの要素をフィルタして、新しい配列として返す。 // @はいれつふぃるた
2416
- type: 'func',
2417
- josi: [['で', 'の'], ['を', 'について']],
2418
- pure: true,
2419
- fn: function(f: any, a: any, sys: any) {
2420
- let ufunc: any = f
2421
- if (typeof f === 'string') { ufunc = sys.__findFunc(f, '配列フィルタ') }
2422
- const result: any = []
2423
- for (const e of a) {
2424
- if (ufunc(e)) { result.push(e) }
2425
- }
2426
- return result
2427
- }
2428
- },
2429
- // @二次元配列処理
2430
- '表ソート': { // @二次元配列AでB列目(0起点)(あるいはキー名)をキーに文字列順にソートする。Aの内容を書き換える。 // @ひょうそーと
2431
- type: 'func',
2432
- josi: [['の'], ['を']],
2433
- pure: true,
2434
- fn: function(a: any, no: any) {
2435
- if (!(a instanceof Array)) {
2436
- throw new Error('『表ソート』には配列を指定する必要があります。')
2437
- }
2438
- a.sort((n, m) => {
2439
- const ns = n[no]
2440
- const ms = m[no]
2441
-
2442
- if (ns === ms) {
2443
- return 0
2444
- } else if (ns < ms) {
2445
- return -1
2446
- } else {
2447
- return 1
2448
- }
2449
- })
2450
- return a
2451
- }
2452
- },
2453
- '表数値ソート': { // @二次元配列AでB列目(0起点)(あるいはキー名)をキーに数値順にソートする。Aの内容を書き換える。 // @ひょうすうちそーと
2454
- type: 'func',
2455
- josi: [['の'], ['を']],
2456
- pure: true,
2457
- fn: function(a: any, no: number) {
2458
- if (!(a instanceof Array)) {
2459
- throw new Error('『表数値ソート』には配列を指定する必要があります。')
2460
- }
2461
- a.sort((n, m) => {
2462
- const ns = n[no]
2463
- const ms = m[no]
2464
- return ns - ms
2465
- })
2466
- return a
2467
- }
2468
- },
2469
- '表ピックアップ': { // @配列Aの列番号B(0起点)(あるいはキー名)で検索文字列Sを含む行を返す // @ひょうぴっくあっぷ
2470
- type: 'func',
2471
- josi: [['の'], ['から'], ['を', 'で']],
2472
- pure: true,
2473
- fn: function(a: any, no: number, s: any) {
2474
- if (!(a instanceof Array)) { throw new Error('『表ピックアップ』には配列を指定する必要があります。') }
2475
- return a.filter((row) => String(row[no]).indexOf(s) >= 0)
2476
- }
2477
- },
2478
- '表完全一致ピックアップ': { // @配列Aの列番号B(0起点)(あるいはキー名)で検索文字列Sと一致する行を返す // @ひょうかんぜんいっちぴっくあっぷ
2479
- type: 'func',
2480
- josi: [['の'], ['から'], ['を', 'で']],
2481
- pure: true,
2482
- fn: function(a: any, no: number, s: any) {
2483
- if (!(a instanceof Array)) { throw new Error('『表完全ピックアップ』には配列を指定する必要があります。') }
2484
- return a.filter((row) => row[no] === s)
2485
- }
2486
- },
2487
- '表検索': { // @二次元配列AでCOL列目(0起点)からキーSを含む行をROW行目から検索して何行目にあるか返す。見つからなければ-1を返す。 // @ひょうけんさく
2488
- type: 'func',
2489
- josi: [['の'], ['で', 'に'], ['から'], ['を']],
2490
- pure: true,
2491
- fn: function(a: any, col: number, row: number, s: any) {
2492
- if (!(a instanceof Array)) { throw new Error('『表検索』には配列を指定する必要があります。') }
2493
- for (let i = row; i < a.length; i++) {
2494
- if (a[i][col] === s) { return i }
2495
- }
2496
- return -1
2497
- }
2498
- },
2499
- '表列数': { // @二次元配列Aの列数を調べて返す。 // @ひょうれつすう
2500
- type: 'func',
2501
- josi: [['の']],
2502
- pure: true,
2503
- fn: function(a: any) {
2504
- if (!(a instanceof Array)) { throw new Error('『表列数』には配列を指定する必要があります。') }
2505
- let cols = 1
2506
- for (let i = 0; i < a.length; i++) {
2507
- if (a[i].length > cols) { cols = a[i].length }
2508
- }
2509
- return cols
2510
- }
2511
- },
2512
- '表行数': { // @二次元配列Aの行数を調べて返す。 // @ひょうぎょうすう
2513
- type: 'func',
2514
- josi: [['の']],
2515
- pure: true,
2516
- fn: function(a: any) {
2517
- if (!(a instanceof Array)) { throw new Error('『表行数』には配列を指定する必要があります。') }
2518
- return a.length
2519
- }
2520
- },
2521
- '表行列交換': { // @二次元配列Aの行と列を交換して返す。 // @ひょうぎょうれつこうかん
2522
- type: 'func',
2523
- josi: [['の', 'を']],
2524
- pure: true,
2525
- fn: function(a: any, sys: any) {
2526
- if (!(a instanceof Array)) { throw new Error('『表行列交換』には配列を指定する必要があります。') }
2527
- const cols = sys.__exec('表列数', [a])
2528
- const rows = a.length
2529
- const res = []
2530
- for (let r = 0; r < cols; r++) {
2531
- const row: any[] = []
2532
- res.push(row)
2533
- for (let c = 0; c < rows; c++) {
2534
- row[c] = (a[c][r] !== undefined) ? a[c][r] : ''
2535
- }
2536
- }
2537
- return res
2538
- }
2539
- },
2540
- '表右回転': { // @二次元配列Aを90度回転して返す。 // @ひょうみぎかいてん
2541
- type: 'func',
2542
- josi: [['の', 'を']],
2543
- pure: true,
2544
- fn: function(a: any, sys: any) {
2545
- if (!(a instanceof Array)) { throw new Error('『表右回転』には配列を指定する必要があります。') }
2546
- const cols = sys.__exec('表列数', [a])
2547
- const rows = a.length
2548
- const res = []
2549
- for (let r = 0; r < cols; r++) {
2550
- const row: any[] = []
2551
- res.push(row)
2552
- for (let c = 0; c < rows; c++) {
2553
- row[c] = a[rows - c - 1][r]
2554
- }
2555
- }
2556
- return res
2557
- }
2558
- },
2559
- '表重複削除': { // @二次元配列AのI列目にある重複項目を削除して返す。 // @ひょうじゅうふくさくじょ
2560
- type: 'func',
2561
- josi: [['の'], ['を', 'で']],
2562
- pure: true,
2563
- fn: function(a: any, i: any) {
2564
- if (!(a instanceof Array)) { throw new Error('『表重複削除』には配列を指定する必要があります。') }
2565
- const res: any[] = []
2566
- const keys:{[key: string]: boolean} = {}
2567
- for (let n = 0; n < a.length; n++) {
2568
- const k = a[n][i]
2569
- if (undefined === keys[k]) {
2570
- keys[k] = true
2571
- res.push(a[n])
2572
- }
2573
- }
2574
- return res
2575
- }
2576
- },
2577
- '表列取得': { // @二次元配列AのI列目を返す。 // @ひょうれつしゅとく
2578
- type: 'func',
2579
- josi: [['の'], ['を']],
2580
- pure: true,
2581
- fn: function(a: any, i: number) {
2582
- if (!(a instanceof Array)) { throw new Error('『表列取得』には配列を指定する必要があります。') }
2583
- const res = a.map(row => row[i])
2584
- return res
2585
- }
2586
- },
2587
- '表列挿入': { // @二次元配列Aの(0から数えて)I列目に配列Sを挿入して返す // @ひょうれつそうにゅう
2588
- type: 'func',
2589
- josi: [['の'], ['に', 'へ'], ['を']],
2590
- pure: true,
2591
- fn: function(a: any, i: any, s: any) {
2592
- if (!(a instanceof Array)) { throw new Error('『表列挿入』には配列を指定する必要があります。') }
2593
- const res: any[] = []
2594
- a.forEach((row, idx) => {
2595
- let nr: any[] = []
2596
- if (i > 0) { nr = nr.concat(row.slice(0, i)) }
2597
- nr.push(s[idx])
2598
- nr = nr.concat(row.slice(i))
2599
- res.push(nr)
2600
- })
2601
- return res
2602
- }
2603
- },
2604
- '表列削除': { // @二次元配列Aの(0から数えて)I列目削除して返す // @ひょうれつそうにゅう
2605
- type: 'func',
2606
- josi: [['の'], ['を']],
2607
- pure: true,
2608
- fn: function(a: any, i: any) {
2609
- if (!(a instanceof Array)) { throw new Error('『表列削除』には配列を指定する必要があります。') }
2610
- const res: any[] = []
2611
- a.forEach((row) => {
2612
- const nr = row.slice(0)
2613
- nr.splice(i, 1)
2614
- res.push(nr)
2615
- })
2616
- return res
2617
- }
2618
- },
2619
- '表列合計': { // @二次元配列Aの(0から数えて)I列目を合計して返す。 // @ひょうれつごうけい
2620
- type: 'func',
2621
- josi: [['の'], ['を', 'で']],
2622
- pure: true,
2623
- fn: function(a: any, i: any) {
2624
- if (!(a instanceof Array)) { throw new Error('『表列合計』には配列を指定する必要があります。') }
2625
- let sum = 0
2626
- a.forEach((row) => { sum += row[i] })
2627
- return sum
2628
- }
2629
- },
2630
- '表曖昧検索': { // @二次元配列AのROW行目からCOL列目(0起点)で正規表現Sにマッチする行を検索して何行目にあるか返す。見つからなければ-1を返す。(v1非互換) // @ひょうあいまいけんさく
2631
- type: 'func',
2632
- josi: [['の'], ['から'], ['で'], ['を']],
2633
- pure: true,
2634
- fn: function(a: any, row: any, col: any, s: any) {
2635
- if (!(a instanceof Array)) { throw new Error('『表曖昧検索』には配列を指定する必要があります。') }
2636
- const re = new RegExp(s)
2637
- for (let i = row; i < a.length; i++) {
2638
- const line = a[i]
2639
- if (re.test(line[col])) { return i }
2640
- }
2641
- return -1
2642
- }
2643
- },
2644
- '表正規表現ピックアップ': { // @二次元配列AでI列目(0起点)から正規表現パターンSにマッチする行をピックアップして返す。 // @ひょうせいきひょうげんぴっくあっぷ
2645
- type: 'func',
2646
- josi: [['の', 'で'], ['から'], ['を']],
2647
- pure: true,
2648
- fn: function(a: any, col: any, s: any) {
2649
- if (!(a instanceof Array)) { throw new Error('『表正規表現ピックアップ』には配列を指定する必要があります。') }
2650
- const re = new RegExp(s)
2651
- const res = []
2652
- for (let i = 0; i < a.length; i++) {
2653
- const row = a[i]
2654
- if (re.test(row[col])) { res.push(row.slice(0)) }
2655
- }
2656
- return res
2657
- }
2658
- },
2659
- // @辞書型変数の操作
2660
- '辞書キー列挙': { // @辞書型変数Aのキーの一覧を配列で返す。 // @じしょきーれっきょ
2661
- type: 'func',
2662
- josi: [['の']],
2663
- pure: true,
2664
- fn: function(a: any) {
2665
- const keys = []
2666
- if (a instanceof Object) { // オブジェクトのキーを返す
2667
- for (const key in a) { keys.push(key) }
2668
- return keys
2669
- }
2670
- if (a instanceof Array) { // 配列なら数字を返す
2671
- for (let i = 0; i < a.length; i++) { keys.push(i) }
2672
- return keys
2673
- }
2674
- throw new Error('『辞書キー列挙』でハッシュ以外が与えられました。')
2675
- }
2676
- },
2677
- '辞書キー削除': { // @辞書型変数AからキーKEYを削除して返す(A自体を変更する)。 // @じしょきーさくじょ
2678
- type: 'func',
2679
- josi: [['から', 'の'], ['を']],
2680
- pure: true,
2681
- fn: function(a: any, key: any) {
2682
- if (a instanceof Object) { // オブジェクトのキーを返す
2683
- if (key in a) { delete a[key] }
2684
- return a
2685
- }
2686
- throw new Error('『辞書キー削除』でハッシュ以外が与えられました。')
2687
- }
2688
- },
2689
- '辞書キー存在': { // @辞書型変数AのキーKEYが存在するか確認 // @じしょきーそんざい
2690
- type: 'func',
2691
- josi: [['の', 'に'], ['が']],
2692
- pure: true,
2693
- fn: function(a: any, key: any) {
2694
- return key in a
2695
- }
2696
- },
2697
- // @ハッシュ
2698
- 'ハッシュキー列挙': { // @ハッシュAのキー一覧を配列で返す。 // @はっしゅきーれっきょ
2699
- type: 'func',
2700
- josi: [['の']],
2701
- pure: true,
2702
- fn: function(a: any, sys: any) {
2703
- return sys.__exec('辞書キー列挙', [a, sys])
2704
- }
2705
- },
2706
- 'ハッシュ内容列挙': { // @ハッシュAの内容一覧を配列で返す。 // @はっしゅないようれっきょ
2707
- type: 'func',
2708
- josi: [['の']],
2709
- pure: true,
2710
- fn: function(a: any) {
2711
- const body = []
2712
- if (a instanceof Object) { // オブジェクトのキーを返す
2713
- for (const key in a) { body.push(a[key]) }
2714
- return body
2715
- }
2716
- throw new Error('『ハッシュ内容列挙』でハッシュ以外が与えられました。')
2717
- }
2718
- },
2719
- 'ハッシュキー削除': { // @ハッシュAからキーKEYを削除して返す。 // @はっしゅきーさくじょ
2720
- type: 'func',
2721
- josi: [['から', 'の'], ['を']],
2722
- pure: true,
2723
- fn: function(a: any, key: any, sys: any) {
2724
- return sys.__exec('辞書キー削除', [a, key, sys])
2725
- }
2726
- },
2727
- 'ハッシュキー存在': { // @ハッシュAのキーKEYが存在するか確認 // @はっしゅきーそんざい
2728
- type: 'func',
2729
- josi: [['の', 'に'], ['が']],
2730
- pure: true,
2731
- fn: function(a: any, key: any) {
2732
- return key in a
2733
- }
2734
- },
2735
- // @タイマー
2736
- '秒待': { // @ N秒の間待機する // @びょうまつ
2737
- type: 'func',
2738
- josi: [['']],
2739
- pure: true,
2740
- asyncFn: true,
2741
- fn: function(n: any, sys:any): Promise<void> {
2742
- return new Promise((resolve, reject) => {
2743
- try {
2744
- // タイマーを仕掛ける
2745
- const timerId = setTimeout(() => {
2746
- // タイマー使用中リストに追加したIDを削除
2747
- const i = sys.__timeout.indexOf(timerId)
2748
- if (i >= 0) { sys.__timeout.splice(i, 1) }
2749
- // Promiseを終了
2750
- resolve()
2751
- }, parseFloat(n) * 1000)
2752
- // タイマー使用中リストに追加
2753
- sys.__timeout.push(timerId)
2754
- } catch (err: any) {
2755
- reject(err)
2756
- }
2757
- })
2758
- },
2759
- return_none: true
2760
- },
2761
- '秒待機': { // @ N秒の間待機する(『秒待』と同じ) // @びょうたいき
2762
- type: 'func',
2763
- josi: [['']],
2764
- pure: true,
2765
- asyncFn: true,
2766
- fn: async function(n: any, sys: any) {
2767
- const p = sys.__exec('秒待', [n, sys])
2768
- return await p
2769
- },
2770
- return_none: true
2771
- },
2772
- '秒逐次待機': { // @ (非推奨) 逐次実行構文にて、N秒の間待機する (廃止予定) // @びょうちくじたいき
2773
- type: 'func',
2774
- josi: [['']],
2775
- pure: true,
2776
- asyncFn: true,
2777
- fn: async function(n: any, sys: any) {
2778
- const p = sys.__exec('秒待', [n, sys])
2779
- return await p
2780
- },
2781
- return_none: true
2782
- },
2783
- '秒後': { // @無名関数(あるいは、文字列で関数名を指定)FをN秒後に実行する。変数『対象』にタイマーIDを代入する。 // @びょうご
2784
- type: 'func',
2785
- josi: [['を'], ['']],
2786
- pure: true,
2787
- fn: function(f: any, n: any, sys: any) {
2788
- // 文字列で指定された関数をオブジェクトに変換
2789
- if (typeof f === 'string') { f = sys.__findFunc(f, '秒後') }
2790
- // 1回限りのタイマーをセット
2791
- const timerId = setTimeout(() => {
2792
- // 使用中リストに追加したIDを削除
2793
- const i = sys.__timeout.indexOf(timerId)
2794
- if (i >= 0) { sys.__timeout.splice(i, 1) }
2795
- try {
2796
- f(timerId, sys)
2797
- } catch (e: any) {
2798
- let err = e
2799
- if (!(e instanceof NakoRuntimeError)) {
2800
- err = new NakoRuntimeError(e, sys.__getSysVar('__line'))
2801
- }
2802
- sys.logger.error(err)
2803
- }
2804
- }, parseFloat(n) * 1000)
2805
- sys.__timeout.unshift(timerId)
2806
- sys.__setSysVar('対象', timerId)
2807
- return timerId
2808
- }
2809
- },
2810
- '秒毎': { // @無名関数(あるいは、文字列で関数名を指定)FをN秒ごとに実行する(『タイマー停止』で停止できる)。変数『対象』にタイマーIDを代入する。 // @びょうごと
2811
- type: 'func',
2812
- josi: [['を'], ['']],
2813
- pure: false,
2814
- fn: function(f: any, n: any, sys: any) {
2815
- // 文字列で指定された関数をオブジェクトに変換
2816
- if (typeof f === 'string') { f = sys.__findFunc(f, '秒毎') }
2817
- // タイマーをセット
2818
- const timerId = setInterval(() => {
2819
- f(timerId, sys)
2820
- }, parseFloat(n) * 1000)
2821
- // タイマーIDを追加
2822
- sys.__interval.unshift(timerId)
2823
- sys.__setSysVar('対象', timerId)
2824
- return timerId
2825
- }
2826
- },
2827
- '秒タイマー開始時': { // @無名関数(あるいは、文字列で関数名を指定)FをN秒ごとに実行する(『秒毎』と同じ) // @びょうたいまーかいししたとき
2828
- type: 'func',
2829
- josi: [['を'], ['']],
2830
- pure: false,
2831
- fn: function(f: any, n: any, sys: any) {
2832
- return sys.__exec('秒毎', [f, n, sys])
2833
- }
2834
- },
2835
- 'タイマー停止': { // @『秒毎』『秒後』や『秒タイマー開始』で開始したタイマーを停止する // @たいまーていし
2836
- type: 'func',
2837
- josi: [['の', 'で']],
2838
- pure: true,
2839
- fn: function(timerId: any, sys: any) {
2840
- const i = sys.__interval.indexOf(timerId)
2841
- if (i >= 0) {
2842
- sys.__interval.splice(i, 1)
2843
- clearInterval(timerId)
2844
- return true
2845
- }
2846
- const j = sys.__timeout.indexOf(timerId)
2847
- if (j >= 0) {
2848
- sys.__timeout.splice(j, 1)
2849
- clearTimeout(timerId)
2850
- return true
2851
- }
2852
- return false
2853
- },
2854
- return_none: false
2855
- },
2856
- '全タイマー停止': { // @『秒毎』『秒後』や『秒タイマー開始』で開始したタイマーを全部停止する // @ぜんたいまーていし
2857
- type: 'func',
2858
- josi: [],
2859
- pure: true,
2860
- fn: function(sys: NakoSystem) {
2861
- // clearInterval
2862
- for (let i = 0; i < sys.__interval.length; i++) {
2863
- const timerId = sys.__interval[i]
2864
- clearInterval(timerId)
2865
- }
2866
- sys.__interval = []
2867
- // clearTimeout
2868
- for (let i = 0; i < sys.__timeout.length; i++) {
2869
- const timerId = sys.__timeout[i]
2870
- clearTimeout(timerId)
2871
- }
2872
- sys.__timeout = []
2873
- },
2874
- return_none: true
2875
- },
2876
- // @日時処理(簡易)
2877
- '元号データ': { type: 'const', value: [{ '元号': '令和', '改元日': '2019/05/01' }, { '元号': '平成', '改元日': '1989/01/08' }, { '元号': '昭和', '改元日': '1926/12/25' }, { '元号': '大正', '改元日': '1912/07/30' }, { '元号': '明治', '改元日': '1868/10/23' }] }, // @げんごうでーた
2878
- '今': { // @現在時刻を「HH:mm:ss」の形式で返す // @いま
2879
- type: 'func',
2880
- josi: [],
2881
- pure: true,
2882
- fn: function() {
2883
- const z2 = (n: number): string => {
2884
- const ns = '00' + String(n)
2885
- return ns.substring(ns.length - 2, ns.length)
2886
- }
2887
- const t = new Date()
2888
- return z2(t.getHours()) + ':' + z2(t.getMinutes()) + ':' + z2(t.getSeconds())
2889
- }
2890
- },
2891
- 'システム時間': { // @現在のUNIX時間 (UTC(1970/1/1)からの経過秒数) を返す // @しすてむじかん
2892
- type: 'func',
2893
- josi: [],
2894
- pure: true,
2895
- fn: function() {
2896
- const now = new Date()
2897
- return Math.floor(now.getTime() / 1000)
2898
- }
2899
- },
2900
- 'システム時間ミリ秒': { // @現在のUNIX時間 (UTC(1970/1/1)からの経過秒数) をミリ秒で返す // @しすてむじかんみりびょう
2901
- type: 'func',
2902
- josi: [],
2903
- pure: true,
2904
- fn: function() {
2905
- const now = new Date()
2906
- return now.getTime()
2907
- }
2908
- },
2909
- '今日': { // @今日の日付を「YYYY/MM/DD」の形式で返す // @きょう
2910
- type: 'func',
2911
- josi: [],
2912
- pure: true,
2913
- fn: function(sys: NakoSystem) {
2914
- return sys.__formatDate(new Date())
2915
- }
2916
- },
2917
- '明日': { // @明日の日付を「YYYY/MM/DD」の形式で返す // @あした
2918
- type: 'func',
2919
- josi: [],
2920
- pure: true,
2921
- fn: function(sys: NakoSystem) {
2922
- const t = Date.now() + (24 * 60 * 60 * 1000)
2923
- return sys.__formatDate(new Date(t))
2924
- }
2925
- },
2926
- '昨日': { // @昨日の日付を「YYYY/MM/DD」の形式で返す // @きのう
2927
- type: 'func',
2928
- josi: [],
2929
- pure: true,
2930
- fn: function(sys: NakoSystem) {
2931
- const t = Date.now() - (24 * 60 * 60 * 1000)
2932
- return sys.__formatDate(new Date(t))
2933
- }
2934
- },
2935
- '今年': { // @今年が何年かを西暦で返す // @ことし
2936
- type: 'func',
2937
- josi: [],
2938
- pure: true,
2939
- fn: function() {
2940
- return (new Date()).getFullYear()
2941
- }
2942
- },
2943
- '来年': { // @来年が何年かを西暦で返す // @らいねん
2944
- type: 'func',
2945
- josi: [],
2946
- pure: true,
2947
- fn: function() {
2948
- return (new Date()).getFullYear() + 1
2949
- }
2950
- },
2951
- '去年': { // @去年が何年かを西暦で返す // @きょねん
2952
- type: 'func',
2953
- josi: [],
2954
- pure: true,
2955
- fn: function() {
2956
- return (new Date()).getFullYear() - 1
2957
- }
2958
- },
2959
- '今月': { // @今月が何月かを返す // @こんげつ
2960
- type: 'func',
2961
- josi: [],
2962
- pure: true,
2963
- fn: function() {
2964
- return (new Date()).getMonth() + 1
2965
- }
2966
- },
2967
- '来月': { // @来月が何月かを返す // @らいげつ
2968
- type: 'func',
2969
- josi: [],
2970
- pure: true,
2971
- fn: function() {
2972
- return (new Date()).getMonth() + 2
2973
- }
2974
- },
2975
- '先月': { // @先月が何月かを返す // @せんげつ
2976
- type: 'func',
2977
- josi: [],
2978
- pure: true,
2979
- fn: function() {
2980
- return (new Date()).getMonth()
2981
- }
2982
- },
2983
- '曜日': { // @Sに指定した日付の曜日を返す。不正な日付の場合は今日の曜日を返す。 // @ようび
2984
- type: 'func',
2985
- josi: [['の']],
2986
- pure: true,
2987
- fn: function(s: string, sys: any) {
2988
- const d = sys.__str2date(s)
2989
- return '日月火水木金土'.charAt(d.getDay() % 7)
2990
- }
2991
- },
2992
- '曜日番号取得': { // @Sに指定した日付の曜日番号を番号で返す。不正な日付の場合は今日の曜日番号を返す。(0=日/1=月/2=火/3=水/4=木/5=金/6=土) // @ようびばんごうしゅとく
2993
- type: 'func',
2994
- josi: [['の']],
2995
- pure: true,
2996
- fn: function(s: any) {
2997
- const a = s.split('/')
2998
- const t = new Date(a[0], a[1] - 1, a[2])
2999
- return t.getDay()
3000
- }
3001
- },
3002
- 'UNIXTIME変換': { // @日時SをUNIX時間 (UTC(1970/1/1)からの経過秒数) に変換して返す(v1非互換) // @UNIXTIMEへんかん
3003
- type: 'func',
3004
- josi: [['の', 'を', 'から']],
3005
- pure: true,
3006
- fn: function(s: string, sys: any) {
3007
- const d = sys.__str2date(s)
3008
- return d.getTime() / 1000
3009
- }
3010
- },
3011
- 'UNIX時間変換': { // @日時SをUNIX時間 (UTC(1970/1/1)からの経過秒数) に変換して返す(v1非互換) // @UNIXじかんへんかん
3012
- type: 'func',
3013
- josi: [['の', 'を', 'から']],
3014
- pure: true,
3015
- fn: function(s: string, sys: any) {
3016
- const d = sys.__str2date(s)
3017
- return d.getTime() / 1000
3018
- }
3019
- },
3020
- '日時変換': { // @UNIX時間 (UTC(1970/1/1)からの経過秒数) を「YYYY/MM/DD HH:mm:ss」の形式に変換 // @にちじへんかん
3021
- type: 'func',
3022
- josi: [['を', 'から']],
3023
- pure: true,
3024
- fn: function(tm: any, sys: any) {
3025
- const t = tm * 1000
3026
- return sys.__formatDateTime(new Date(t), '2022/01/01 00:00:00')
3027
- }
3028
- },
3029
- '日時書式変換': { // @UNIX時間TM(または日付文字列)を「YYYY/MM/DD HH:mm:ss」または「YY-M-D H:m:s」その他、W:曜日、WWW:曜日英、MMM:月英、ccc:ミリ秒の書式に変換 // @にちじしょしきへんかん
3030
- type: 'func',
3031
- josi: [['を'], ['で']],
3032
- pure: true,
3033
- fn: function(tm: any, fmt: any, sys: any) {
3034
- const t = sys.__str2date(tm)
3035
- fmt = fmt.replace(/(YYYY|ccc|WWW|MMM|YY|MM|DD|HH|mm|ss|[MDHmsW])/g, (m: string) => {
3036
- switch (m) {
3037
- case 'YYYY': return t.getFullYear()
3038
- case 'YY': return (String(t.getFullYear())).substring(2)
3039
- case 'MM': return sys.__zero2(String(t.getMonth() as number + 1))
3040
- case 'DD': return sys.__zero2(t.getDate())
3041
- case 'M': return (t.getMonth() as number + 1)
3042
- case 'D': return (t.getDate())
3043
- case 'HH': return sys.__zero2(t.getHours())
3044
- case 'mm': return sys.__zero2(t.getMinutes())
3045
- case 'ss': return sys.__zero2(t.getSeconds())
3046
- case 'ccc': return sys.__zero(t.getMilliseconds(), 3)
3047
- case 'H': return (t.getHours())
3048
- case 'm': return (t.getMinutes())
3049
- case 's': return (t.getSeconds())
3050
- case 'W': return '日月火水木金土'.charAt(t.getDay() % 7)
3051
- case 'WWW': return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][t.getDay() % 7]
3052
- case 'MMM': return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][t.getMonth()]
3053
- }
3054
- return m
3055
- })
3056
- return fmt
3057
- }
3058
- },
3059
- '和暦変換': { // @Sを和暦に変換する。Sは明治以降の日付が有効。 // @われきへんかん
3060
- type: 'func',
3061
- josi: [['を']],
3062
- pure: true,
3063
- fn: function(s: string, sys: NakoSystem) {
3064
- const d = sys.__str2date(s)
3065
- const t = d.getTime()
3066
- for (const era of sys.__getSysVar('元号データ')) {
3067
- const gengo = String(era['元号'])
3068
- const d2 = sys.__str2date(era['改元日'])
3069
- const t2 = d2.getTime()
3070
- if (t2 <= t) {
3071
- let y: any = (d.getFullYear() - d2.getFullYear()) + 1
3072
- if (y === 1) { y = '元' }
3073
- return gengo + String(y) + '年' + sys.__zero2(d.getMonth() + 1) + '月' + sys.__zero2(d.getDate()) + '日'
3074
- }
3075
- }
3076
- throw new Error('『和暦変換』は明示以前の日付には対応していません。')
3077
- }
3078
- },
3079
- '年数差': { // @日付AとBの差を年数で求めて返す。A<Bなら正の数、そうでないなら負の数を返す (v1非互換)。 // @ねんすうさ
3080
- type: 'func',
3081
- josi: [['と', 'から'], ['の', 'までの']],
3082
- pure: true,
3083
- fn: function(a: any, b: any, sys: any) {
3084
- const t1 = sys.__str2date(a)
3085
- const t2 = sys.__str2date(b)
3086
- return (t2.getFullYear() - t1.getFullYear())
3087
- }
3088
- },
3089
- '月数差': { // @日付AとBの差を月数で求めて返す。A<Bなら正の数、そうでないなら負の数を返す (v1非互換)。 // @げっすうさ
3090
- type: 'func',
3091
- josi: [['と', 'から'], ['の', 'までの']],
3092
- pure: true,
3093
- fn: function(a: any, b: any, sys: any) {
3094
- const t1 = sys.__str2date(a)
3095
- const t2 = sys.__str2date(b)
3096
- return (t2.getFullYear() * 12 + Number(t2.getMonth())) -
3097
- (t1.getFullYear() * 12 + Number(t1.getMonth()))
3098
- }
3099
- },
3100
- '日数差': { // @日付AとBの差を日数で求めて返す。A<Bなら正の数、そうでないなら負の数を返す。 // @にっすうさ
3101
- type: 'func',
3102
- josi: [['と', 'から'], ['の', 'までの']],
3103
- pure: true,
3104
- fn: function(a: any, b: any, sys: any) {
3105
- const t1 = Math.ceil(sys.__str2date(a).getTime() / 1000)
3106
- const t2 = Math.ceil(sys.__str2date(b).getTime() / 1000)
3107
- const days = Math.ceil((t2 - t1) / (60 * 60 * 24))
3108
- return days
3109
- }
3110
- },
3111
- '時間差': { // @時間AとBの時間の差を求めて返す。A<Bなら正の数、そうでないなら負の数を返す。 // @じかんさ
3112
- type: 'func',
3113
- josi: [['と', 'から'], ['の', 'までの']],
3114
- pure: true,
3115
- fn: function(a: any, b: any, sys: any) {
3116
- const t1 = Math.ceil(sys.__str2date(a).getTime() / 1000)
3117
- const t2 = Math.ceil(sys.__str2date(b).getTime() / 1000)
3118
- const hours = Math.ceil((t2 - t1) / (60 * 60))
3119
- return hours
3120
- }
3121
- },
3122
- '分差': { // @時間AとBの分数の差を求めて返す。A<Bなら正の数、そうでないなら負の数を返す。 // @ふんさ
3123
- type: 'func',
3124
- josi: [['と', 'から'], ['の', 'までの']],
3125
- pure: true,
3126
- fn: function(a: any, b: any, sys: any) {
3127
- const t1 = Math.ceil(sys.__str2date(a).getTime() / 1000)
3128
- const t2 = Math.ceil(sys.__str2date(b).getTime() / 1000)
3129
- const min = Math.ceil((t2 - t1) / (60))
3130
- return min
3131
- }
3132
- },
3133
- '秒差': { // @時間AとBの差を秒差で求めて返す。A<Bなら正の数、そうでないなら負の数を返す。 // @びょうさ
3134
- type: 'func',
3135
- josi: [['と', 'から'], ['の', 'までの']],
3136
- pure: true,
3137
- fn: function(a: any, b: any, sys: any) {
3138
- const t1 = Math.ceil(sys.__str2date(a).getTime() / 1000)
3139
- const t2 = Math.ceil(sys.__str2date(b).getTime() / 1000)
3140
- const sec = Math.ceil((t2 - t1))
3141
- return sec
3142
- }
3143
- },
3144
- '日時差': { // @日時AとBの差を種類unitで返す。A<Bなら正の数、そうでないなら負の数を返す (v1非互換)。 // @にちじさ
3145
- type: 'func',
3146
- josi: [['と', 'から'], ['の', 'までの'], ['による']],
3147
- pure: true,
3148
- fn: function(a: any, b: any, unit: string, sys: any): string {
3149
- switch (unit) {
3150
- case '年': return sys.__exec('年数差', [a, b, sys])
3151
- case '月': return sys.__exec('月数差', [a, b, sys])
3152
- case '日': return sys.__exec('日数差', [a, b, sys])
3153
- case '時間': return sys.__exec('時間差', [a, b, sys])
3154
- case '分': return sys.__exec('分差', [a, b, sys])
3155
- case '秒': return sys.__exec('秒差', [a, b, sys])
3156
- }
3157
- throw new Error('『日時差』で不明な単位です。')
3158
- }
3159
- },
3160
- '時間加算': { // @時間SにAを加えて返す。Aには「(+|-)hh:nn:dd」で指定する。 // @じかんかさん
3161
- type: 'func',
3162
- josi: [['に'], ['を']],
3163
- pure: true,
3164
- fn: function(s: string, a: string, sys: any) {
3165
- const op = a.charAt(0)
3166
- if (op === '-' || op === '+') {
3167
- a = a.substring(1)
3168
- }
3169
- const d = sys.__str2date(s)
3170
- const aa = (a + ':0:0').split(':')
3171
- let sec = parseInt(aa[0]) * 60 * 60 +
3172
- parseInt(aa[1]) * 60 +
3173
- parseInt(aa[2])
3174
- if (op === '-') { sec *= -1 }
3175
- const rd = new Date(Number(d.getTime()) + (sec * 1000))
3176
- return sys.__formatDateTime(rd, s)
3177
- }
3178
- },
3179
- '日付加算': { // @日付SにAを加えて返す。Aには「(+|-)yyyy/mm/dd」で指定する。 // @ひづけかさん
3180
- type: 'func',
3181
- josi: [['に'], ['を']],
3182
- pure: true,
3183
- fn: function(s: string, a: string, sys: any) {
3184
- let op = 1
3185
- const opc = a.charAt(0)
3186
- if (opc === '-' || opc === '+') {
3187
- a = a.substring(1)
3188
- if (opc === '-') { op *= -1 }
3189
- }
3190
- const d = sys.__str2date(s)
3191
- const aa = (a + '/0/0').split('/')
3192
- const addY = parseInt(aa[0]) * op
3193
- const addM = parseInt(aa[1]) * op
3194
- const addD = parseInt(aa[2]) * op
3195
- d.setFullYear(Number(d.getFullYear()) + addY)
3196
- d.setMonth(Number(d.getMonth()) + addM)
3197
- d.setDate(Number(d.getDate()) + addD)
3198
- return sys.__formatDateTime(d, s)
3199
- }
3200
- },
3201
- '日時加算': { // @日時SにAを加えて返す。Aは「(+|-)1(年|ヶ月|日|週|時間|分|秒)」のように指定する (v1非互換)。 // @にちじかさん
3202
- type: 'func',
3203
- josi: [['に'], ['を']],
3204
- pure: true,
3205
- fn: function(s: string, a: string, sys: any) {
3206
- const r = ('' + a).match(/([+|-]?)(\d+)(年|ヶ月|日|週間|時間|分|秒)$/)
3207
- if (!r) { throw new Error('『日付加算』は『(+|-)1(年|ヶ月|日|時間|分|秒)』の書式で指定します。') }
3208
- switch (r[3]) {
3209
- case '年': return sys.__exec('日付加算', [s, `${r[1]}${r[2]}/0/0`, sys])
3210
- case 'ヶ月': return sys.__exec('日付加算', [s, `${r[1]}0/${r[2]}/0`, sys])
3211
- case '週間': return sys.__exec('日付加算', [s, `${r[1]}0/0/${parseInt(r[2]) * 7}`, sys])
3212
- case '日': return sys.__exec('日付加算', [s, `${r[1]}0/0/${r[2]}`, sys])
3213
- case '時間': return sys.__exec('時間加算', [s, `${r[1]}${r[2]}:0:0`, sys])
3214
- case '分': return sys.__exec('時間加算', [s, `${r[1]}0:${r[2]}:0`, sys])
3215
- case '秒': return sys.__exec('時間加算', [s, `${r[1]}0:0:${r[2]}`, sys])
3216
- }
3217
- }
3218
- },
3219
- '時間ミリ秒取得': { // @ミリ秒単位の時間を数値で返す。結果は実装に依存する。 // @じかんみりびょうしゅとく
3220
- type: 'func',
3221
- josi: [],
3222
- pure: true,
3223
- fn: function() {
3224
- if (performance && performance.now) {
3225
- return performance.now()
3226
- } else if (Date.now) {
3227
- return Date.now()
3228
- } else {
3229
- const now = new Date()
3230
- return now.getTime()
3231
- }
3232
- }
3233
- },
3234
- // @デバッグ支援
3235
- 'デバッグ表示': { // @デバッグ用にSを表示する // @でばっぐひょうじ
3236
- type: 'func',
3237
- josi: [['と', 'を', 'の']],
3238
- pure: true,
3239
- fn: function(s: any, sys: NakoSystem) {
3240
- // 行番号の情報を得る
3241
- const lineInfo: string = String(sys.__getSysVar('__line', 0)) + '::'
3242
- const a = lineInfo.split(':', 2)
3243
- const no = parseInt(String(a[0]).replace('l', '')) + 1
3244
- const fname = a[1]
3245
- // オブジェクトならJSON文字列に変換
3246
- if (typeof s === 'object') {
3247
- s = JSON.stringify(s)
3248
- }
3249
- s = `${fname}(${no}): ${s}`
3250
- sys.__exec('表示', [s, sys])
3251
- },
3252
- return_none: true
3253
- },
3254
- 'ハテナ関数設定': { // @ハテナ関数「?? (計算式)」の動作をカスタマイズする。文字列の配列を指定可能で、システム関数名か「js:code」を指定可能。 // @はてなかんすうせってい
3255
- type: 'func',
3256
- josi: [['を', 'の']],
3257
- pure: true,
3258
- fn: function(s: any, sys: NakoSystem) {
3259
- if (typeof s === 'function') {
3260
- sys.__hatena = s
3261
- return
3262
- }
3263
- if (typeof s === 'string') {
3264
- sys.__hatena = sys.__getSysVar(s, 'デバッグ表示')
3265
- return
3266
- }
3267
- if (s instanceof Array) {
3268
- const fa: ((s: string, sys: NakoSystem)=>string)[] = (s as Array<string>).map((fstr: string) => {
3269
- if (fstr.substring(0, 3) === 'JS:') {
3270
- const code = fstr.substring(3)
3271
- return sys.__evalJS(code, sys)
3272
- } else {
3273
- return sys.__getSysVar(fstr, 'デバッグ表示')
3274
- }
3275
- })
3276
- sys.__hatena = (p: any, sys: NakoSystem) => {
3277
- let param: any = p
3278
- for (const f of fa) {
3279
- param = f(param, sys)
3280
- }
3281
- }
3282
- return
3283
- }
3284
- sys.__hatena = sys.__getSysVar('デバッグ表示')
3285
- },
3286
- return_none: true
3287
- },
3288
- 'ハテナ関数実行': { // @『ハテナ関数設定』で設定した関数を実行する // @はてなかんすうじっこう
3289
- type: 'func',
3290
- josi: [['の', 'を', 'と']],
3291
- pure: true,
3292
- fn: function(s: any, sys: NakoSystem) {
3293
- sys.__hatena(s, sys)
3294
- },
3295
- return_none: true
3296
- },
3297
- 'エラー発生': { // @故意にエラーSを発生させる // @えらーはっせい
3298
- type: 'func',
3299
- josi: [['の', 'で']],
3300
- pure: true,
3301
- fn: function(s: any) {
3302
- throw new Error(s)
3303
- },
3304
- return_none: true
3305
- },
3306
- '__DEBUG': { // @デバッグモードにする // @__DEBUG
3307
- type: 'func',
3308
- josi: [],
3309
- pure: true,
3310
- fn: function(sys: NakoSystem) {
3311
- sys.isDebug = true
3312
- console.log(sys)
3313
- }
3314
- },
3315
- '__DEBUG強制待機': { type: 'const', value: 0 }, // @__DEBUGきょうせいたいき
3316
- '__DEBUGブレイクポイント一覧': { type: 'const', value: [] }, // @__DEBUGぶれいくぽいんといちらん
3317
- '__DEBUG待機フラグ': { type: 'const', value: 0 }, // @__DEBUGたいきふらぐ
3318
- '__DEBUG_BP_WAIT': { // @エディタのブレイクポイント機能のための待機 // @__DEBUG_BP_WAIT
3319
- type: 'func',
3320
- josi: [['で']],
3321
- pure: true,
3322
- asyncFn: true,
3323
- fn: function(curLine: number, sys: any) {
3324
- return new Promise((resolve) => {
3325
- const breakpoints = sys.__getSysVar('__DEBUGブレイクポイント一覧')
3326
- const forceLine = sys.__getSysVar('__DEBUG強制待機')
3327
- sys.__setSysVar('__DEBUG強制待機', 0)
3328
- // ブレイクポイント or __DEBUG強制待機 が指定されたか?
3329
- if (breakpoints.indexOf(curLine) >= 0 || forceLine) {
3330
- if (sys.__getSysVar('プラグイン名') !== 'メイン') { return } // 現状メインのみデバッグする
3331
- console.log(`@__DEBUG_BP_WAIT(${curLine})`)
3332
- const timerId = setInterval(() => {
3333
- if (sys.__getSysVar('__DEBUG待機フラグ') === 1) {
3334
- sys.__setSysVar('__DEBUG待機フラグ', 0)
3335
- clearInterval(timerId)
3336
- resolve(curLine)
3337
- }
3338
- }, 500)
3339
- } else {
3340
- resolve(curLine)
3341
- }
3342
- })
3343
- }
3344
- },
3345
- 'グローバル関数一覧取得': { // @グローバル変数にある関数一覧を取得 // @ぐろーばるかんすういちらんしゅとく
3346
- type: 'func',
3347
- josi: [],
3348
- pure: true,
3349
- fn: function(sys: NakoSystem) {
3350
- const vars: Map<string, any> = (sys as any).__varslist[1]
3351
- const res: string[] = []
3352
- for (const key of vars.keys()) {
3353
- res.push(key)
3354
- }
3355
- return res
3356
- }
3357
- },
3358
- 'システム関数一覧取得': { // @システム関数の一覧を取得 // @しすてむかんすういちらんしゅとく
3359
- type: 'func',
3360
- josi: [],
3361
- pure: true,
3362
- fn: function(sys: NakoSystem) {
3363
- const vars: Map<string, any> = (sys as any).__v0
3364
- const res: string[] = []
3365
- for (const key of vars.keys()) {
3366
- if (key.startsWith('__') || key.startsWith('!') || key === 'meta') { continue }
3367
- res.push(key)
3368
- }
3369
- return res
3370
- }
3371
- },
3372
- 'システム関数存在': { // @文字列で関数名を指定してシステム関数が存在するかを調べる // @しすてむかんすうそんざい
3373
- type: 'func',
3374
- josi: [['が', 'の']],
3375
- pure: true,
3376
- fn: function(fname: string, sys: any) {
3377
- return (typeof sys.__getSysVar(fname) !== 'undefined')
3378
- }
3379
- },
3380
- 'プラグイン一覧取得': { // @利用中のプラグイン一覧を得る // @ぷらぐいんいちらんしゅとく
3381
- type: 'func',
3382
- josi: [],
3383
- pure: true,
3384
- fn: function(sys: NakoSystem) {
3385
- const a = []
3386
- for (const f in (sys as any).pluginfiles) { a.push(f) }
3387
- return a
3388
- }
3389
- },
3390
- 'モジュール一覧取得': { // @取り込んだモジュール一覧を得る // @もじゅーるいちらんしゅとく
3391
- type: 'func',
3392
- josi: [],
3393
- pure: true,
3394
- fn: function(sys: NakoSystem) {
3395
- const a = []
3396
- for (const f in (sys as any).__module) { a.push(f) }
3397
- return a
3398
- }
3399
- },
3400
- '助詞一覧取得': { // @文法として定義されている助詞の一覧を取得する // @じょしいちらんしゅとく
3401
- type: 'func',
3402
- josi: [],
3403
- pure: true,
3404
- asyncFn: false,
3405
- fn: function(sys: NakoSystem) {
3406
- return sys.josiList
3407
- }
3408
- },
3409
- '予約語一覧取得': { // @文法として定義されている予約語の一覧を取得する // @よやくごいちらんしゅとく
3410
- type: 'func',
3411
- josi: [],
3412
- pure: true,
3413
- asyncFn: false,
3414
- fn: function(sys: NakoSystem) {
3415
- return sys.reservedWords
3416
- }
3417
- },
3418
- // @プラグイン管理
3419
- 'プラグイン名': { type: 'const', value: 'メイン' }, // @ぷらぐいんめい
3420
- 'プラグイン名設定': { // @プラグイン名をSに変更する(システムにより自動的に「メイン」あるいはプラグインのファイル名が呼ばれる) // @ぷらぐいんめいせってい
3421
- type: 'func',
3422
- josi: [['に', 'へ']],
3423
- pure: true,
3424
- fn: function(s: string, sys: any) {
3425
- sys.__setSysVar('プラグイン名', s)
3426
- },
3427
- return_none: true
3428
- },
3429
- '名前空間': { type: 'const', value: '' }, // @なまえくうかん
3430
- '名前空間設定': { // @名前空間をSに設定する(システムにより自動的に変更される。ファイル名から拡張子を削ったもの) // @なまえくうかんせってい
3431
- type: 'func',
3432
- josi: [['に', 'へ']],
3433
- pure: true,
3434
- fn: function(s: string, sys: NakoSystem) {
3435
- // push namespace
3436
- (sys as any).__namespaceList.push([sys.__getSysVar('名前空間'), sys.__getSysVar('プラグイン名')])
3437
- sys.__setSysVar('名前空間', s)
3438
- },
3439
- return_none: true
3440
- },
3441
- '名前空間ポップ': { // @システム利用のため呼ぶべからず。(名前空間を一つ前の値に戻す) // @なまえくうかんぽっぷ
3442
- type: 'func',
3443
- josi: [],
3444
- pure: true,
3445
- fn: function(sys: NakoSystem) {
3446
- // pop namespace
3447
- const a = (sys as any).__namespaceList.pop()
3448
- if (a) {
3449
- sys.__setSysVar('名前空間', a[0])
3450
- sys.__setSysVar('プラグイン名', a[1])
3451
- }
3452
- },
3453
- return_none: true
3454
- },
3455
-
3456
- // @URLエンコードとパラメータ
3457
- 'URLエンコード': { // @URLエンコードして返す // @URLえんこーど
3458
- type: 'func',
3459
- josi: [['を', 'から']],
3460
- pure: true,
3461
- fn: function(text: any) {
3462
- return encodeURIComponent(text)
3463
- }
3464
- },
3465
- 'URLデコード': { // @URLデコードして返す // @URLでこーど
3466
- type: 'func',
3467
- josi: [['を', 'へ', 'に']],
3468
- pure: true,
3469
- fn: function(text: any) {
3470
- return decodeURIComponent(text)
3471
- }
3472
- },
3473
- 'URLパラメータ解析': { // @URLパラメータを解析してハッシュで返す // @URLぱらめーたかいせき
3474
- type: 'func',
3475
- josi: [['を', 'の', 'から']],
3476
- pure: true,
3477
- fn: function(url: string, sys: any) {
3478
- const res: any = {}
3479
- if (typeof url !== 'string') {
3480
- return res
3481
- }
3482
- const p = url.split('?')
3483
- if (p.length <= 1) {
3484
- return res
3485
- }
3486
- const params = p[1].split('&')
3487
- for (const line of params) {
3488
- const line2 = line + '='
3489
- const kv = line2.split('=')
3490
- const k = sys.__exec('URLデコード', [kv[0]])
3491
- res[k] = sys.__exec('URLデコード', [kv[1]])
3492
- }
3493
- return res
3494
- }
3495
- },
3496
- // @BASE64
3497
- 'BASE64エンコード': { // @BASE64エンコードして返す // @BASE64えんこーど
3498
- type: 'func',
3499
- josi: [['を', 'から']],
3500
- pure: true,
3501
- fn: function(text: any) {
3502
- // browser?
3503
- if (typeof (window) !== 'undefined' && (window as any).btoa) {
3504
- const u8a: any = new TextEncoder().encode(text)
3505
- const utf8str = String.fromCharCode.apply(null, u8a)
3506
- return btoa(utf8str)
3507
- }
3508
- // Node?
3509
- if (typeof (Buffer) !== 'undefined') {
3510
- return Buffer.from(text).toString('base64')
3511
- }
3512
- throw new Error('『BASE64エンコード』は利用できません。')
3513
- }
3514
- },
3515
- 'BASE64デコード': { // @BASE64デコードして返す // @BASE64でこーど
3516
- type: 'func',
3517
- josi: [['を', 'へ', 'に']],
3518
- pure: true,
3519
- fn: function(text: any) {
3520
- if (typeof (window) !== 'undefined' && (window as any).atob) {
3521
- const decodedUtf8str = atob(text)
3522
- const dec: any = Array.prototype.map.call(decodedUtf8str, c => c.charCodeAt())
3523
- const decodedArray = new Uint8Array(dec)
3524
- return new TextDecoder('UTF-8').decode(decodedArray)
3525
- }
3526
- // Node?
3527
- if (typeof (Buffer) !== 'undefined') {
3528
- return Buffer.from(text, 'base64').toString()
3529
- }
3530
- throw new Error('『BASE64デコード』は利用できません。')
3531
- }
3532
- },
3533
- // @パス操作
3534
- '拡張子抽出': { // @ファイル名Sから拡張子を抽出する // @かくちょうしちゅうしゅつ
3535
- type: 'func',
3536
- josi: [['から', 'の']],
3537
- pure: true,
3538
- fn: function(fname: string, sys: NakoSystem) {
3539
- if (fname === null || fname === undefined) { return '' }
3540
- const sep = sys.pathSeparator || '/'
3541
- if (fname.indexOf(sep) >= 0) { // パス記号があればファイル名を抽出
3542
- const parts = fname.split(sep)
3543
- fname = parts[parts.length - 1]
3544
- }
3545
- const m = fname.match(/(\.[a-zA-Z0-9_\-+]+)$/)
3546
- if (m) { return m[1] }
3547
- return ''
3548
- }
3549
- },
3550
- '拡張子変更': { // @ファイル名Aの拡張子をBに変更して返す // @かくちょうしへんこう
3551
- type: 'func',
3552
- josi: [['の', 'を', 'から'], ['に', 'へ']],
3553
- pure: true,
3554
- fn: function(fname: string, ext: string, sys: NakoSystem) {
3555
- if (fname === null || fname === undefined) { return ext }
3556
- const sep = sys.pathSeparator || '/'
3557
- const pathList = fname.split(sep)
3558
- const filename = pathList[pathList.length - 1]
3559
- const pathStr = pathList.slice(0, -1).join(sep)
3560
- const rawExt = (ext ?? '').trim()
3561
- let extWithDot = rawExt
3562
- if (rawExt !== '' ) {
3563
- extWithDot = rawExt.startsWith('.') ? rawExt : '.' + rawExt
3564
- }
3565
- const newFilename = filename.replace(/(\.[a-zA-Z0-9_\-+]+)?$/, extWithDot)
3566
- return sys.__exec('終端パス追加', [pathStr, sys]) + newFilename
3567
- }
3568
- },
3569
- '終端パス追加': { // @パスSの終端にパス区切り文字を追加して返す // @しゅうたんぱすついか
3570
- type: 'func',
3571
- josi: [['に', 'へ']],
3572
- pure: true,
3573
- fn: function(path: string, sys: NakoSystem) {
3574
- const sep = sys.pathSeparator || '/'
3575
- if (path === undefined || path === null || path === '') {
3576
- return ''
3577
- }
3578
- if (path.endsWith(sep)) {
3579
- return path
3580
- }
3581
- return path + sep
3582
- }
3583
- },
3584
- '終端パス除去': { // @フォルダ名DIRの末尾にあるパス記号を削除する // @しゅうたんぱすじょきょ
3585
- type: 'func',
3586
- josi: [['の', 'から']],
3587
- pure: true,
3588
- fn: function(dir: string, sys: NakoSystem) {
3589
- const sep = sys.pathSeparator || '/'
3590
- if (!dir) { return '' }
3591
- if (dir.endsWith(sep)) {
3592
- return dir.substring(0, dir.length - 1)
3593
- } else {
3594
- return dir
3595
- }
3596
- }
3597
- },
3598
- '終端パス削除': { // @フォルダ名DIRの末尾にあるパス記号を削除する // @しゅうたんぱすさくじょ
3599
- type: 'func',
3600
- josi: [['の', 'から']],
3601
- pure: true,
3602
- fn: function(dir: string, sys: NakoSystem) {
3603
- return sys.__exec('終端パス除去', [dir, sys])
3604
- }
3605
- },
3606
- 'ファイル名抽出': { // @パスPATHからファイル名を抽出して返す // @ふぁいるめいちゅうしゅつ
3607
- type: 'func',
3608
- josi: [['の', 'から']],
3609
- pure: true,
3610
- fn: function(dir: string, sys: NakoSystem) {
3611
- const sep = sys.pathSeparator || '/'
3612
- const parts = dir.split(sep)
3613
- return parts[parts.length - 1]
3614
- }
3615
- },
3616
- 'パス抽出': { // @パスPATHからディレクトリ部分を抽出して返す // @ぱすちゅうしゅつ
3617
- type: 'func',
3618
- josi: [['の', 'から']],
3619
- pure: true,
3620
- fn: function(dir: string, sys: NakoSystem) {
3621
- const sep = sys.pathSeparator || '/'
3622
- const parts = dir.split(sep)
3623
- parts.pop()
3624
- return parts.join(sep)
3625
- }
3626
- }
3627
- }
387
+ // 分割ファイルの命令を plugin_system にマージする (#2351)
388
+ // 実行時は単一のプラグイン『plugin_system』として振る舞う
389
+ Object.assign(PluginSystem, PluginSystemDebug)
390
+ Object.assign(PluginSystem, PluginSystemMath)
391
+ Object.assign(PluginSystem, PluginSystemString)
392
+ Object.assign(PluginSystem, PluginSystemArray)
393
+ Object.assign(PluginSystem, PluginSystemDatetime)
394
+ Object.assign(PluginSystem, PluginSystemUrl)
395
+ Object.assign(PluginSystem, PluginSystemTypes)
396
+ Object.assign(PluginSystem, PluginSystemJson)
397
+ Object.assign(PluginSystem, PluginSystemRegexp)
398
+ Object.assign(PluginSystem, PluginSystemDict)
399
+ Object.assign(PluginSystem, PluginSystemStdio)
400
+ Object.assign(PluginSystem, PluginSystemTimer)
401
+
402
+ export default PluginSystem