lexgui 0.7.8 → 0.7.10

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.
@@ -1,7 +1,8 @@
1
1
  import { LX } from 'lexgui';
2
2
 
3
- if(!LX) {
4
- throw("lexgui.js missing!");
3
+ if( !LX )
4
+ {
5
+ throw( "lexgui.js missing!" );
5
6
  }
6
7
 
7
8
  LX.extensions.push( 'CodeEditor' );
@@ -14,8 +15,8 @@ function strReverse( str ) { return str.split( "" ).reverse().join( "" ); }
14
15
  function isLetter( c ){ return /[a-zA-Z]/.test( c ); };
15
16
  function isSymbol( c ){ return /[^\w\s]/.test( c ); };
16
17
 
17
- function indexOfFrom( str, reg, from, reverse ) {
18
-
18
+ function indexOfFrom( str, reg, from, reverse )
19
+ {
19
20
  from = from ?? 0;
20
21
 
21
22
  if( reverse )
@@ -33,7 +34,8 @@ function indexOfFrom( str, reg, from, reverse ) {
33
34
  }
34
35
  }
35
36
 
36
- function codeScopesEqual( a, b ) {
37
+ function codeScopesEqual( a, b )
38
+ {
37
39
  if( a.length !== b.length ) return false;
38
40
  for( let i = 0; i < a.length; i++ )
39
41
  {
@@ -42,10 +44,10 @@ function codeScopesEqual( a, b ) {
42
44
  return true;
43
45
  }
44
46
 
45
- class CodeSelection {
46
-
47
- constructor( editor, cursor, className = "lexcodeselection" ) {
48
-
47
+ class CodeSelection
48
+ {
49
+ constructor( editor, cursor, className = "lexcodeselection" )
50
+ {
49
51
  this.editor = editor;
50
52
  this.cursor = cursor;
51
53
  this.className = className;
@@ -57,20 +59,23 @@ class CodeSelection {
57
59
  this.toY = cursor.line;
58
60
  }
59
61
 
60
- sameLine() {
62
+ sameLine()
63
+ {
61
64
  return this.fromY === this.toY;
62
65
  }
63
66
 
64
- samePosition() {
67
+ samePosition()
68
+ {
65
69
  return this.fromX === this.toX;
66
70
  }
67
71
 
68
- isEmpty() {
72
+ isEmpty()
73
+ {
69
74
  return this.sameLine() && this.samePosition();
70
75
  }
71
76
 
72
- invertIfNecessary() {
73
- // if( this.fromX > this.toX )
77
+ invertIfNecessary()
78
+ {
74
79
  if( this.fromY > this.toY )
75
80
  {
76
81
  swapElements( this, 'fromX', 'toX' );
@@ -82,8 +87,8 @@ class CodeSelection {
82
87
  }
83
88
  }
84
89
 
85
- selectInline( cursor, x, y, width, isSearchResult ) {
86
-
90
+ selectInline( cursor, x, y, width, isSearchResult )
91
+ {
87
92
  this.chars = width / this.editor.charWidth;
88
93
  this.fromX = x;
89
94
  this.toX = x + this.chars;
@@ -110,8 +115,8 @@ class CodeSelection {
110
115
  this.editor._hideActiveLine();
111
116
  }
112
117
 
113
- save() {
114
-
118
+ save()
119
+ {
115
120
  return {
116
121
  fromX: this.fromX,
117
122
  fromY: this.fromY,
@@ -120,16 +125,16 @@ class CodeSelection {
120
125
  }
121
126
  }
122
127
 
123
- load( data ) {
124
-
128
+ load( data )
129
+ {
125
130
  this.fromX = data.fromX;
126
131
  this.fromY = data.fromY;
127
132
  this.toX = data.toX;
128
133
  this.toY = data.toY;
129
134
  }
130
135
 
131
- getText() {
132
-
136
+ getText()
137
+ {
133
138
  if( !this.editor.code || !this.sameLine() )
134
139
  return null;
135
140
 
@@ -137,16 +142,16 @@ class CodeSelection {
137
142
  }
138
143
  };
139
144
 
140
- class ScrollBar {
141
-
145
+ class ScrollBar
146
+ {
142
147
  static SCROLLBAR_VERTICAL = 1;
143
148
  static SCROLLBAR_HORIZONTAL = 2;
144
149
 
145
150
  static SCROLLBAR_VERTICAL_WIDTH = 10;
146
151
  static SCROLLBAR_HORIZONTAL_HEIGHT = 10;
147
152
 
148
- constructor( editor, type ) {
149
-
153
+ constructor( editor, type )
154
+ {
150
155
  this.editor = editor;
151
156
  this.type = type;
152
157
 
@@ -199,7 +204,6 @@ class ScrollBar {
199
204
  doc.removeEventListener( "mouseup", inner_mouseup );
200
205
  }
201
206
  }
202
-
203
207
  }
204
208
 
205
209
  /* Highlight rules
@@ -210,8 +214,8 @@ class ScrollBar {
210
214
  to "ctx.discardToken" and no class is applied
211
215
  */
212
216
 
213
- const HighlightRules = {
214
-
217
+ const HighlightRules =
218
+ {
215
219
  common: [
216
220
  { test: ctx => ctx.inBlockComment, className: "cm-com" },
217
221
  { test: ctx => ctx.inString, action: (ctx, editor) => editor._appendStringToken( ctx.token ), discard: true },
@@ -280,9 +284,9 @@ const HighlightRules = {
280
284
  * @class CodeEditor
281
285
  */
282
286
 
283
- class CodeEditor {
284
-
285
- static __instances = [];
287
+ class CodeEditor
288
+ {
289
+ static __instances = [];
286
290
 
287
291
  static CURSOR_LEFT = 1;
288
292
  static CURSOR_TOP = 2;
@@ -295,17 +299,17 @@ class CodeEditor {
295
299
  static KEEP_VISIBLE_LINES = 1;
296
300
  static UPDATE_VISIBLE_LINES = 2;
297
301
 
298
- static WORD_TYPE_METHOD = 0;
299
- static WORD_TYPE_CLASS = 1;
302
+ static WORD_TYPE_METHOD = 0;
303
+ static WORD_TYPE_CLASS = 1;
300
304
 
301
- static CODE_MIN_FONT_SIZE = 9;
302
- static CODE_MAX_FONT_SIZE = 22;
305
+ static CODE_MIN_FONT_SIZE = 9;
306
+ static CODE_MAX_FONT_SIZE = 22;
303
307
 
304
- static LINE_GUTTER_WIDTH = 48;
305
- static LINE_GUTTER_WIDTH = 48;
308
+ static LINE_GUTTER_WIDTH = 48;
309
+ static LINE_GUTTER_WIDTH = 48;
306
310
 
307
- static RESIZE_SCROLLBAR_H = 1;
308
- static RESIZE_SCROLLBAR_V = 2;
311
+ static RESIZE_SCROLLBAR_H = 1;
312
+ static RESIZE_SCROLLBAR_V = 2;
309
313
  static RESIZE_SCROLLBAR_H_V = CodeEditor.RESIZE_SCROLLBAR_H | CodeEditor.RESIZE_SCROLLBAR_V;
310
314
 
311
315
  /**
@@ -317,8 +321,8 @@ class CodeEditor {
317
321
  * disableEdition:
318
322
  */
319
323
 
320
- constructor( area, options = {} ) {
321
-
324
+ constructor( area, options = {} )
325
+ {
322
326
  if( options.filesAsync )
323
327
  {
324
328
  options.files = [ ...options.filesAsync ];
@@ -336,8 +340,8 @@ class CodeEditor {
336
340
  }
337
341
  }
338
342
 
339
- async _init( area, options ) {
340
-
343
+ async _init( area, options )
344
+ {
341
345
  window.editor = this;
342
346
 
343
347
  CodeEditor.__instances.push( this );
@@ -1197,8 +1201,8 @@ class CodeEditor {
1197
1201
  else // Next char
1198
1202
  {
1199
1203
  var letter = this.getCharAtPos( cursor );
1200
- if( letter ) {
1201
-
1204
+ if( letter )
1205
+ {
1202
1206
  // Selecting chars
1203
1207
  if( e.shiftKey )
1204
1208
  {
@@ -1210,7 +1214,8 @@ class CodeEditor {
1210
1214
  }
1211
1215
  else
1212
1216
  {
1213
- if( !cursor.selection ) {
1217
+ if( !cursor.selection )
1218
+ {
1214
1219
  this.cursorToRight( letter, cursor );
1215
1220
  if( this.useAutoComplete && this.isAutoCompleteActive )
1216
1221
  this.showAutoCompleteBox( 'foo', cursor );
@@ -1221,16 +1226,20 @@ class CodeEditor {
1221
1226
  this.resetCursorPos( CodeEditor.CURSOR_LEFT_TOP, cursor );
1222
1227
  this.cursorToLine( cursor, cursor.selection.toY );
1223
1228
  this.cursorToPosition( cursor, cursor.selection.toX );
1224
- this.endSelection();
1229
+ this.endSelection( cursor );
1225
1230
  }
1226
1231
  }
1227
1232
  }
1228
- else if( this.code.lines[ cursor.line + 1 ] !== undefined ) {
1229
-
1230
- if( e.shiftKey ) {
1233
+ else if( this.code.lines[ cursor.line + 1 ] !== undefined )
1234
+ {
1235
+ if( e.shiftKey )
1236
+ {
1231
1237
  if( !cursor.selection ) this.startSelection( cursor );
1232
1238
  }
1233
- else this.endSelection();
1239
+ else
1240
+ {
1241
+ this.endSelection();
1242
+ }
1234
1243
 
1235
1244
  this.lineDown( cursor, true );
1236
1245
 
@@ -1290,6 +1299,10 @@ class CodeEditor {
1290
1299
  this.codeArea.root.style.height = `calc(100% - ${ this._fullVerticalOffset }px)`;
1291
1300
  }, 50 );
1292
1301
 
1302
+ if( options.callback )
1303
+ {
1304
+ options.callback.call( this, this );
1305
+ }
1293
1306
  });
1294
1307
 
1295
1308
  window.editor = this;
@@ -1338,7 +1351,8 @@ class CodeEditor {
1338
1351
  }
1339
1352
 
1340
1353
  // Clear signals
1341
- clear() {
1354
+ clear()
1355
+ {
1342
1356
  console.assert( this.rightStatusPanel && this.leftStatusPanel, "No panels to clear." );
1343
1357
  this.rightStatusPanel.clear();
1344
1358
  this.leftStatusPanel.clear();
@@ -1350,8 +1364,8 @@ class CodeEditor {
1350
1364
  }
1351
1365
 
1352
1366
  // This received key inputs from the entire document...
1353
- onKeyPressed( e ) {
1354
-
1367
+ onKeyPressed( e )
1368
+ {
1355
1369
  // Toggle visibility of the file explorer
1356
1370
  if( e.key == 'b' && e.ctrlKey && this.useFileExplorer )
1357
1371
  {
@@ -1369,13 +1383,14 @@ class CodeEditor {
1369
1383
  }
1370
1384
  }
1371
1385
 
1372
- getText( min ) {
1386
+ getText( min )
1387
+ {
1373
1388
  return this.code.lines.join( min ? ' ' : '\n' );
1374
1389
  }
1375
1390
 
1376
1391
  // This can be used to empty all text...
1377
- setText( text = "", lang ) {
1378
-
1392
+ setText( text = "", lang )
1393
+ {
1379
1394
  let newLines = text.split( '\n' );
1380
1395
  this.code.lines = [].concat( newLines );
1381
1396
 
@@ -1397,8 +1412,8 @@ class CodeEditor {
1397
1412
  this._processLinesIfNecessary();
1398
1413
  }
1399
1414
 
1400
- appendText( text, cursor ) {
1401
-
1415
+ appendText( text, cursor )
1416
+ {
1402
1417
  let lidx = cursor.line;
1403
1418
 
1404
1419
  if( cursor.selection )
@@ -1468,8 +1483,18 @@ class CodeEditor {
1468
1483
  } );
1469
1484
  }
1470
1485
 
1471
- async loadFile( file, options = {} ) {
1486
+ setCustomSuggestions( suggestions )
1487
+ {
1488
+ if( !suggestions || suggestions.constructor !== Array )
1489
+ {
1490
+ return;
1491
+ }
1492
+
1493
+ this.customSuggestions = suggestions;
1494
+ }
1472
1495
 
1496
+ async loadFile( file, options = {} )
1497
+ {
1473
1498
  const _innerAddTab = ( text, name, title ) => {
1474
1499
 
1475
1500
  // Remove Carriage Return in some cases and sub tabs using spaces
@@ -1540,8 +1565,8 @@ class CodeEditor {
1540
1565
  }
1541
1566
  }
1542
1567
 
1543
- _addUndoStep( cursor, force, deleteRedo = true ) {
1544
-
1568
+ _addUndoStep( cursor, force, deleteRedo = true )
1569
+ {
1545
1570
  // Only the mainc cursor stores undo steps
1546
1571
  if( !cursor.isMain )
1547
1572
  return;
@@ -1582,10 +1607,12 @@ class CodeEditor {
1582
1607
  } );
1583
1608
  }
1584
1609
 
1585
- _doUndo( cursor ) {
1586
-
1610
+ _doUndo( cursor )
1611
+ {
1587
1612
  if( !this.code.undoSteps.length )
1613
+ {
1588
1614
  return;
1615
+ }
1589
1616
 
1590
1617
  this._addRedoStep( cursor );
1591
1618
 
@@ -1612,8 +1639,8 @@ class CodeEditor {
1612
1639
  this._hideActiveLine();
1613
1640
  }
1614
1641
 
1615
- _addRedoStep( cursor ) {
1616
-
1642
+ _addRedoStep( cursor )
1643
+ {
1617
1644
  // Only the mainc cursor stores redo steps
1618
1645
  if( !cursor.isMain )
1619
1646
  {
@@ -1626,10 +1653,12 @@ class CodeEditor {
1626
1653
  } );
1627
1654
  }
1628
1655
 
1629
- _doRedo( cursor ) {
1630
-
1656
+ _doRedo( cursor )
1657
+ {
1631
1658
  if( !this.code.redoSteps.length )
1659
+ {
1632
1660
  return;
1661
+ }
1633
1662
 
1634
1663
  this._addUndoStep( cursor, true, false);
1635
1664
 
@@ -1656,8 +1685,8 @@ class CodeEditor {
1656
1685
  }
1657
1686
  }
1658
1687
 
1659
- _changeLanguage( lang, langExtension, override = false ) {
1660
-
1688
+ _changeLanguage( lang, langExtension, override = false )
1689
+ {
1661
1690
  this.code.language = lang;
1662
1691
  this.highlight = lang;
1663
1692
 
@@ -1702,8 +1731,8 @@ class CodeEditor {
1702
1731
  }
1703
1732
  }
1704
1733
 
1705
- _changeLanguageFromExtension( ext ) {
1706
-
1734
+ _changeLanguageFromExtension( ext )
1735
+ {
1707
1736
  if( !ext )
1708
1737
  {
1709
1738
  return this._changeLanguage( this.code.language );
@@ -1733,8 +1762,8 @@ class CodeEditor {
1733
1762
  this._changeLanguage( 'Plain Text' );
1734
1763
  }
1735
1764
 
1736
- _createStatusPanel( options ) {
1737
-
1765
+ _createStatusPanel( options )
1766
+ {
1738
1767
  if( this.skipInfo )
1739
1768
  {
1740
1769
  return;
@@ -1833,8 +1862,8 @@ class CodeEditor {
1833
1862
  return panel;
1834
1863
  }
1835
1864
 
1836
- _getFileIcon( name, extension, lang ) {
1837
-
1865
+ _getFileIcon( name, extension, lang )
1866
+ {
1838
1867
  const isNewTabButton = name ? ( name === '+' ) : false;
1839
1868
  if( isNewTabButton )
1840
1869
  {
@@ -1888,8 +1917,8 @@ class CodeEditor {
1888
1917
  return "AlignLeft gray";
1889
1918
  }
1890
1919
 
1891
- _onNewTab( e ) {
1892
-
1920
+ _onNewTab( e )
1921
+ {
1893
1922
  this.processFocus( false );
1894
1923
 
1895
1924
  if( this.onNewTab )
@@ -1906,8 +1935,8 @@ class CodeEditor {
1906
1935
  new LX.DropdownMenu( e.target, dmOptions, { side: "bottom", align: "start" });
1907
1936
  }
1908
1937
 
1909
- _onCreateNewFile() {
1910
-
1938
+ _onCreateNewFile()
1939
+ {
1911
1940
  let options = {};
1912
1941
 
1913
1942
  if( this.onCreateFile )
@@ -1923,8 +1952,8 @@ class CodeEditor {
1923
1952
  this.addTab( name, true, name, { indexOffset: options.indexOffset, language: options.language ?? "JavaScript" } );
1924
1953
  }
1925
1954
 
1926
- _onSelectTab( isNewTabButton, event, name ) {
1927
-
1955
+ _onSelectTab( isNewTabButton, event, name )
1956
+ {
1928
1957
  if( this.disableEdition )
1929
1958
  {
1930
1959
  return;
@@ -1973,8 +2002,8 @@ class CodeEditor {
1973
2002
  }
1974
2003
  }
1975
2004
 
1976
- _onContextMenuTab( isNewTabButton, event, name, ) {
1977
-
2005
+ _onContextMenuTab( isNewTabButton, event, name, )
2006
+ {
1978
2007
  if( isNewTabButton )
1979
2008
  {
1980
2009
  return;
@@ -2003,8 +2032,8 @@ class CodeEditor {
2003
2032
  ], { side: "bottom", align: "start", event });
2004
2033
  }
2005
2034
 
2006
- addTab( name, selected, title, options = {} ) {
2007
-
2035
+ addTab( name, selected, title, options = {} )
2036
+ {
2008
2037
  // If already loaded, set new name...
2009
2038
  const repeats = Object.keys( editor.loadedTabs ).slice( 1 ).reduce( ( v, key ) => {
2010
2039
  const noRepeatName = key.replace( /[_\d+]/g, '');
@@ -2120,8 +2149,8 @@ class CodeEditor {
2120
2149
  return name;
2121
2150
  }
2122
2151
 
2123
- loadCode( name ) {
2124
-
2152
+ loadCode( name )
2153
+ {
2125
2154
  // Hide all others
2126
2155
  this.codeSizer.querySelectorAll( ".code" ).forEach( c => c.classList.add( "hidden" ) );
2127
2156
 
@@ -2179,8 +2208,8 @@ class CodeEditor {
2179
2208
  this._updateDataInfoPanel( "@tab-name", code.tabName );
2180
2209
  }
2181
2210
 
2182
- loadTab( name ) {
2183
-
2211
+ loadTab( name )
2212
+ {
2184
2213
  // Already open...
2185
2214
  if( this.openedTabs[ name ] )
2186
2215
  {
@@ -2245,8 +2274,8 @@ class CodeEditor {
2245
2274
  this._updateDataInfoPanel( "@tab-name", code.tabName );
2246
2275
  }
2247
2276
 
2248
- closeTab( name, eraseAll ) {
2249
-
2277
+ closeTab( name, eraseAll )
2278
+ {
2250
2279
  if( !this.allowClosingTabs )
2251
2280
  {
2252
2281
  return;
@@ -2262,12 +2291,13 @@ class CodeEditor {
2262
2291
  }
2263
2292
  }
2264
2293
 
2265
- getSelectedTabName() {
2294
+ getSelectedTabName()
2295
+ {
2266
2296
  return this.tabs.selected;
2267
2297
  }
2268
2298
 
2269
- loadTabFromFile() {
2270
-
2299
+ loadTabFromFile()
2300
+ {
2271
2301
  const input = document.createElement( 'input' );
2272
2302
  input.type = 'file';
2273
2303
  document.body.appendChild( input );
@@ -2281,8 +2311,8 @@ class CodeEditor {
2281
2311
  });
2282
2312
  }
2283
2313
 
2284
- processFocus( active ) {
2285
-
2314
+ processFocus( active )
2315
+ {
2286
2316
  if( active )
2287
2317
  {
2288
2318
  this.restartBlink();
@@ -2294,8 +2324,8 @@ class CodeEditor {
2294
2324
  }
2295
2325
  }
2296
2326
 
2297
- processMouse( e ) {
2298
-
2327
+ processMouse( e )
2328
+ {
2299
2329
  if( !e.target.classList.contains('code') && !e.target.classList.contains('lexcodearea') ) return;
2300
2330
  if( !this.code ) return;
2301
2331
 
@@ -2435,8 +2465,8 @@ class CodeEditor {
2435
2465
  }
2436
2466
  }
2437
2467
 
2438
- _onMouseUp( e ) {
2439
-
2468
+ _onMouseUp( e )
2469
+ {
2440
2470
  if( ( LX.getTime() - this.lastMouseDown ) < 120 )
2441
2471
  {
2442
2472
  this.state.selectingText = false;
@@ -2453,8 +2483,8 @@ class CodeEditor {
2453
2483
  delete this._lastSelectionKeyDir;
2454
2484
  }
2455
2485
 
2456
- processClick( e ) {
2457
-
2486
+ processClick( e )
2487
+ {
2458
2488
  var cursor = this.getCurrentCursor();
2459
2489
  var code_rect = this.codeScroller.getBoundingClientRect();
2460
2490
  var position = [( e.clientX - code_rect.x ) + this.getScrollLeft(), (e.clientY - code_rect.y) + this.getScrollTop()];
@@ -2485,8 +2515,8 @@ class CodeEditor {
2485
2515
  this.hideAutoCompleteBox();
2486
2516
  }
2487
2517
 
2488
- updateSelections( e, keepRange, flags = CodeEditor.SELECTION_X_Y ) {
2489
-
2518
+ updateSelections( e, keepRange, flags = CodeEditor.SELECTION_X_Y )
2519
+ {
2490
2520
  for( let cursor of this.cursors.children )
2491
2521
  {
2492
2522
  if( !cursor.selection )
@@ -2498,16 +2528,16 @@ class CodeEditor {
2498
2528
  }
2499
2529
  }
2500
2530
 
2501
- processSelections( e, keepRange, flags = CodeEditor.SELECTION_X_Y ) {
2502
-
2531
+ processSelections( e, keepRange, flags = CodeEditor.SELECTION_X_Y )
2532
+ {
2503
2533
  for( let cursor of this.cursors.children )
2504
2534
  {
2505
2535
  this._processSelection( cursor, e, keepRange, flags );
2506
2536
  }
2507
2537
  }
2508
2538
 
2509
- _processSelection( cursor, e, keepRange, flags = CodeEditor.SELECTION_X_Y ) {
2510
-
2539
+ _processSelection( cursor, e, keepRange, flags = CodeEditor.SELECTION_X_Y )
2540
+ {
2511
2541
  const isMouseEvent = e && ( e.constructor == MouseEvent );
2512
2542
 
2513
2543
  if( isMouseEvent )
@@ -2668,8 +2698,8 @@ class CodeEditor {
2668
2698
  }
2669
2699
  }
2670
2700
 
2671
- async processKey( e ) {
2672
-
2701
+ async processKey( e )
2702
+ {
2673
2703
  const numCursors = this.cursors.childElementCount;
2674
2704
 
2675
2705
  if( !this.code || e.srcElement.constructor != HTMLDivElement )
@@ -2737,8 +2767,8 @@ class CodeEditor {
2737
2767
  delete this._lastProcessedCursorIndex;
2738
2768
  }
2739
2769
 
2740
- async processKeyAtTargetCursor( e, key, targetIdx ) {
2741
-
2770
+ async processKeyAtTargetCursor( e, key, targetIdx )
2771
+ {
2742
2772
  let cursor = this.cursors.children[ targetIdx ];
2743
2773
 
2744
2774
  // We could delete secondary cursor while iterating..
@@ -2749,13 +2779,14 @@ class CodeEditor {
2749
2779
  this._processGlobalKeys( e, key );
2750
2780
  }
2751
2781
 
2752
- _processGlobalKeys( e, key ) {
2753
-
2782
+ _processGlobalKeys( e, key )
2783
+ {
2754
2784
  let cursor = this.getCurrentCursor();
2755
2785
 
2756
2786
  if( e.ctrlKey || e.metaKey )
2757
2787
  {
2758
- switch( key.toLowerCase() ) {
2788
+ switch( key.toLowerCase() )
2789
+ {
2759
2790
  case 'a': // select all
2760
2791
  e.preventDefault();
2761
2792
  this.selectAll();
@@ -2831,8 +2862,8 @@ class CodeEditor {
2831
2862
  return false;
2832
2863
  }
2833
2864
 
2834
- async _processKeyAtCursor( e, key, cursor ) {
2835
-
2865
+ async _processKeyAtCursor( e, key, cursor )
2866
+ {
2836
2867
  const skipUndo = e.detail.skipUndo ?? false;
2837
2868
 
2838
2869
  // keys with length > 1 are probably special keys
@@ -2994,8 +3025,8 @@ class CodeEditor {
2994
3025
  }
2995
3026
  }
2996
3027
 
2997
- async _pasteContent( cursor ) {
2998
-
3028
+ async _pasteContent( cursor )
3029
+ {
2999
3030
  const mustDetectLanguage = ( !this.getText().length );
3000
3031
 
3001
3032
  let text = await navigator.clipboard.readText();
@@ -3025,8 +3056,8 @@ class CodeEditor {
3025
3056
  }
3026
3057
  }
3027
3058
 
3028
- async _copyContent( cursor ) {
3029
-
3059
+ async _copyContent( cursor )
3060
+ {
3030
3061
  let textToCopy = "";
3031
3062
 
3032
3063
  if( !cursor.selection )
@@ -3060,8 +3091,8 @@ class CodeEditor {
3060
3091
  // .then(() => console.log("Successfully copied"), (err) => console.error("Error"));
3061
3092
  }
3062
3093
 
3063
- async _cutContent( cursor ) {
3064
-
3094
+ async _cutContent( cursor )
3095
+ {
3065
3096
  let lidx = cursor.line;
3066
3097
  let textToCut = "";
3067
3098
 
@@ -3107,8 +3138,8 @@ class CodeEditor {
3107
3138
  // .then(() => console.log("Successfully cut"), (err) => console.error("Error"));
3108
3139
  }
3109
3140
 
3110
- _duplicateLine( lidx, cursor ) {
3111
-
3141
+ _duplicateLine( lidx, cursor )
3142
+ {
3112
3143
  this.endSelection();
3113
3144
  this._addUndoStep( cursor, true );
3114
3145
  this.code.lines.splice( lidx, 0, this.code.lines[ lidx ] );
@@ -3117,8 +3148,8 @@ class CodeEditor {
3117
3148
  this.hideAutoCompleteBox();
3118
3149
  }
3119
3150
 
3120
- _commentLines( cursor, useCommentBlock ) {
3121
-
3151
+ _commentLines( cursor, useCommentBlock )
3152
+ {
3122
3153
  const lang = CodeEditor.languages[ this.highlight ];
3123
3154
 
3124
3155
  this.state.keyChain = null;
@@ -3195,8 +3226,8 @@ class CodeEditor {
3195
3226
  this._hideActiveLine();
3196
3227
  }
3197
3228
 
3198
- _commentLine( cursor, line, minNonspaceIdx, updateCursor = true ) {
3199
-
3229
+ _commentLine( cursor, line, minNonspaceIdx, updateCursor = true )
3230
+ {
3200
3231
  const lang = CodeEditor.languages[ this.highlight ];
3201
3232
  if( !( lang.singleLineComments ?? true ) )
3202
3233
  return;
@@ -3225,8 +3256,8 @@ class CodeEditor {
3225
3256
  }
3226
3257
  }
3227
3258
 
3228
- _uncommentLines( cursor ) {
3229
-
3259
+ _uncommentLines( cursor )
3260
+ {
3230
3261
  this.state.keyChain = null;
3231
3262
 
3232
3263
  if( cursor.selection )
@@ -3252,8 +3283,8 @@ class CodeEditor {
3252
3283
  this._hideActiveLine();
3253
3284
  }
3254
3285
 
3255
- _uncommentLine( cursor, line ) {
3256
-
3286
+ _uncommentLine( cursor, line )
3287
+ {
3257
3288
  const lang = CodeEditor.languages[ this.highlight ];
3258
3289
 
3259
3290
  if( !( lang.singleLineComments ?? true ))
@@ -3274,8 +3305,8 @@ class CodeEditor {
3274
3305
  }
3275
3306
  }
3276
3307
 
3277
- action( key, deleteSelection, fn, eventSkipDelete ) {
3278
-
3308
+ action( key, deleteSelection, fn, eventSkipDelete )
3309
+ {
3279
3310
  this.actions[ key ] = {
3280
3311
  "key": key,
3281
3312
  "callback": fn,
@@ -3284,13 +3315,14 @@ class CodeEditor {
3284
3315
  };
3285
3316
  }
3286
3317
 
3287
- _actionMustDelete( cursor, action, e ) {
3318
+ _actionMustDelete( cursor, action, e )
3319
+ {
3288
3320
  return cursor.selection && action.deleteSelection &&
3289
3321
  ( action.eventSkipDelete ? !e[ action.eventSkipDelete ] : true );
3290
3322
  }
3291
3323
 
3292
- scanWordSuggestions() {
3293
-
3324
+ scanWordSuggestions()
3325
+ {
3294
3326
  this.code.tokens = {};
3295
3327
 
3296
3328
  for( let i = 0; i < this.code.lines.length; ++i )
@@ -3301,16 +3333,19 @@ class CodeEditor {
3301
3333
  }
3302
3334
  }
3303
3335
 
3304
- toLocalLine( line ) {
3336
+ toLocalLine( line )
3337
+ {
3305
3338
  const d = Math.max( this.firstLineInViewport - this.lineScrollMargin.x, 0 );
3306
3339
  return Math.min( Math.max( line - d, 0 ), this.code.lines.length - 1 );
3307
3340
  }
3308
3341
 
3309
- getMaxLineLength() {
3342
+ getMaxLineLength()
3343
+ {
3310
3344
  return Math.max(...this.code.lines.map( v => v.length ));
3311
3345
  }
3312
3346
 
3313
- _processLinesIfNecessary() {
3347
+ _processLinesIfNecessary()
3348
+ {
3314
3349
  if( this.mustProcessLines )
3315
3350
  {
3316
3351
  this.mustProcessLines = false;
@@ -3318,8 +3353,8 @@ class CodeEditor {
3318
3353
  }
3319
3354
  }
3320
3355
 
3321
- processLines( mode ) {
3322
-
3356
+ processLines( mode )
3357
+ {
3323
3358
  if( !this.code )
3324
3359
  {
3325
3360
  return;
@@ -3373,8 +3408,8 @@ class CodeEditor {
3373
3408
  this.resize();
3374
3409
  }
3375
3410
 
3376
- processLine( lineNumber, force, skipPropagation ) {
3377
-
3411
+ processLine( lineNumber, force, skipPropagation )
3412
+ {
3378
3413
  if( this._scopeStack )
3379
3414
  {
3380
3415
  this.code.lineScopes[ lineNumber ] = [ ...this._scopeStack ];
@@ -3596,14 +3631,15 @@ class CodeEditor {
3596
3631
  return this._updateLine( force, lineNumber, lineInnerHtml, skipPropagation, symbols, tokensToEvaluate );
3597
3632
  }
3598
3633
 
3599
- _getLineSignatureFromTokens( tokens ) {
3634
+ _getLineSignatureFromTokens( tokens )
3635
+ {
3600
3636
  const structuralChars = new Set( [ '{', '}'] );
3601
3637
  const sign = tokens.filter( t => structuralChars.has( t ) );
3602
3638
  return sign.join( "_" );
3603
3639
  }
3604
3640
 
3605
- _updateBlockComments( section, lineNumber, tokens ) {
3606
-
3641
+ _updateBlockComments( section, lineNumber, tokens )
3642
+ {
3607
3643
  const lang = CodeEditor.languages[ this.highlight ];
3608
3644
  const blockCommentsTokens = lang.blockCommentsTokens ?? this.defaultBlockCommentTokens;
3609
3645
  const lineOpensBlock = ( section[ 0 ].x === lineNumber );
@@ -3682,8 +3718,8 @@ class CodeEditor {
3682
3718
  }
3683
3719
  }
3684
3720
 
3685
- _processExtraLineIfNecessary( lineNumber, tokens, oldSymbols, skipPropagation ) {
3686
-
3721
+ _processExtraLineIfNecessary( lineNumber, tokens, oldSymbols, skipPropagation )
3722
+ {
3687
3723
  if( !this._scopeStack )
3688
3724
  {
3689
3725
  console.warn( "CodeEditor: No scope available" );
@@ -3750,8 +3786,8 @@ class CodeEditor {
3750
3786
  }
3751
3787
  }
3752
3788
 
3753
- _updateLine( force, lineNumber, html, skipPropagation, symbols = [], tokens = [] ) {
3754
-
3789
+ _updateLine( force, lineNumber, html, skipPropagation, symbols = [], tokens = [] )
3790
+ {
3755
3791
  const gutterLineHtml = `<span class='line-gutter'>${ lineNumber + 1 }</span>`;
3756
3792
  const oldSymbols = this._updateLineSymbols( lineNumber, symbols );
3757
3793
  const lineScope = CodeEditor.debugScopes && this.code.lineScopes[ lineNumber ] ? this.code.lineScopes[ lineNumber ].map( s => `${ s.type }` ).join( ", " ) : "";
@@ -3809,8 +3845,8 @@ class CodeEditor {
3809
3845
  /**
3810
3846
  * Parses a single line of code and extract declared symbols
3811
3847
  */
3812
- _parseLineForSymbols( lineNumber, lineString, tokens, pushedScope ) {
3813
-
3848
+ _parseLineForSymbols( lineNumber, lineString, tokens, pushedScope )
3849
+ {
3814
3850
  const scope = this._scopeStack.at( pushedScope ? -2 : -1 );
3815
3851
 
3816
3852
  if( !scope || this._inBlockCommentSection( lineNumber ) )
@@ -3946,8 +3982,8 @@ class CodeEditor {
3946
3982
  * - Removes old symbols from that line
3947
3983
  * - Inserts the new symbols
3948
3984
  */
3949
- _updateLineSymbols( lineNumber, newSymbols ) {
3950
-
3985
+ _updateLineSymbols( lineNumber, newSymbols )
3986
+ {
3951
3987
  this.code.lineSymbols[ lineNumber ] = this.code.lineSymbols[ lineNumber ] ?? [];
3952
3988
  const oldSymbols = LX.deepCopy( this.code.lineSymbols[ lineNumber ] );
3953
3989
 
@@ -3986,8 +4022,8 @@ class CodeEditor {
3986
4022
  return oldSymbols;
3987
4023
  }
3988
4024
 
3989
- _lineHasComment( lineString ) {
3990
-
4025
+ _lineHasComment( lineString )
4026
+ {
3991
4027
  const lang = CodeEditor.languages[ this.highlight ];
3992
4028
 
3993
4029
  if( !(lang.singleLineComments ?? true) )
@@ -4012,8 +4048,8 @@ class CodeEditor {
4012
4048
  }
4013
4049
  }
4014
4050
 
4015
- _getTokensFromLine( lineString, skipNonWords ) {
4016
-
4051
+ _getTokensFromLine( lineString, skipNonWords )
4052
+ {
4017
4053
  if( !lineString || !lineString.length )
4018
4054
  {
4019
4055
  return [];
@@ -4072,8 +4108,8 @@ class CodeEditor {
4072
4108
  return this._processTokens( tokensToEvaluate );
4073
4109
  }
4074
4110
 
4075
- _processTokens( tokens, offset = 0 ) {
4076
-
4111
+ _processTokens( tokens, offset = 0 )
4112
+ {
4077
4113
  if( this.highlight == 'C++' || this.highlight == 'CSS' )
4078
4114
  {
4079
4115
  var idx = tokens.slice( offset ).findIndex( ( value, index ) => this._isNumber( value ) );
@@ -4142,8 +4178,8 @@ class CodeEditor {
4142
4178
  return tokens;
4143
4179
  }
4144
4180
 
4145
- _mustHightlightWord( token, wordCategory, lang ) {
4146
-
4181
+ _mustHightlightWord( token, wordCategory, lang )
4182
+ {
4147
4183
  if( !lang )
4148
4184
  {
4149
4185
  lang = CodeEditor.languages[ this.highlight ];
@@ -4159,8 +4195,8 @@ class CodeEditor {
4159
4195
  return wordCategory[ this.highlight ] && wordCategory[ this.highlight ].has( t );
4160
4196
  }
4161
4197
 
4162
- _getTokenHighlighting( ctx, highlight ) {
4163
-
4198
+ _getTokenHighlighting( ctx, highlight )
4199
+ {
4164
4200
  const rules = [ ...HighlightRules.common, ...( HighlightRules[ highlight ] || [] ), ...HighlightRules.post_common ];
4165
4201
 
4166
4202
  for( const rule of rules )
@@ -4178,8 +4214,8 @@ class CodeEditor {
4178
4214
  return null;
4179
4215
  }
4180
4216
 
4181
- _evaluateToken( ctxData ) {
4182
-
4217
+ _evaluateToken( ctxData )
4218
+ {
4183
4219
  let { token, prev, next, tokenIndex, isFirstToken, isLastToken } = ctxData;
4184
4220
 
4185
4221
  const lang = CodeEditor.languages[ this.highlight ];
@@ -4276,8 +4312,8 @@ class CodeEditor {
4276
4312
  return `<span class="${ highlight } ${ tokenClass }">${ token }</span>`;
4277
4313
  }
4278
4314
 
4279
- _appendStringToken( token ) {
4280
-
4315
+ _appendStringToken( token )
4316
+ {
4281
4317
  if( !this._pendingString )
4282
4318
  {
4283
4319
  this._pendingString = "";
@@ -4288,14 +4324,15 @@ class CodeEditor {
4288
4324
  return true;
4289
4325
  }
4290
4326
 
4291
- _getCurrentString() {
4327
+ _getCurrentString()
4328
+ {
4292
4329
  const chars = this._pendingString;
4293
4330
  delete this._pendingString;
4294
4331
  return chars;
4295
4332
  }
4296
4333
 
4297
- _enclosedByTokens( token, tokenIndex, tagStart, tagEnd ) {
4298
-
4334
+ _enclosedByTokens( token, tokenIndex, tagStart, tagEnd )
4335
+ {
4299
4336
  const tokenStartIndex = this._currentTokenPositions[ tokenIndex ];
4300
4337
  const tagStartIndex = indexOfFrom( this._currentLineString, tagStart, tokenStartIndex, true );
4301
4338
  if( tagStartIndex < 0 ) // Not found..
@@ -4313,8 +4350,8 @@ class CodeEditor {
4313
4350
  }
4314
4351
  }
4315
4352
 
4316
- _inBlockCommentSection( lineNumber, tokenPosition, tokenLength ) {
4317
-
4353
+ _inBlockCommentSection( lineNumber, tokenPosition, tokenLength )
4354
+ {
4318
4355
  const lang = CodeEditor.languages[ this.highlight ];
4319
4356
  const blockCommentsTokens = lang.blockCommentsTokens ?? this.defaultBlockCommentTokens;
4320
4357
 
@@ -4341,8 +4378,8 @@ class CodeEditor {
4341
4378
  }
4342
4379
  }
4343
4380
 
4344
- _isKeyword( ctxData ) {
4345
-
4381
+ _isKeyword( ctxData )
4382
+ {
4346
4383
  const { token, tokenIndex, tokens, lang } = ctxData;
4347
4384
 
4348
4385
  let isKwd = this._mustHightlightWord( token, CodeEditor.keywords ) || this.highlight == 'XML';
@@ -4373,8 +4410,8 @@ class CodeEditor {
4373
4410
  return isKwd;
4374
4411
  }
4375
4412
 
4376
- _isNumber( token ) {
4377
-
4413
+ _isNumber( token )
4414
+ {
4378
4415
  const lang = CodeEditor.languages[ this.highlight ];
4379
4416
  if( !( lang.numbers ?? true ) )
4380
4417
  {
@@ -4412,8 +4449,8 @@ class CodeEditor {
4412
4449
  return token.length && token != ' ' && !Number.isNaN( +token );
4413
4450
  }
4414
4451
 
4415
- _encloseSelectedWordWithKey( key, lidx, cursor ) {
4416
-
4452
+ _encloseSelectedWordWithKey( key, lidx, cursor )
4453
+ {
4417
4454
  if( !cursor.selection || ( cursor.selection.fromY != cursor.selection.toY ) )
4418
4455
  {
4419
4456
  return false;
@@ -4460,8 +4497,8 @@ class CodeEditor {
4460
4497
  return true;
4461
4498
  }
4462
4499
 
4463
- _detectLanguage( text ) {
4464
-
4500
+ _detectLanguage( text )
4501
+ {
4465
4502
  const tokenSet = new Set( this._getTokensFromLine( text, true ) );
4466
4503
  const scores = {};
4467
4504
 
@@ -4500,8 +4537,8 @@ class CodeEditor {
4500
4537
  return sorted[0][1] > 0 ? sorted[0][0] : undefined;
4501
4538
  }
4502
4539
 
4503
- lineUp( cursor, resetLeft ) {
4504
-
4540
+ lineUp( cursor, resetLeft )
4541
+ {
4505
4542
  if( this.code.lines[ cursor.line - 1 ] == undefined )
4506
4543
  return false;
4507
4544
 
@@ -4512,8 +4549,8 @@ class CodeEditor {
4512
4549
  return true;
4513
4550
  }
4514
4551
 
4515
- lineDown( cursor, resetLeft ) {
4516
-
4552
+ lineDown( cursor, resetLeft )
4553
+ {
4517
4554
  if( this.code.lines[ cursor.line + 1 ] == undefined )
4518
4555
  return false;
4519
4556
 
@@ -4524,8 +4561,8 @@ class CodeEditor {
4524
4561
  return true;
4525
4562
  }
4526
4563
 
4527
- restartBlink() {
4528
-
4564
+ restartBlink()
4565
+ {
4529
4566
  if( !this.code ) return;
4530
4567
 
4531
4568
  clearInterval( this.blinker );
@@ -4539,8 +4576,8 @@ class CodeEditor {
4539
4576
  this.cursors.classList.remove( 'show' );
4540
4577
  }
4541
4578
 
4542
- startSelection( cursor ) {
4543
-
4579
+ startSelection( cursor )
4580
+ {
4544
4581
  // Show elements
4545
4582
  let selectionContainer = document.createElement( 'div' );
4546
4583
  selectionContainer.className = 'selections';
@@ -4553,8 +4590,8 @@ class CodeEditor {
4553
4590
  cursor.selection = new CodeSelection( this, cursor );
4554
4591
  }
4555
4592
 
4556
- deleteSelection( cursor ) {
4557
-
4593
+ deleteSelection( cursor )
4594
+ {
4558
4595
  // I think it's not necessary but...
4559
4596
  if( this.disableEdition )
4560
4597
  {
@@ -4586,8 +4623,8 @@ class CodeEditor {
4586
4623
  this.processLines();
4587
4624
  }
4588
4625
 
4589
- endSelection( cursor ) {
4590
-
4626
+ endSelection( cursor )
4627
+ {
4591
4628
  delete this._tripleClickSelection;
4592
4629
  delete this._lastSelectionKeyDir;
4593
4630
  delete this._currentOcurrences;
@@ -4610,7 +4647,9 @@ class CodeEditor {
4610
4647
  }
4611
4648
  }
4612
4649
 
4613
- selectAll() {
4650
+ selectAll()
4651
+ {
4652
+ this.endSelection();
4614
4653
 
4615
4654
  // Use main cursor
4616
4655
  this._removeSecondaryCursors();
@@ -4632,8 +4671,8 @@ class CodeEditor {
4632
4671
  this.hideAutoCompleteBox();
4633
4672
  }
4634
4673
 
4635
- cursorToRight( key, cursor ) {
4636
-
4674
+ cursorToRight( key, cursor )
4675
+ {
4637
4676
  if( !key ) return;
4638
4677
 
4639
4678
  cursor._left += this.charWidth;
@@ -4651,8 +4690,8 @@ class CodeEditor {
4651
4690
  }
4652
4691
  }
4653
4692
 
4654
- cursorToLeft( key, cursor ) {
4655
-
4693
+ cursorToLeft( key, cursor )
4694
+ {
4656
4695
  if( !key ) return;
4657
4696
 
4658
4697
  cursor._left -= this.charWidth;
@@ -4672,8 +4711,8 @@ class CodeEditor {
4672
4711
  }
4673
4712
  }
4674
4713
 
4675
- cursorToTop( cursor, resetLeft = false ) {
4676
-
4714
+ cursorToTop( cursor, resetLeft = false )
4715
+ {
4677
4716
  cursor._top -= this.lineHeight;
4678
4717
  cursor._top = Math.max( cursor._top, 0 );
4679
4718
  cursor.style.top = `calc(${ cursor._top }px)`;
@@ -4692,8 +4731,8 @@ class CodeEditor {
4692
4731
  }
4693
4732
  }
4694
4733
 
4695
- cursorToBottom( cursor, resetLeft = false ) {
4696
-
4734
+ cursorToBottom( cursor, resetLeft = false )
4735
+ {
4697
4736
  cursor._top += this.lineHeight;
4698
4737
  cursor.style.top = `calc(${ cursor._top }px)`;
4699
4738
 
@@ -4713,8 +4752,8 @@ class CodeEditor {
4713
4752
  }
4714
4753
  }
4715
4754
 
4716
- cursorToString( cursor, text, reverse ) {
4717
-
4755
+ cursorToString( cursor, text, reverse )
4756
+ {
4718
4757
  if( !text.length )
4719
4758
  {
4720
4759
  return;
@@ -4726,23 +4765,23 @@ class CodeEditor {
4726
4765
  }
4727
4766
  }
4728
4767
 
4729
- cursorToPosition( cursor, position ) {
4730
-
4768
+ cursorToPosition( cursor, position )
4769
+ {
4731
4770
  cursor.position = position;
4732
4771
  cursor._left = position * this.charWidth;
4733
4772
  cursor.style.left = `calc( ${ cursor._left }px + ${ this.xPadding } )`;
4734
4773
  }
4735
4774
 
4736
- cursorToLine( cursor, line, resetLeft = false ) {
4737
-
4775
+ cursorToLine( cursor, line, resetLeft = false )
4776
+ {
4738
4777
  cursor.line = line;
4739
4778
  cursor._top = this.lineHeight * line;
4740
4779
  cursor.style.top = cursor._top + "px";
4741
4780
  if( resetLeft ) this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
4742
4781
  }
4743
4782
 
4744
- saveCursor( cursor, state = {} ) {
4745
-
4783
+ saveCursor( cursor, state = {} )
4784
+ {
4746
4785
  state.position = cursor.position;
4747
4786
  state.line = cursor.line;
4748
4787
  state.selection = cursor.selection ? cursor.selection.save() : undefined;
@@ -4750,8 +4789,8 @@ class CodeEditor {
4750
4789
  return state;
4751
4790
  }
4752
4791
 
4753
- saveCursors() {
4754
-
4792
+ saveCursors()
4793
+ {
4755
4794
  var cursors = [];
4756
4795
 
4757
4796
  for( let cursor of this.cursors.children )
@@ -4762,8 +4801,8 @@ class CodeEditor {
4762
4801
  return cursors;
4763
4802
  }
4764
4803
 
4765
- getCurrentCursor( removeOthers ) {
4766
-
4804
+ getCurrentCursor( removeOthers )
4805
+ {
4767
4806
  if( removeOthers )
4768
4807
  {
4769
4808
  this._removeSecondaryCursors();
@@ -4772,8 +4811,8 @@ class CodeEditor {
4772
4811
  return this.cursors.children[ 0 ];
4773
4812
  }
4774
4813
 
4775
- relocateCursors() {
4776
-
4814
+ relocateCursors()
4815
+ {
4777
4816
  for( let cursor of this.cursors.children )
4778
4817
  {
4779
4818
  cursor._left = cursor.position * this.charWidth;
@@ -4783,8 +4822,8 @@ class CodeEditor {
4783
4822
  }
4784
4823
  }
4785
4824
 
4786
- mergeCursors( line ) {
4787
-
4825
+ mergeCursors( line )
4826
+ {
4788
4827
  console.assert( line >= 0 );
4789
4828
  const cursorsInLine = Array.from( this.cursors.children ).filter( v => v.line == line );
4790
4829
 
@@ -4792,8 +4831,8 @@ class CodeEditor {
4792
4831
  this.removeCursor( cursorsInLine.pop() );
4793
4832
  }
4794
4833
 
4795
- restoreCursor( cursor, state ) {
4796
-
4834
+ restoreCursor( cursor, state )
4835
+ {
4797
4836
  cursor.position = state.position ?? 0;
4798
4837
  cursor.line = state.line ?? 0;
4799
4838
 
@@ -4814,15 +4853,15 @@ class CodeEditor {
4814
4853
  }
4815
4854
  }
4816
4855
 
4817
- removeCursor( cursor ) {
4818
-
4856
+ removeCursor( cursor )
4857
+ {
4819
4858
  LX.deleteElement( this.selections[ cursor.name ] );
4820
4859
  delete this.selections[ cursor.name ];
4821
4860
  LX.deleteElement( cursor );
4822
4861
  }
4823
4862
 
4824
- resetCursorPos( flag, cursor ) {
4825
-
4863
+ resetCursorPos( flag, cursor )
4864
+ {
4826
4865
  cursor = cursor ?? this.getCurrentCursor();
4827
4866
 
4828
4867
  if( flag & CodeEditor.CURSOR_LEFT )
@@ -4840,8 +4879,8 @@ class CodeEditor {
4840
4879
  }
4841
4880
  }
4842
4881
 
4843
- _addCursor( line = 0, position = 0, force, isMain = false ) {
4844
-
4882
+ _addCursor( line = 0, position = 0, force, isMain = false )
4883
+ {
4845
4884
  // If cursor in that position exists, remove it instead..
4846
4885
  const exists = Array.from( this.cursors.children ).find( v => v.position == position && v.line == line );
4847
4886
  if( exists && !force )
@@ -4891,30 +4930,42 @@ class CodeEditor {
4891
4930
  return cursor;
4892
4931
  }
4893
4932
 
4894
- _removeSecondaryCursors() {
4895
-
4933
+ _removeSecondaryCursors()
4934
+ {
4896
4935
  while( this.cursors.childElementCount > 1 )
4936
+ {
4897
4937
  this.cursors.lastChild.remove();
4938
+ }
4939
+ }
4940
+
4941
+ _getLastCursor()
4942
+ {
4943
+ return this.cursors.lastChild;
4898
4944
  }
4899
4945
 
4900
- _logCursors() {
4946
+ _isLastCursor( cursor )
4947
+ {
4948
+ return cursor === this._getLastCursor();
4949
+ }
4901
4950
 
4951
+ _logCursors()
4952
+ {
4902
4953
  for( let cursor of this.cursors.children )
4903
4954
  {
4904
4955
  cursor.print();
4905
4956
  }
4906
4957
  }
4907
4958
 
4908
- _addSpaceTabs( cursor, n ) {
4909
-
4959
+ _addSpaceTabs( cursor, n )
4960
+ {
4910
4961
  for( var i = 0; i < n; ++i )
4911
4962
  {
4912
4963
  this.actions[ 'Tab' ].callback( cursor.line, cursor, null );
4913
4964
  }
4914
4965
  }
4915
4966
 
4916
- _addSpaces( n ) {
4917
-
4967
+ _addSpaces( n )
4968
+ {
4918
4969
  for( var i = 0; i < n; ++i )
4919
4970
  {
4920
4971
  this.root.dispatchEvent( new CustomEvent( 'keydown', { 'detail': {
@@ -4925,8 +4976,8 @@ class CodeEditor {
4925
4976
  }
4926
4977
  }
4927
4978
 
4928
- _removeSpaces( cursor ) {
4929
-
4979
+ _removeSpaces( cursor )
4980
+ {
4930
4981
  const lidx = cursor.line;
4931
4982
 
4932
4983
  // Remove indentation
@@ -4965,17 +5016,20 @@ class CodeEditor {
4965
5016
  }
4966
5017
  }
4967
5018
 
4968
- getScrollLeft() {
5019
+ getScrollLeft()
5020
+ {
4969
5021
  if( !this.codeScroller ) return 0;
4970
5022
  return this.codeScroller.scrollLeft;
4971
5023
  }
4972
5024
 
4973
- getScrollTop() {
5025
+ getScrollTop()
5026
+ {
4974
5027
  if( !this.codeScroller ) return 0;
4975
5028
  return this.codeScroller.scrollTop;
4976
5029
  }
4977
5030
 
4978
- setScrollLeft( value ) {
5031
+ setScrollLeft( value )
5032
+ {
4979
5033
  if( !this.codeScroller ) return;
4980
5034
  LX.doAsync( () => {
4981
5035
  this.codeScroller.scrollLeft = value;
@@ -4983,7 +5037,8 @@ class CodeEditor {
4983
5037
  }, 20 );
4984
5038
  }
4985
5039
 
4986
- setScrollTop( value ) {
5040
+ setScrollTop( value )
5041
+ {
4987
5042
  if( !this.codeScroller ) return;
4988
5043
  LX.doAsync( () => {
4989
5044
  this.codeScroller.scrollTop = value;
@@ -4991,8 +5046,8 @@ class CodeEditor {
4991
5046
  }, 20 );
4992
5047
  }
4993
5048
 
4994
- resize( flag = CodeEditor.RESIZE_SCROLLBAR_H_V, pMaxLength, onResize ) {
4995
-
5049
+ resize( flag = CodeEditor.RESIZE_SCROLLBAR_H_V, pMaxLength, onResize )
5050
+ {
4996
5051
  setTimeout( () => {
4997
5052
 
4998
5053
  let scrollWidth, scrollHeight;
@@ -5022,8 +5077,8 @@ class CodeEditor {
5022
5077
  }, 10 );
5023
5078
  }
5024
5079
 
5025
- resizeIfNecessary( cursor, force ) {
5026
-
5080
+ resizeIfNecessary( cursor, force )
5081
+ {
5027
5082
  const maxLineLength = this.getMaxLineLength();
5028
5083
  const numViewportChars = Math.floor( ( this.codeScroller.clientWidth - CodeEditor.LINE_GUTTER_WIDTH ) / this.charWidth );
5029
5084
  if( force || ( maxLineLength >= numViewportChars && maxLineLength != this._lastMaxLineLength ) )
@@ -5037,8 +5092,8 @@ class CodeEditor {
5037
5092
  }
5038
5093
  }
5039
5094
 
5040
- resizeScrollBars( flag = CodeEditor.RESIZE_SCROLLBAR_H_V ) {
5041
-
5095
+ resizeScrollBars( flag = CodeEditor.RESIZE_SCROLLBAR_H_V )
5096
+ {
5042
5097
  if( flag & CodeEditor.RESIZE_SCROLLBAR_V )
5043
5098
  {
5044
5099
  const totalLinesInViewport = (( this.codeScroller.offsetHeight ) / this.lineHeight)|0;
@@ -5071,8 +5126,8 @@ class CodeEditor {
5071
5126
  }
5072
5127
  }
5073
5128
 
5074
- setScrollBarValue( type = 'vertical', value ) {
5075
-
5129
+ setScrollBarValue( type = 'vertical', value )
5130
+ {
5076
5131
  if( type == 'vertical' )
5077
5132
  {
5078
5133
  const scrollBarHeight = this.vScrollbar.thumb.parentElement.offsetHeight;
@@ -5102,8 +5157,8 @@ class CodeEditor {
5102
5157
  }
5103
5158
  }
5104
5159
 
5105
- updateHorizontalScrollFromScrollBar( value ) {
5106
-
5160
+ updateHorizontalScrollFromScrollBar( value )
5161
+ {
5107
5162
  value = this.hScrollbar.thumb._left - value;
5108
5163
 
5109
5164
  // Move scrollbar thumb
@@ -5124,8 +5179,8 @@ class CodeEditor {
5124
5179
  this._discardScroll = true;
5125
5180
  }
5126
5181
 
5127
- updateVerticalScrollFromScrollBar( value ) {
5128
-
5182
+ updateVerticalScrollFromScrollBar( value )
5183
+ {
5129
5184
  value = this.vScrollbar.thumb._top - value;
5130
5185
 
5131
5186
  // Move scrollbar thumb
@@ -5143,12 +5198,13 @@ class CodeEditor {
5143
5198
  this.codeScroller.scrollTop = currentScroll;
5144
5199
  }
5145
5200
 
5146
- getCharAtPos( cursor, offset = 0 ) {
5201
+ getCharAtPos( cursor, offset = 0 )
5202
+ {
5147
5203
  return this.code.lines[ cursor.line ][ cursor.position + offset ];
5148
5204
  }
5149
5205
 
5150
- getWordAtPos( cursor, offset = 0 ) {
5151
-
5206
+ getWordAtPos( cursor, offset = 0 )
5207
+ {
5152
5208
  const col = cursor.line;
5153
5209
  const words = this.code.lines[ col ];
5154
5210
 
@@ -5197,7 +5253,8 @@ class CodeEditor {
5197
5253
  return [ word, from, to ];
5198
5254
  }
5199
5255
 
5200
- _measureChar( char = "a", useFloating = false, getBB = false ) {
5256
+ _measureChar( char = "a", useFloating = false, getBB = false )
5257
+ {
5201
5258
  const parentContainer = LX.makeContainer( null, "lexcodeeditor", "", document.body );
5202
5259
  const container = LX.makeContainer( null, "code", "", parentContainer );
5203
5260
  const line = document.createElement( "pre" );
@@ -5211,12 +5268,13 @@ class CodeEditor {
5211
5268
  return getBB ? bb : bb[ 0 ];
5212
5269
  }
5213
5270
 
5214
- measureString( str ) {
5271
+ measureString( str )
5272
+ {
5215
5273
  return str.length * this.charWidth;
5216
5274
  }
5217
5275
 
5218
- runScript( code ) {
5219
-
5276
+ runScript( code )
5277
+ {
5220
5278
  const script = document.createElement( 'script' );
5221
5279
  script.type = 'module';
5222
5280
  script.innerHTML = code;
@@ -5226,8 +5284,8 @@ class CodeEditor {
5226
5284
  document.getElementsByTagName( 'head' )[ 0 ].appendChild( script );
5227
5285
  }
5228
5286
 
5229
- toJSONFormat( text ) {
5230
-
5287
+ toJSONFormat( text )
5288
+ {
5231
5289
  let params = text.split( ':' );
5232
5290
 
5233
5291
  for(let i = 0; i < params.length; i++) {
@@ -5261,8 +5319,8 @@ class CodeEditor {
5261
5319
  }
5262
5320
  }
5263
5321
 
5264
- showAutoCompleteBox( key, cursor ) {
5265
-
5322
+ showAutoCompleteBox( key, cursor )
5323
+ {
5266
5324
  if( !cursor.isMain )
5267
5325
  {
5268
5326
  return;
@@ -5355,7 +5413,6 @@ class CodeEditor {
5355
5413
  }
5356
5414
 
5357
5415
  pre.appendChild( LX.makeIcon( iconName, { iconClass: "mr-1", svgClass: "sm " + iconClass } ) );
5358
- s
5359
5416
  pre.addEventListener( 'click', () => {
5360
5417
  this.autoCompleteWord( s );
5361
5418
  } );
@@ -5395,8 +5452,8 @@ s
5395
5452
  this.isAutoCompleteActive = true;
5396
5453
  }
5397
5454
 
5398
- hideAutoCompleteBox() {
5399
-
5455
+ hideAutoCompleteBox()
5456
+ {
5400
5457
  if( !this.autocomplete )
5401
5458
  {
5402
5459
  return;
@@ -5410,8 +5467,8 @@ s
5410
5467
  return isActive != this.isAutoCompleteActive;
5411
5468
  }
5412
5469
 
5413
- autoCompleteWord( suggestion ) {
5414
-
5470
+ autoCompleteWord( suggestion )
5471
+ {
5415
5472
  if( !this.isAutoCompleteActive )
5416
5473
  return;
5417
5474
 
@@ -5437,8 +5494,8 @@ s
5437
5494
  this.hideAutoCompleteBox();
5438
5495
  }
5439
5496
 
5440
- _getSelectedAutoComplete() {
5441
-
5497
+ _getSelectedAutoComplete()
5498
+ {
5442
5499
  if( !this.isAutoCompleteActive )
5443
5500
  {
5444
5501
  return;
@@ -5464,18 +5521,21 @@ s
5464
5521
  }
5465
5522
  }
5466
5523
 
5467
- _moveArrowSelectedAutoComplete( dir ) {
5468
-
5524
+ _moveArrowSelectedAutoComplete( dir )
5525
+ {
5469
5526
  if( !this.isAutoCompleteActive )
5470
- return;
5527
+ return;
5471
5528
 
5472
- const [word, idx] = this._getSelectedAutoComplete();
5529
+ const [ word, idx ] = this._getSelectedAutoComplete();
5473
5530
  const offset = dir == 'down' ? 1 : -1;
5474
5531
 
5475
- if( dir == 'down' ) {
5476
- if( (idx + offset) >= this.autocomplete.childElementCount ) return;
5477
- } else if( dir == 'up') {
5478
- if( (idx + offset) < 0 ) return;
5532
+ if( dir == 'down' )
5533
+ {
5534
+ if( ( idx + offset ) >= this.autocomplete.childElementCount ) return;
5535
+ }
5536
+ else if( dir == 'up')
5537
+ {
5538
+ if( ( idx + offset ) < 0 ) return;
5479
5539
  }
5480
5540
 
5481
5541
  this.autocomplete.scrollTop += offset * 20;
@@ -5485,8 +5545,8 @@ s
5485
5545
  this.autocomplete.childNodes[ idx + offset ].classList.add('selected');
5486
5546
  }
5487
5547
 
5488
- showSearchBox( clear ) {
5489
-
5548
+ showSearchBox( clear )
5549
+ {
5490
5550
  this.hideSearchLineBox();
5491
5551
 
5492
5552
  this.searchbox.classList.add( 'opened' );
@@ -5514,8 +5574,8 @@ s
5514
5574
  input.focus();
5515
5575
  }
5516
5576
 
5517
- hideSearchBox() {
5518
-
5577
+ hideSearchBox()
5578
+ {
5519
5579
  const active = this.searchboxActive;
5520
5580
 
5521
5581
  if( this.searchboxActive )
@@ -5532,11 +5592,11 @@ s
5532
5592
 
5533
5593
  this.searchResultSelections.classList.remove( 'show' );
5534
5594
 
5535
- return active != this.searchboxActive;
5595
+ return ( active != this.searchboxActive );
5536
5596
  }
5537
5597
 
5538
- search( text, reverse, callback, skipAlert ) {
5539
-
5598
+ search( text, reverse, callback, skipAlert, forceFocus = true )
5599
+ {
5540
5600
  text = text ?? this._lastTextFound;
5541
5601
 
5542
5602
  if( !text )
@@ -5658,12 +5718,15 @@ s
5658
5718
  };
5659
5719
 
5660
5720
  // Force focus back to search box
5661
- const input = this.searchbox.querySelector( 'input' );
5662
- input.focus();
5721
+ if( forceFocus )
5722
+ {
5723
+ const input = this.searchbox.querySelector( 'input' );
5724
+ input.focus();
5725
+ }
5663
5726
  }
5664
5727
 
5665
- showSearchLineBox() {
5666
-
5728
+ showSearchLineBox()
5729
+ {
5667
5730
  this.hideSearchBox();
5668
5731
 
5669
5732
  this.searchlinebox.classList.add( 'opened' );
@@ -5674,8 +5737,8 @@ s
5674
5737
  input.focus();
5675
5738
  }
5676
5739
 
5677
- hideSearchLineBox() {
5678
-
5740
+ hideSearchLineBox()
5741
+ {
5679
5742
  if( this.searchlineboxActive )
5680
5743
  {
5681
5744
  this.searchlinebox.classList.remove( 'opened' );
@@ -5683,8 +5746,8 @@ s
5683
5746
  }
5684
5747
  }
5685
5748
 
5686
- goToLine( line ) {
5687
-
5749
+ goToLine( line )
5750
+ {
5688
5751
  if( !this._isNumber( line ) )
5689
5752
  return;
5690
5753
 
@@ -5695,8 +5758,8 @@ s
5695
5758
  this.cursorToLine( cursor, line - 1, true );
5696
5759
  }
5697
5760
 
5698
- selectNextOcurrence( cursor ) {
5699
-
5761
+ selectNextOcurrence( cursor )
5762
+ {
5700
5763
  if( !cursor.selection )
5701
5764
  return;
5702
5765
 
@@ -5711,11 +5774,12 @@ s
5711
5774
  this._currentOcurrences[ currentKey ] = true;
5712
5775
  }
5713
5776
 
5714
- this.search( text, false, (col, ln) => {
5777
+ this.search( text, false, ( col, ln ) => {
5715
5778
 
5716
5779
  const key = [ col, ln ].join( '_' );
5717
5780
 
5718
- if( this._currentOcurrences[ key ] ) {
5781
+ if( this._currentOcurrences[ key ] )
5782
+ {
5719
5783
  return;
5720
5784
  }
5721
5785
 
@@ -5726,11 +5790,11 @@ s
5726
5790
 
5727
5791
  this._currentOcurrences[ key ] = true;
5728
5792
 
5729
- }, true );
5793
+ }, true, false );
5730
5794
  }
5731
5795
 
5732
- _updateDataInfoPanel( signal, value ) {
5733
-
5796
+ _updateDataInfoPanel( signal, value )
5797
+ {
5734
5798
  if( !this.skipInfo )
5735
5799
  {
5736
5800
  if( this.cursors.childElementCount > 1 )
@@ -5742,8 +5806,8 @@ s
5742
5806
  }
5743
5807
  }
5744
5808
 
5745
- _setActiveLine( number ) {
5746
-
5809
+ _setActiveLine( number )
5810
+ {
5747
5811
  number = number ?? this.state.activeLine;
5748
5812
 
5749
5813
  const cursor = this.getCurrentCursor();
@@ -5769,11 +5833,13 @@ s
5769
5833
  }
5770
5834
  }
5771
5835
 
5772
- _hideActiveLine() {
5836
+ _hideActiveLine()
5837
+ {
5773
5838
  this.code.querySelectorAll( '.active-line' ).forEach( e => e.classList.remove( 'active-line' ) );
5774
5839
  }
5775
5840
 
5776
- _setFontSize( size ) {
5841
+ _setFontSize( size )
5842
+ {
5777
5843
  // Change font size
5778
5844
  this.fontSize = size;
5779
5845
  const r = document.querySelector( ':root' );
@@ -5797,20 +5863,24 @@ s
5797
5863
  LX.emit( "@font-size", this.fontSize );
5798
5864
  }
5799
5865
 
5800
- _applyFontSizeOffset( offset = 0 ) {
5866
+ _applyFontSizeOffset( offset = 0 )
5867
+ {
5801
5868
  const newFontSize = LX.clamp( this.fontSize + offset, CodeEditor.CODE_MIN_FONT_SIZE, CodeEditor.CODE_MAX_FONT_SIZE );
5802
5869
  this._setFontSize( newFontSize );
5803
5870
  }
5804
5871
 
5805
- _increaseFontSize() {
5872
+ _increaseFontSize()
5873
+ {
5806
5874
  this._applyFontSizeOffset( 1 );
5807
5875
  }
5808
5876
 
5809
- _decreaseFontSize() {
5877
+ _decreaseFontSize()
5878
+ {
5810
5879
  this._applyFontSizeOffset( -1 );
5811
5880
  }
5812
5881
 
5813
- _clearTmpVariables() {
5882
+ _clearTmpVariables()
5883
+ {
5814
5884
  delete this._currentLineString;
5815
5885
  delete this._currentLineNumber;
5816
5886
  delete this._buildingString;
@@ -5821,7 +5891,8 @@ s
5821
5891
  delete this._scopeStack;
5822
5892
  }
5823
5893
 
5824
- async _requestFileAsync( url, dataType, nocache ) {
5894
+ async _requestFileAsync( url, dataType, nocache )
5895
+ {
5825
5896
  return new Promise( (resolve, reject) => {
5826
5897
  dataType = dataType ?? "arraybuffer";
5827
5898
  const mimeType = dataType === "arraybuffer" ? "application/octet-stream" : undefined;
@@ -5852,7 +5923,8 @@ s
5852
5923
  }
5853
5924
  }
5854
5925
 
5855
- CodeEditor.languages = {
5926
+ CodeEditor.languages =
5927
+ {
5856
5928
  'Plain Text': { ext: "txt", blockComments: false, singleLineComments: false, numbers: false, icon: "AlignLeft gray" },
5857
5929
  'JavaScript': { ext: "js", icon: "Js goldenrod" },
5858
5930
  'TypeScript': { ext: "ts", icon: "Ts pipelineblue" },
@@ -5872,17 +5944,20 @@ CodeEditor.languages = {
5872
5944
  'PHP': { ext: "php", icon: "Php blueviolet" },
5873
5945
  };
5874
5946
 
5875
- CodeEditor.nativeTypes = {
5947
+ CodeEditor.nativeTypes =
5948
+ {
5876
5949
  'C++': ['int', 'float', 'double', 'bool', 'long', 'short', 'char', 'wchar_t', 'void'],
5877
5950
  'WGSL': ['bool', 'u32', 'i32', 'f16', 'f32', 'vec2', 'vec3', 'vec4', 'vec2f', 'vec3f', 'vec4f', 'mat2x2f', 'mat3x3f', 'mat4x4f', 'array', 'vec2u', 'vec3u', 'vec4u', 'ptr', 'sampler']
5878
5951
  };
5879
5952
 
5880
- CodeEditor.declarationKeywords = {
5953
+ CodeEditor.declarationKeywords =
5954
+ {
5881
5955
  'JavaScript': ['var', 'let', 'const', 'this', 'static', 'class'],
5882
5956
  'C++': [...CodeEditor.nativeTypes["C++"], 'const', 'auto', 'class', 'struct', 'namespace', 'enum', 'extern']
5883
5957
  };
5884
5958
 
5885
- CodeEditor.keywords = {
5959
+ CodeEditor.keywords =
5960
+ {
5886
5961
  'JavaScript': ['var', 'let', 'const', 'this', 'in', 'of', 'true', 'false', 'new', 'function', 'NaN', 'static', 'class', 'constructor', 'null', 'typeof', 'debugger', 'abstract',
5887
5962
  'arguments', 'extends', 'instanceof', 'Infinity'],
5888
5963
  'TypeScript': ['var', 'let', 'const', 'this', 'in', 'of', 'true', 'false', 'new', 'function', 'class', 'extends', 'instanceof', 'Infinity', 'private', 'public', 'protected', 'interface',
@@ -5911,7 +5986,9 @@ CodeEditor.keywords = {
5911
5986
  'enum'],
5912
5987
  };
5913
5988
 
5914
- CodeEditor.utils = { // These ones don't have hightlight, used as suggestions to autocomplete only...
5989
+ // These ones don't have hightlight, used as suggestions to autocomplete only...
5990
+ CodeEditor.utils =
5991
+ {
5915
5992
  'JavaScript': ['querySelector', 'body', 'addEventListener', 'removeEventListener', 'remove', 'sort', 'keys', 'filter', 'isNaN', 'parseFloat', 'parseInt', 'EPSILON', 'isFinite',
5916
5993
  'bind', 'prototype', 'length', 'assign', 'entries', 'values', 'concat', 'substring', 'substr', 'splice', 'slice', 'buffer', 'appendChild', 'createElement', 'prompt',
5917
5994
  'alert'],
@@ -5929,7 +6006,8 @@ CodeEditor.utils = { // These ones don't have hightlight, used as suggestions to
5929
6006
  'lime', 'teal', 'navy', 'transparent', 'currentcolor', 'inherit', 'initial', 'unset', 'revert', 'none', 'auto', 'fit-content', 'min-content', 'max-content']
5930
6007
  };
5931
6008
 
5932
- CodeEditor.types = {
6009
+ CodeEditor.types =
6010
+ {
5933
6011
  'JavaScript': ['Object', 'String', 'Function', 'Boolean', 'Symbol', 'Error', 'Number', 'TextEncoder', 'TextDecoder', 'Array', 'ArrayBuffer', 'InputEvent', 'MouseEvent',
5934
6012
  'Int8Array', 'Int16Array', 'Int32Array', 'Float32Array', 'Float64Array', 'Element'],
5935
6013
  'TypeScript': ['arguments', 'constructor', 'null', 'typeof', 'debugger', 'abstract', 'Object', 'string', 'String', 'Function', 'Boolean', 'boolean', 'Error', 'Number', 'number', 'TextEncoder',
@@ -5943,7 +6021,8 @@ CodeEditor.types = {
5943
6021
  'PHP': ['Exception', 'DateTime', 'JsonSerializable'],
5944
6022
  };
5945
6023
 
5946
- CodeEditor.builtIn = {
6024
+ CodeEditor.builtIn =
6025
+ {
5947
6026
  'JavaScript': ['document', 'console', 'window', 'navigator', 'performance'],
5948
6027
  'CSS': ['*', '!important'],
5949
6028
  'C++': ['vector', 'list', 'map'],
@@ -5953,7 +6032,8 @@ CodeEditor.builtIn = {
5953
6032
  'PHP': ['echo', 'print'],
5954
6033
  };
5955
6034
 
5956
- CodeEditor.statements = {
6035
+ CodeEditor.statements =
6036
+ {
5957
6037
  'JavaScript': ['for', 'if', 'else', 'case', 'switch', 'return', 'while', 'continue', 'break', 'do', 'import', 'from', 'throw', 'async', 'try', 'catch', 'await'],
5958
6038
  'TypeScript': ['for', 'if', 'else', 'case', 'switch', 'return', 'while', 'continue', 'break', 'do', 'import', 'from', 'throw', 'async', 'try', 'catch', 'await', 'as'],
5959
6039
  'CSS': ['@', 'import'],
@@ -5969,7 +6049,8 @@ CodeEditor.statements = {
5969
6049
  'try', 'catch', 'die', 'do', 'exit', 'finally'],
5970
6050
  };
5971
6051
 
5972
- CodeEditor.symbols = {
6052
+ CodeEditor.symbols =
6053
+ {
5973
6054
  'JavaScript': ['<', '>', '[', ']', '{', '}', '(', ')', ';', '=', '|', '||', '&', '&&', '?', '??'],
5974
6055
  'TypeScript': ['<', '>', '[', ']', '{', '}', '(', ')', ';', '=', '|', '||', '&', '&&', '?', '??'],
5975
6056
  'C': ['<', '>', '[', ']', '{', '}', '(', ')', ';', '=', '|', '||', '&', '&&', '?', '*', '-', '+'],