lexgui 0.1.22 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/codeeditor.js +229 -137
- package/build/lexgui.css +30 -3
- package/build/lexgui.js +1 -1
- package/build/lexgui.module.js +1 -1
- package/changelog.md +9 -0
- package/examples/code_editor.html +12 -9
- package/package.json +1 -1
|
@@ -201,8 +201,8 @@ class CodeEditor {
|
|
|
201
201
|
static WORD_TYPE_METHOD = 0;
|
|
202
202
|
static WORD_TYPE_CLASS = 1;
|
|
203
203
|
|
|
204
|
-
static CODE_MAX_FONT_SIZE =
|
|
205
|
-
static CODE_MIN_FONT_SIZE =
|
|
204
|
+
static CODE_MAX_FONT_SIZE = 22;
|
|
205
|
+
static CODE_MIN_FONT_SIZE = 9;
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
208
|
* @param {*} options
|
|
@@ -333,42 +333,15 @@ class CodeEditor {
|
|
|
333
333
|
|
|
334
334
|
// Add main cursor
|
|
335
335
|
{
|
|
336
|
-
|
|
337
|
-
cursor.className = "cursor";
|
|
338
|
-
cursor.innerHTML = " ";
|
|
339
|
-
cursor._left = 0;
|
|
340
|
-
cursor.style.left = this.xPadding;
|
|
341
|
-
cursor._top = 0;
|
|
342
|
-
cursor.style.top = cursor._top + "px";
|
|
343
|
-
cursor._position = 0;
|
|
344
|
-
cursor._line = 0;
|
|
345
|
-
cursor.print = (function() { console.log( this.line, this.position ) }).bind( cursor );
|
|
336
|
+
this._addCursor( 0, 0, true );
|
|
346
337
|
|
|
347
338
|
Object.defineProperty( this, 'line', {
|
|
348
|
-
get: (v) => { return
|
|
339
|
+
get: (v) => { return this._getCurrentCursor().line }
|
|
349
340
|
} );
|
|
350
|
-
|
|
341
|
+
|
|
351
342
|
Object.defineProperty( this, 'position', {
|
|
352
|
-
get: (v) => { return
|
|
353
|
-
} );
|
|
354
|
-
|
|
355
|
-
Object.defineProperty( cursor, 'line', {
|
|
356
|
-
get: (v) => { return this._line },
|
|
357
|
-
set: (v) => {
|
|
358
|
-
this._line = v;
|
|
359
|
-
this._setActiveLine( v );
|
|
360
|
-
}
|
|
343
|
+
get: (v) => { return this._getCurrentCursor().position }
|
|
361
344
|
} );
|
|
362
|
-
|
|
363
|
-
Object.defineProperty( cursor, 'position', {
|
|
364
|
-
get: (v) => { return this._position },
|
|
365
|
-
set: (v) => {
|
|
366
|
-
this._position = v;
|
|
367
|
-
this._updateDataInfoPanel( "@cursor-pos", "Col " + v );
|
|
368
|
-
}
|
|
369
|
-
} );
|
|
370
|
-
|
|
371
|
-
this.cursors.appendChild( cursor );
|
|
372
345
|
}
|
|
373
346
|
|
|
374
347
|
// Scroll stuff
|
|
@@ -534,6 +507,7 @@ class CodeEditor {
|
|
|
534
507
|
this.tabSpaces = 4;
|
|
535
508
|
this.maxUndoSteps = 16;
|
|
536
509
|
this.lineHeight = 20;
|
|
510
|
+
this.charWidth = 7; // To update later depending on size..
|
|
537
511
|
this.defaultSingleLineCommentToken = '//';
|
|
538
512
|
this.defaultBlockCommentTokens = [ '/*', '*/' ];
|
|
539
513
|
this._lastTime = null;
|
|
@@ -624,6 +598,7 @@ class CodeEditor {
|
|
|
624
598
|
};
|
|
625
599
|
this.statementsAndDeclarations = {
|
|
626
600
|
'JavaScript': ['for', 'if', 'else', 'case', 'switch', 'return', 'while', 'continue', 'break', 'do', 'import', 'from', 'throw', 'async', 'try', 'catch', 'await'],
|
|
601
|
+
'CSS': ['@', 'import'],
|
|
627
602
|
'C++': ['std', 'for', 'if', 'else', 'return', 'continue', 'break', 'case', 'switch', 'while', 'using', 'glm', 'spdlog'],
|
|
628
603
|
'GLSL': ['for', 'if', 'else', 'return', 'continue', 'break'],
|
|
629
604
|
'WGSL': ['const','for', 'if', 'else', 'return', 'continue', 'break', 'storage', 'read', 'uniform'],
|
|
@@ -659,6 +634,7 @@ class CodeEditor {
|
|
|
659
634
|
this.action( 'Escape', false, ( ln, cursor, e ) => {
|
|
660
635
|
this.hideAutoCompleteBox();
|
|
661
636
|
this.hideSearchBox();
|
|
637
|
+
this._removeSecondaryCursors();
|
|
662
638
|
});
|
|
663
639
|
|
|
664
640
|
this.action( 'Backspace', false, ( ln, cursor, e ) => {
|
|
@@ -704,7 +680,7 @@ class CodeEditor {
|
|
|
704
680
|
}
|
|
705
681
|
else if( this.code.lines[ ln - 1 ] != undefined ) {
|
|
706
682
|
|
|
707
|
-
this.lineUp();
|
|
683
|
+
this.lineUp( cursor );
|
|
708
684
|
e.cancelShift = true;
|
|
709
685
|
this.actions[ 'End' ].callback( cursor.line, cursor, e );
|
|
710
686
|
// Move line on top
|
|
@@ -759,7 +735,7 @@ class CodeEditor {
|
|
|
759
735
|
const prestring = this.code.lines[ ln ].substring( 0, idx );
|
|
760
736
|
let lastX = cursor.position;
|
|
761
737
|
|
|
762
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT );
|
|
738
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
763
739
|
if(idx > 0) this.cursorToString( cursor, prestring );
|
|
764
740
|
this.setScrollLeft( 0 );
|
|
765
741
|
|
|
@@ -793,14 +769,14 @@ class CodeEditor {
|
|
|
793
769
|
this.selection.selectInline(cursor.position, cursor.line, this.measureString( string ));
|
|
794
770
|
else
|
|
795
771
|
{
|
|
796
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT );
|
|
772
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
797
773
|
this.cursorToString( cursor, this.code.lines[ ln ] );
|
|
798
774
|
this.processSelection( e );
|
|
799
775
|
}
|
|
800
776
|
} else if( !e.keepSelection )
|
|
801
777
|
this.endSelection();
|
|
802
778
|
|
|
803
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT );
|
|
779
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
804
780
|
this.cursorToString( cursor, this.code.lines[ ln ] );
|
|
805
781
|
|
|
806
782
|
const last_char = ( this.code.clientWidth / this.charWidth )|0;
|
|
@@ -856,7 +832,7 @@ class CodeEditor {
|
|
|
856
832
|
if( !this.selection )
|
|
857
833
|
this.startSelection( cursor );
|
|
858
834
|
|
|
859
|
-
this.lineUp();
|
|
835
|
+
this.lineUp( cursor );
|
|
860
836
|
|
|
861
837
|
var letter = this.getCharAtPos( cursor );
|
|
862
838
|
if( !letter ) {
|
|
@@ -867,7 +843,7 @@ class CodeEditor {
|
|
|
867
843
|
|
|
868
844
|
} else {
|
|
869
845
|
this.endSelection();
|
|
870
|
-
this.lineUp();
|
|
846
|
+
this.lineUp( cursor );
|
|
871
847
|
// Go to end of line if out of line
|
|
872
848
|
var letter = this.getCharAtPos( cursor );
|
|
873
849
|
if( !letter ) this.actions['End'].callback( cursor.line, cursor, e );
|
|
@@ -960,7 +936,7 @@ class CodeEditor {
|
|
|
960
936
|
}
|
|
961
937
|
else {
|
|
962
938
|
this.selection.invertIfNecessary();
|
|
963
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP );
|
|
939
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP, cursor );
|
|
964
940
|
this.cursorToLine( cursor, this.selection.fromY, true );
|
|
965
941
|
this.cursorToPosition( cursor, this.selection.fromX );
|
|
966
942
|
this.endSelection();
|
|
@@ -986,7 +962,7 @@ class CodeEditor {
|
|
|
986
962
|
|
|
987
963
|
// Nothing to do..
|
|
988
964
|
if( cursor.line == this.code.lines.length - 1 &&
|
|
989
|
-
cursor.position == this.code.lines[ cursor.line
|
|
965
|
+
cursor.position == this.code.lines[ cursor.line ].length )
|
|
990
966
|
return;
|
|
991
967
|
|
|
992
968
|
if( e.metaKey ) { // Apple devices (Command)
|
|
@@ -1002,7 +978,7 @@ class CodeEditor {
|
|
|
1002
978
|
// Selections...
|
|
1003
979
|
if( e.shiftKey ) { if( !this.selection ) this.startSelection( cursor ); }
|
|
1004
980
|
else this.endSelection();
|
|
1005
|
-
this.cursorToString( cursor, substr);
|
|
981
|
+
this.cursorToString( cursor, substr );
|
|
1006
982
|
if( e.shiftKey ) this.processSelection( e );
|
|
1007
983
|
} else {
|
|
1008
984
|
var letter = this.getCharAtPos( cursor );
|
|
@@ -1020,7 +996,7 @@ class CodeEditor {
|
|
|
1020
996
|
else
|
|
1021
997
|
{
|
|
1022
998
|
this.selection.invertIfNecessary();
|
|
1023
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP );
|
|
999
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP, cursor );
|
|
1024
1000
|
this.cursorToLine( cursor, this.selection.toY );
|
|
1025
1001
|
this.cursorToPosition( cursor, this.selection.toX );
|
|
1026
1002
|
this.endSelection();
|
|
@@ -1106,7 +1082,8 @@ class CodeEditor {
|
|
|
1106
1082
|
}
|
|
1107
1083
|
|
|
1108
1084
|
getText( min ) {
|
|
1109
|
-
|
|
1085
|
+
|
|
1086
|
+
return this.code.lines.join( min ? ' ' : '\n' );
|
|
1110
1087
|
}
|
|
1111
1088
|
|
|
1112
1089
|
// This can be used to empty all text...
|
|
@@ -1115,7 +1092,9 @@ class CodeEditor {
|
|
|
1115
1092
|
let new_lines = text.split( '\n' );
|
|
1116
1093
|
this.code.lines = [].concat( new_lines );
|
|
1117
1094
|
|
|
1118
|
-
|
|
1095
|
+
this._removeSecondaryCursors();
|
|
1096
|
+
|
|
1097
|
+
let cursor = this._getCurrentCursor( true );
|
|
1119
1098
|
let lastLine = new_lines.pop();
|
|
1120
1099
|
|
|
1121
1100
|
this.cursorToLine( cursor, new_lines.length ); // Already substracted 1
|
|
@@ -1128,9 +1107,8 @@ class CodeEditor {
|
|
|
1128
1107
|
}
|
|
1129
1108
|
}
|
|
1130
1109
|
|
|
1131
|
-
appendText( text ) {
|
|
1110
|
+
appendText( text, cursor ) {
|
|
1132
1111
|
|
|
1133
|
-
let cursor = this.cursors.children[ 0 ];
|
|
1134
1112
|
let lidx = cursor.line;
|
|
1135
1113
|
|
|
1136
1114
|
if( this.selection ) {
|
|
@@ -1234,6 +1212,65 @@ class CodeEditor {
|
|
|
1234
1212
|
}
|
|
1235
1213
|
}
|
|
1236
1214
|
|
|
1215
|
+
_addCursor( line = 0, position = 0, isMain = false ) {
|
|
1216
|
+
|
|
1217
|
+
let cursor = document.createElement( 'div' );
|
|
1218
|
+
cursor.className = "cursor";
|
|
1219
|
+
cursor.innerHTML = " ";
|
|
1220
|
+
cursor.isMainCursor = isMain;
|
|
1221
|
+
cursor._left = position * this.charWidth;
|
|
1222
|
+
cursor.style.left = "calc( " + cursor._left + "px + " + this.xPadding + " )";
|
|
1223
|
+
cursor._top = line * this.lineHeight;
|
|
1224
|
+
cursor.style.top = cursor._top + "px";
|
|
1225
|
+
cursor._position = position;
|
|
1226
|
+
cursor._line = line;
|
|
1227
|
+
cursor.print = (function() { console.log( this, this._line, this._position ) }).bind( cursor );
|
|
1228
|
+
|
|
1229
|
+
Object.defineProperty( cursor, 'line', {
|
|
1230
|
+
get: (v) => { return cursor._line },
|
|
1231
|
+
set: (v) => {
|
|
1232
|
+
cursor._line = v;
|
|
1233
|
+
if( cursor.isMainCursor ) this._setActiveLine( v );
|
|
1234
|
+
}
|
|
1235
|
+
} );
|
|
1236
|
+
|
|
1237
|
+
Object.defineProperty( cursor, 'position', {
|
|
1238
|
+
get: (v) => { return cursor._position },
|
|
1239
|
+
set: (v) => {
|
|
1240
|
+
cursor._position = v;
|
|
1241
|
+
if( cursor.isMainCursor ) this._updateDataInfoPanel( "@cursor-pos", "Col " + v );
|
|
1242
|
+
}
|
|
1243
|
+
} );
|
|
1244
|
+
|
|
1245
|
+
this.cursors.appendChild( cursor );
|
|
1246
|
+
|
|
1247
|
+
return cursor;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
_getCurrentCursor( removeOthers ) {
|
|
1251
|
+
|
|
1252
|
+
if( removeOthers )
|
|
1253
|
+
{
|
|
1254
|
+
this._removeSecondaryCursors();
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
return this.cursors.children[ 0 ];
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
_removeSecondaryCursors() {
|
|
1261
|
+
|
|
1262
|
+
while( this.cursors.childElementCount > 1 )
|
|
1263
|
+
this.cursors.lastChild.remove();
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
_logCursors() {
|
|
1267
|
+
|
|
1268
|
+
for( let cursor of this.cursors.children )
|
|
1269
|
+
{
|
|
1270
|
+
cursor.print();
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1237
1274
|
_addUndoStep( cursor, force, deleteRedo = true ) {
|
|
1238
1275
|
|
|
1239
1276
|
const d = new Date();
|
|
@@ -1260,8 +1297,6 @@ class CodeEditor {
|
|
|
1260
1297
|
this.code.redoSteps.length = 0;
|
|
1261
1298
|
}
|
|
1262
1299
|
|
|
1263
|
-
var cursor = cursor ?? this.cursors.children[ 0 ];
|
|
1264
|
-
|
|
1265
1300
|
this.code.undoSteps.push( {
|
|
1266
1301
|
lines: LX.deepCopy( this.code.lines ),
|
|
1267
1302
|
cursor: this.saveCursor( cursor ),
|
|
@@ -1272,8 +1307,6 @@ class CodeEditor {
|
|
|
1272
1307
|
|
|
1273
1308
|
_addRedoStep( cursor ) {
|
|
1274
1309
|
|
|
1275
|
-
var cursor = cursor ?? this.cursors.children[ 0 ];
|
|
1276
|
-
|
|
1277
1310
|
this.code.redoSteps.push( {
|
|
1278
1311
|
lines: LX.deepCopy( this.code.lines ),
|
|
1279
1312
|
cursor: this.saveCursor( cursor ),
|
|
@@ -1374,7 +1407,7 @@ class CodeEditor {
|
|
|
1374
1407
|
ext == 'css' ? "fa-solid fa-hashtag dodgerblue" :
|
|
1375
1408
|
ext == 'xml' ? "fa-solid fa-rss orange" :
|
|
1376
1409
|
ext == 'bat' ? "fa-brands fa-windows lightblue" :
|
|
1377
|
-
[ 'js', 'py', 'json', 'cpp', 'rs' ].indexOf( ext ) > -1 ? "images/" + ext + ".png" :
|
|
1410
|
+
[ 'js', 'py', 'json', 'cpp', 'rs', 'md' ].indexOf( ext ) > -1 ? "images/" + ext + ".png" :
|
|
1378
1411
|
!isNewTabButton ? "fa-solid fa-align-left gray" : undefined;
|
|
1379
1412
|
}
|
|
1380
1413
|
|
|
@@ -1388,7 +1421,7 @@ class CodeEditor {
|
|
|
1388
1421
|
});
|
|
1389
1422
|
}
|
|
1390
1423
|
|
|
1391
|
-
_onSelectTab( isNewTabButton, event, name
|
|
1424
|
+
_onSelectTab( isNewTabButton, event, name ) {
|
|
1392
1425
|
|
|
1393
1426
|
if( isNewTabButton )
|
|
1394
1427
|
{
|
|
@@ -1396,7 +1429,9 @@ class CodeEditor {
|
|
|
1396
1429
|
return;
|
|
1397
1430
|
}
|
|
1398
1431
|
|
|
1399
|
-
|
|
1432
|
+
this._removeSecondaryCursors();
|
|
1433
|
+
var cursor = this._getCurrentCursor( true );
|
|
1434
|
+
|
|
1400
1435
|
this.saveCursor( cursor, this.code.cursorState );
|
|
1401
1436
|
|
|
1402
1437
|
this.code = this.loadedTabs[ name ];
|
|
@@ -1573,12 +1608,12 @@ class CodeEditor {
|
|
|
1573
1608
|
}
|
|
1574
1609
|
}
|
|
1575
1610
|
|
|
1576
|
-
processMouse(e) {
|
|
1611
|
+
processMouse( e ) {
|
|
1577
1612
|
|
|
1578
1613
|
if( !e.target.classList.contains('code') ) return;
|
|
1579
1614
|
if( !this.code ) return;
|
|
1580
1615
|
|
|
1581
|
-
var cursor = this.
|
|
1616
|
+
var cursor = this._getCurrentCursor();
|
|
1582
1617
|
var code_rect = this.code.getBoundingClientRect();
|
|
1583
1618
|
var mouse_pos = [(e.clientX - code_rect.x), (e.clientY - code_rect.y)];
|
|
1584
1619
|
|
|
@@ -1630,7 +1665,7 @@ class CodeEditor {
|
|
|
1630
1665
|
{
|
|
1631
1666
|
case LX.MOUSE_DOUBLE_CLICK:
|
|
1632
1667
|
const [word, from, to] = this.getWordAtPos( cursor );
|
|
1633
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT );
|
|
1668
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
1634
1669
|
this.cursorToPosition( cursor, from );
|
|
1635
1670
|
this.startSelection( cursor );
|
|
1636
1671
|
this.selection.selectInline( from, cursor.line, this.measureString( word ) );
|
|
@@ -1638,7 +1673,7 @@ class CodeEditor {
|
|
|
1638
1673
|
break;
|
|
1639
1674
|
// Select entire line
|
|
1640
1675
|
case LX.MOUSE_TRIPLE_CLICK:
|
|
1641
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT );
|
|
1676
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
1642
1677
|
e._shiftKey = true;
|
|
1643
1678
|
this.actions['End'].callback(cursor.line, cursor, e);
|
|
1644
1679
|
this._tripleClickSelection = true;
|
|
@@ -1654,11 +1689,11 @@ class CodeEditor {
|
|
|
1654
1689
|
return;
|
|
1655
1690
|
|
|
1656
1691
|
LX.addContextMenu( null, e, m => {
|
|
1657
|
-
m.add( "Copy", () => { this._copyContent(); } );
|
|
1692
|
+
m.add( "Copy", () => { this._copyContent( cursor ); } );
|
|
1658
1693
|
if( !this.disableEdition )
|
|
1659
1694
|
{
|
|
1660
|
-
m.add( "Cut", () => { this._cutContent(); } );
|
|
1661
|
-
m.add( "Paste", () => { this._pasteContent(); } );
|
|
1695
|
+
m.add( "Cut", () => { this._cutContent( cursor ); } );
|
|
1696
|
+
m.add( "Paste", () => { this._pasteContent( cursor ); } );
|
|
1662
1697
|
m.add( "" );
|
|
1663
1698
|
m.add( "Format/JSON", () => {
|
|
1664
1699
|
let json = this.toJSONFormat( this.getText() );
|
|
@@ -1690,26 +1725,39 @@ class CodeEditor {
|
|
|
1690
1725
|
|
|
1691
1726
|
processClick( e ) {
|
|
1692
1727
|
|
|
1693
|
-
var cursor = this.
|
|
1728
|
+
var cursor = this._getCurrentCursor();
|
|
1694
1729
|
var code_rect = this.codeScroller.getBoundingClientRect();
|
|
1695
1730
|
var position = [( e.clientX - code_rect.x ) + this.getScrollLeft(), (e.clientY - code_rect.y) + this.getScrollTop()];
|
|
1696
1731
|
var ln = (position[ 1 ] / this.lineHeight)|0;
|
|
1697
1732
|
|
|
1698
1733
|
if( this.code.lines[ ln ] == undefined )
|
|
1699
1734
|
return;
|
|
1700
|
-
|
|
1701
|
-
this.cursorToLine( cursor, ln, true );
|
|
1702
|
-
|
|
1735
|
+
|
|
1703
1736
|
var ch = ( ( position[ 0 ] - parseInt( this.xPadding ) + 3) / this.charWidth )|0;
|
|
1704
1737
|
var string = this.code.lines[ ln ].slice( 0, ch );
|
|
1705
|
-
|
|
1738
|
+
|
|
1739
|
+
// Move main cursor there...
|
|
1740
|
+
if( !e.altKey )
|
|
1741
|
+
{
|
|
1742
|
+
// Make sure we only keep the main cursor..
|
|
1743
|
+
this._removeSecondaryCursors();
|
|
1744
|
+
|
|
1745
|
+
this.cursorToLine( cursor, ln, true );
|
|
1746
|
+
this.cursorToPosition( cursor, string.length );
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
// Add new cursor
|
|
1750
|
+
else
|
|
1751
|
+
{
|
|
1752
|
+
this._addCursor( ln, string.length );
|
|
1753
|
+
}
|
|
1706
1754
|
|
|
1707
1755
|
this.hideAutoCompleteBox();
|
|
1708
1756
|
}
|
|
1709
1757
|
|
|
1710
1758
|
processSelection( e, keep_range, flags = CodeEditor.SELECTION_X_Y ) {
|
|
1711
1759
|
|
|
1712
|
-
var cursor = this.
|
|
1760
|
+
var cursor = this._getCurrentCursor();
|
|
1713
1761
|
const isMouseEvent = e && ( e.constructor == MouseEvent );
|
|
1714
1762
|
|
|
1715
1763
|
if( isMouseEvent ) this.processClick( e );
|
|
@@ -1863,7 +1911,23 @@ class CodeEditor {
|
|
|
1863
1911
|
}
|
|
1864
1912
|
}
|
|
1865
1913
|
|
|
1866
|
-
async processKey(
|
|
1914
|
+
async processKey( event ) {
|
|
1915
|
+
|
|
1916
|
+
const numCursors = this.cursors.childElementCount;
|
|
1917
|
+
|
|
1918
|
+
for( var i = 0; i < numCursors; i++ )
|
|
1919
|
+
{
|
|
1920
|
+
let cursor = this.cursors.children[ i ];
|
|
1921
|
+
|
|
1922
|
+
// We could delete secondary cursor while iterating..
|
|
1923
|
+
if( !cursor )
|
|
1924
|
+
break;
|
|
1925
|
+
|
|
1926
|
+
this.processKeyAtCursor( event, cursor );
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
async processKeyAtCursor( e, cursor ) {
|
|
1867
1931
|
|
|
1868
1932
|
if( !this.code || e.srcElement.constructor != HTMLDivElement )
|
|
1869
1933
|
return;
|
|
@@ -1876,7 +1940,6 @@ class CodeEditor {
|
|
|
1876
1940
|
if( key.length > 1 && this.specialKeys.indexOf( key ) == -1 )
|
|
1877
1941
|
return;
|
|
1878
1942
|
|
|
1879
|
-
let cursor = this.cursors.children[ 0 ];
|
|
1880
1943
|
let lidx = cursor.line;
|
|
1881
1944
|
this.code.lines[ lidx ] = this.code.lines[ lidx ] ?? "";
|
|
1882
1945
|
|
|
@@ -1887,26 +1950,14 @@ class CodeEditor {
|
|
|
1887
1950
|
switch( key.toLowerCase() ) {
|
|
1888
1951
|
case 'a': // select all
|
|
1889
1952
|
e.preventDefault();
|
|
1890
|
-
this.
|
|
1891
|
-
this.startSelection( cursor );
|
|
1892
|
-
const nlines = this.code.lines.length - 1;
|
|
1893
|
-
this.selection.toX = this.code.lines[ nlines ].length;
|
|
1894
|
-
this.selection.toY = nlines;
|
|
1895
|
-
this.cursorToPosition( cursor, this.selection.toX );
|
|
1896
|
-
this.cursorToLine( cursor, this.selection.toY );
|
|
1897
|
-
this.processSelection( null, true );
|
|
1898
|
-
this.hideAutoCompleteBox();
|
|
1953
|
+
this.selectAll( cursor );
|
|
1899
1954
|
break;
|
|
1900
1955
|
case 'c': // copy
|
|
1901
|
-
this._copyContent();
|
|
1956
|
+
this._copyContent( cursor );
|
|
1902
1957
|
return;
|
|
1903
1958
|
case 'd': // duplicate line
|
|
1904
1959
|
e.preventDefault();
|
|
1905
|
-
this.
|
|
1906
|
-
this.code.lines.splice( lidx, 0, this.code.lines[ lidx ] );
|
|
1907
|
-
this.lineDown( cursor );
|
|
1908
|
-
this.processLines();
|
|
1909
|
-
this.hideAutoCompleteBox();
|
|
1960
|
+
this._duplicateLine( lidx, cursor );
|
|
1910
1961
|
return;
|
|
1911
1962
|
case 'f': // find/search
|
|
1912
1963
|
e.preventDefault();
|
|
@@ -1921,14 +1972,14 @@ class CodeEditor {
|
|
|
1921
1972
|
this.onsave( this.getText() );
|
|
1922
1973
|
return;
|
|
1923
1974
|
case 'v': // paste
|
|
1924
|
-
this._pasteContent();
|
|
1975
|
+
this._pasteContent( cursor );
|
|
1925
1976
|
return;
|
|
1926
1977
|
case 'x': // cut line
|
|
1927
|
-
this._cutContent();
|
|
1978
|
+
this._cutContent( cursor );
|
|
1928
1979
|
this.hideAutoCompleteBox();
|
|
1929
1980
|
return;
|
|
1930
1981
|
case 'y': // redo
|
|
1931
|
-
if(!this.code.redoSteps.length)
|
|
1982
|
+
if( !this.code.redoSteps.length )
|
|
1932
1983
|
return;
|
|
1933
1984
|
this._addUndoStep( cursor, true, false);
|
|
1934
1985
|
const redo_step = this.code.redoSteps.pop();
|
|
@@ -1937,7 +1988,7 @@ class CodeEditor {
|
|
|
1937
1988
|
this.restoreCursor( cursor, redo_step.cursor );
|
|
1938
1989
|
return;
|
|
1939
1990
|
case 'z': // undo
|
|
1940
|
-
if(!this.code.undoSteps.length)
|
|
1991
|
+
if( !this.code.undoSteps.length )
|
|
1941
1992
|
return;
|
|
1942
1993
|
this._addRedoStep( cursor );
|
|
1943
1994
|
const undo_step = this.code.undoSteps.pop();
|
|
@@ -1953,6 +2004,13 @@ class CodeEditor {
|
|
|
1953
2004
|
e.preventDefault();
|
|
1954
2005
|
this._decreaseFontSize();
|
|
1955
2006
|
return;
|
|
2007
|
+
case 'arrowdown': // add cursor below only for the main cursor..
|
|
2008
|
+
if( cursor.isMainCursor && this.code.lines[ lidx + 1 ] != undefined )
|
|
2009
|
+
{
|
|
2010
|
+
var new_cursor = this._addCursor( cursor.line, cursor.position );
|
|
2011
|
+
this.lineDown( new_cursor );
|
|
2012
|
+
return;
|
|
2013
|
+
}
|
|
1956
2014
|
}
|
|
1957
2015
|
}
|
|
1958
2016
|
|
|
@@ -1962,8 +2020,9 @@ class CodeEditor {
|
|
|
1962
2020
|
case 'ArrowUp':
|
|
1963
2021
|
if(this.code.lines[ lidx - 1 ] == undefined)
|
|
1964
2022
|
return;
|
|
1965
|
-
|
|
1966
|
-
this.
|
|
2023
|
+
this._addUndoStep( cursor, true );
|
|
2024
|
+
swapArrayElements( this.code.lines, lidx - 1, lidx );
|
|
2025
|
+
this.lineUp( cursor );
|
|
1967
2026
|
this.processLine( lidx - 1 );
|
|
1968
2027
|
this.processLine( lidx );
|
|
1969
2028
|
this.hideAutoCompleteBox();
|
|
@@ -1971,8 +2030,9 @@ class CodeEditor {
|
|
|
1971
2030
|
case 'ArrowDown':
|
|
1972
2031
|
if(this.code.lines[ lidx + 1 ] == undefined)
|
|
1973
2032
|
return;
|
|
1974
|
-
|
|
1975
|
-
this.
|
|
2033
|
+
this._addUndoStep( cursor, true );
|
|
2034
|
+
swapArrayElements( this.code.lines, lidx, lidx + 1 );
|
|
2035
|
+
this.lineDown( cursor );
|
|
1976
2036
|
this.processLine( lidx );
|
|
1977
2037
|
this.processLine( lidx + 1 );
|
|
1978
2038
|
this.hideAutoCompleteBox();
|
|
@@ -1983,17 +2043,18 @@ class CodeEditor {
|
|
|
1983
2043
|
// Apply binded actions...
|
|
1984
2044
|
|
|
1985
2045
|
for( const actKey in this.actions ) {
|
|
2046
|
+
|
|
1986
2047
|
if( key != actKey ) continue;
|
|
1987
2048
|
e.preventDefault();
|
|
1988
2049
|
|
|
1989
|
-
if(this.actions[ key ].deleteSelection && this.selection)
|
|
1990
|
-
this.actions['Backspace'].callback(lidx, cursor, e);
|
|
2050
|
+
if( this.actions[ key ].deleteSelection && this.selection )
|
|
2051
|
+
this.actions['Backspace'].callback( lidx, cursor, e );
|
|
1991
2052
|
|
|
1992
2053
|
return this.actions[ key ].callback( lidx, cursor, e );
|
|
1993
2054
|
}
|
|
1994
2055
|
|
|
1995
2056
|
// From now on, don't allow ctrl, shift or meta (mac) combinations
|
|
1996
|
-
if(
|
|
2057
|
+
if( e.ctrlKey || e.metaKey )
|
|
1997
2058
|
return;
|
|
1998
2059
|
|
|
1999
2060
|
// Add undo steps
|
|
@@ -2005,7 +2066,7 @@ class CodeEditor {
|
|
|
2005
2066
|
|
|
2006
2067
|
// Some custom cases for word enclosing (), {}, "", '', ...
|
|
2007
2068
|
|
|
2008
|
-
const enclosableKeys = ["\"", "'", "(", "{"];
|
|
2069
|
+
const enclosableKeys = [ "\"", "'", "(", "{" ];
|
|
2009
2070
|
if( enclosableKeys.indexOf( key ) > -1 )
|
|
2010
2071
|
{
|
|
2011
2072
|
if( this._encloseSelectedWordWithKey( key, lidx, cursor ) )
|
|
@@ -2023,19 +2084,19 @@ class CodeEditor {
|
|
|
2023
2084
|
|
|
2024
2085
|
// Append key
|
|
2025
2086
|
|
|
2026
|
-
const isPairKey = (Object.values( this.pairKeys ).indexOf( key ) > -1) && !this.wasKeyPaired;
|
|
2027
|
-
const sameKeyNext = isPairKey && (this.code.lines[ lidx ][cursor.position] === key);
|
|
2087
|
+
const isPairKey = ( Object.values( this.pairKeys ).indexOf( key ) > -1 ) && !this.wasKeyPaired;
|
|
2088
|
+
const sameKeyNext = isPairKey && ( this.code.lines[ lidx ][ cursor.position ] === key );
|
|
2028
2089
|
|
|
2029
2090
|
if( !sameKeyNext )
|
|
2030
2091
|
{
|
|
2031
2092
|
this.code.lines[ lidx ] = [
|
|
2032
|
-
this.code.lines[ lidx ].slice(0, cursor.position),
|
|
2093
|
+
this.code.lines[ lidx ].slice( 0, cursor.position ),
|
|
2033
2094
|
key,
|
|
2034
|
-
this.code.lines[ lidx ].slice(cursor.position)
|
|
2095
|
+
this.code.lines[ lidx ].slice( cursor.position )
|
|
2035
2096
|
].join('');
|
|
2036
2097
|
}
|
|
2037
2098
|
|
|
2038
|
-
this.cursorToRight( key );
|
|
2099
|
+
this.cursorToRight( key, cursor );
|
|
2039
2100
|
|
|
2040
2101
|
// Some custom cases for auto key pair (), {}, "", '', ...
|
|
2041
2102
|
|
|
@@ -2045,7 +2106,7 @@ class CodeEditor {
|
|
|
2045
2106
|
// Make sure to detect later that the key is paired automatically to avoid loops...
|
|
2046
2107
|
this.wasKeyPaired = true;
|
|
2047
2108
|
|
|
2048
|
-
if(sameKeyNext) return;
|
|
2109
|
+
if( sameKeyNext ) return;
|
|
2049
2110
|
|
|
2050
2111
|
this.root.dispatchEvent(new KeyboardEvent('keydown', { 'key': this.pairKeys[ key ] }));
|
|
2051
2112
|
this.cursorToLeft( key, cursor );
|
|
@@ -2072,14 +2133,14 @@ class CodeEditor {
|
|
|
2072
2133
|
this.showAutoCompleteBox( key, cursor );
|
|
2073
2134
|
}
|
|
2074
2135
|
|
|
2075
|
-
async _pasteContent() {
|
|
2136
|
+
async _pasteContent( cursor ) {
|
|
2137
|
+
|
|
2076
2138
|
let text = await navigator.clipboard.readText();
|
|
2077
|
-
this.appendText(text);
|
|
2139
|
+
this.appendText( text, cursor );
|
|
2078
2140
|
}
|
|
2079
2141
|
|
|
2080
|
-
async _copyContent() {
|
|
2142
|
+
async _copyContent( cursor ) {
|
|
2081
2143
|
|
|
2082
|
-
let cursor = this.cursors.children[ 0 ];
|
|
2083
2144
|
let text_to_copy = "";
|
|
2084
2145
|
|
|
2085
2146
|
if( !this.selection ) {
|
|
@@ -2109,9 +2170,8 @@ class CodeEditor {
|
|
|
2109
2170
|
navigator.clipboard.writeText( text_to_copy ).then(() => console.log("Successfully copied"), (err) => console.error("Error"));
|
|
2110
2171
|
}
|
|
2111
2172
|
|
|
2112
|
-
async _cutContent() {
|
|
2173
|
+
async _cutContent( cursor ) {
|
|
2113
2174
|
|
|
2114
|
-
let cursor = this.cursors.children[ 0 ];
|
|
2115
2175
|
let lidx = cursor.line;
|
|
2116
2176
|
let text_to_cut = "";
|
|
2117
2177
|
|
|
@@ -2121,9 +2181,9 @@ class CodeEditor {
|
|
|
2121
2181
|
text_to_cut = "\n" + this.code.lines[ cursor.line ];
|
|
2122
2182
|
this.code.lines.splice( lidx, 1 );
|
|
2123
2183
|
this.processLines();
|
|
2124
|
-
this.resetCursorPos( CodeEditor.CURSOR_LEFT );
|
|
2184
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
2125
2185
|
if( this.code.lines[ lidx ] == undefined )
|
|
2126
|
-
this.lineUp();
|
|
2186
|
+
this.lineUp( cursor );
|
|
2127
2187
|
}
|
|
2128
2188
|
else {
|
|
2129
2189
|
|
|
@@ -2151,6 +2211,16 @@ class CodeEditor {
|
|
|
2151
2211
|
navigator.clipboard.writeText( text_to_cut ).then(() => console.log("Successfully cut"), (err) => console.error("Error"));
|
|
2152
2212
|
}
|
|
2153
2213
|
|
|
2214
|
+
_duplicateLine( lidx, cursor ) {
|
|
2215
|
+
|
|
2216
|
+
this.endSelection();
|
|
2217
|
+
this._addUndoStep( cursor, true );
|
|
2218
|
+
this.code.lines.splice( lidx, 0, this.code.lines[ lidx ] );
|
|
2219
|
+
this.lineDown( cursor );
|
|
2220
|
+
this.processLines();
|
|
2221
|
+
this.hideAutoCompleteBox();
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2154
2224
|
action( key, deleteSelection, fn ) {
|
|
2155
2225
|
|
|
2156
2226
|
this.actions[ key ] = {
|
|
@@ -2618,7 +2688,13 @@ class CodeEditor {
|
|
|
2618
2688
|
}
|
|
2619
2689
|
|
|
2620
2690
|
_isCSSClass( token, prev, next ) {
|
|
2621
|
-
|
|
2691
|
+
|
|
2692
|
+
if( this.highlight != 'CSS' )
|
|
2693
|
+
return false;
|
|
2694
|
+
|
|
2695
|
+
return ( prev == '.' || prev == '::'
|
|
2696
|
+
|| ( prev == ':' && next == '{' )
|
|
2697
|
+
|| ( token[ 0 ] == '#' && prev != ':' ) );
|
|
2622
2698
|
}
|
|
2623
2699
|
|
|
2624
2700
|
isNumber( token ) {
|
|
@@ -2712,8 +2788,6 @@ class CodeEditor {
|
|
|
2712
2788
|
|
|
2713
2789
|
lineUp( cursor, resetLeft ) {
|
|
2714
2790
|
|
|
2715
|
-
cursor = cursor ?? this.cursors.children[ 0 ];
|
|
2716
|
-
|
|
2717
2791
|
if( this.code.lines[ cursor.line - 1 ] == undefined )
|
|
2718
2792
|
return false;
|
|
2719
2793
|
|
|
@@ -2725,8 +2799,6 @@ class CodeEditor {
|
|
|
2725
2799
|
}
|
|
2726
2800
|
|
|
2727
2801
|
lineDown( cursor, resetLeft ) {
|
|
2728
|
-
|
|
2729
|
-
cursor = cursor ?? this.cursors.children[ 0 ];
|
|
2730
2802
|
|
|
2731
2803
|
if( this.code.lines[ cursor.line + 1 ] == undefined )
|
|
2732
2804
|
return false;
|
|
@@ -2804,10 +2876,23 @@ class CodeEditor {
|
|
|
2804
2876
|
delete this._lastSelectionKeyDir;
|
|
2805
2877
|
}
|
|
2806
2878
|
|
|
2879
|
+
selectAll( cursor ) {
|
|
2880
|
+
|
|
2881
|
+
this.resetCursorPos( CodeEditor.CURSOR_LEFT | CodeEditor.CURSOR_TOP, cursor );
|
|
2882
|
+
this.startSelection( cursor );
|
|
2883
|
+
const nlines = this.code.lines.length - 1;
|
|
2884
|
+
this.selection.toX = this.code.lines[ nlines ].length;
|
|
2885
|
+
this.selection.toY = nlines;
|
|
2886
|
+
this.cursorToPosition( cursor, this.selection.toX );
|
|
2887
|
+
this.cursorToLine( cursor, this.selection.toY );
|
|
2888
|
+
this.processSelection( null, true );
|
|
2889
|
+
this.hideAutoCompleteBox();
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2807
2892
|
cursorToRight( key, cursor ) {
|
|
2808
2893
|
|
|
2809
2894
|
if( !key ) return;
|
|
2810
|
-
|
|
2895
|
+
|
|
2811
2896
|
cursor._left += this.charWidth;
|
|
2812
2897
|
cursor.style.left = "calc( " + cursor._left + "px + " + this.xPadding + " )";
|
|
2813
2898
|
cursor.position++;
|
|
@@ -2826,7 +2911,7 @@ class CodeEditor {
|
|
|
2826
2911
|
cursorToLeft( key, cursor ) {
|
|
2827
2912
|
|
|
2828
2913
|
if( !key ) return;
|
|
2829
|
-
|
|
2914
|
+
|
|
2830
2915
|
cursor._left -= this.charWidth;
|
|
2831
2916
|
cursor._left = Math.max( cursor._left, 0 );
|
|
2832
2917
|
cursor.style.left = "calc( " + cursor._left + "px + " + this.xPadding + " )";
|
|
@@ -2845,13 +2930,12 @@ class CodeEditor {
|
|
|
2845
2930
|
|
|
2846
2931
|
cursorToTop( cursor, resetLeft = false ) {
|
|
2847
2932
|
|
|
2848
|
-
cursor = cursor ?? this.cursors.children[ 0 ];
|
|
2849
2933
|
cursor._top -= this.lineHeight;
|
|
2850
2934
|
cursor._top = Math.max(cursor._top, 0);
|
|
2851
2935
|
cursor.style.top = "calc(" + cursor._top + "px)";
|
|
2852
2936
|
this.restartBlink();
|
|
2853
2937
|
|
|
2854
|
-
if(resetLeft)
|
|
2938
|
+
if( resetLeft )
|
|
2855
2939
|
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
2856
2940
|
|
|
2857
2941
|
doAsync(() => {
|
|
@@ -2863,12 +2947,12 @@ class CodeEditor {
|
|
|
2863
2947
|
|
|
2864
2948
|
cursorToBottom( cursor, resetLeft = false ) {
|
|
2865
2949
|
|
|
2866
|
-
cursor = cursor ?? this.cursors.children[ 0 ];
|
|
2867
2950
|
cursor._top += this.lineHeight;
|
|
2868
2951
|
cursor.style.top = "calc(" + cursor._top + "px)";
|
|
2952
|
+
|
|
2869
2953
|
this.restartBlink();
|
|
2870
2954
|
|
|
2871
|
-
if(resetLeft)
|
|
2955
|
+
if( resetLeft )
|
|
2872
2956
|
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
2873
2957
|
|
|
2874
2958
|
doAsync(() => {
|
|
@@ -2880,10 +2964,11 @@ class CodeEditor {
|
|
|
2880
2964
|
|
|
2881
2965
|
cursorToString( cursor, text, reverse ) {
|
|
2882
2966
|
|
|
2883
|
-
if( !text.length )
|
|
2884
|
-
|
|
2967
|
+
if( !text.length )
|
|
2968
|
+
return;
|
|
2969
|
+
|
|
2885
2970
|
for( let char of text )
|
|
2886
|
-
reverse ? this.cursorToLeft( char ) : this.cursorToRight( char );
|
|
2971
|
+
reverse ? this.cursorToLeft( char, cursor ) : this.cursorToRight( char, cursor );
|
|
2887
2972
|
}
|
|
2888
2973
|
|
|
2889
2974
|
cursorToPosition( cursor, position ) {
|
|
@@ -2903,17 +2988,16 @@ class CodeEditor {
|
|
|
2903
2988
|
|
|
2904
2989
|
saveCursor( cursor, state = {} ) {
|
|
2905
2990
|
|
|
2906
|
-
var cursor = cursor ?? this.cursors.children[ 0 ];
|
|
2907
2991
|
state.top = cursor._top;
|
|
2908
2992
|
state.left = cursor._left;
|
|
2909
2993
|
state.line = cursor.line;
|
|
2910
2994
|
state.position = cursor.position;
|
|
2995
|
+
|
|
2911
2996
|
return state;
|
|
2912
2997
|
}
|
|
2913
2998
|
|
|
2914
2999
|
restoreCursor( cursor, state ) {
|
|
2915
3000
|
|
|
2916
|
-
cursor = cursor ?? this.cursors.children[ 0 ];
|
|
2917
3001
|
cursor.line = state.line ?? 0;
|
|
2918
3002
|
cursor.position = state.position ?? 0;
|
|
2919
3003
|
|
|
@@ -2925,7 +3009,7 @@ class CodeEditor {
|
|
|
2925
3009
|
|
|
2926
3010
|
resetCursorPos( flag, cursor ) {
|
|
2927
3011
|
|
|
2928
|
-
cursor = cursor ?? this.
|
|
3012
|
+
cursor = cursor ?? this._getCurrentCursor();
|
|
2929
3013
|
|
|
2930
3014
|
if( flag & CodeEditor.CURSOR_LEFT )
|
|
2931
3015
|
{
|
|
@@ -2942,14 +3026,14 @@ class CodeEditor {
|
|
|
2942
3026
|
}
|
|
2943
3027
|
}
|
|
2944
3028
|
|
|
2945
|
-
addSpaceTabs(n) {
|
|
3029
|
+
addSpaceTabs( n ) {
|
|
2946
3030
|
|
|
2947
3031
|
for( var i = 0; i < n; ++i ) {
|
|
2948
3032
|
this.actions[ 'Tab' ].callback();
|
|
2949
3033
|
}
|
|
2950
3034
|
}
|
|
2951
3035
|
|
|
2952
|
-
addSpaces(n) {
|
|
3036
|
+
addSpaces( n ) {
|
|
2953
3037
|
|
|
2954
3038
|
for( var i = 0; i < n; ++i ) {
|
|
2955
3039
|
this.root.dispatchEvent( new CustomEvent( 'keydown', { 'detail': {
|
|
@@ -3109,14 +3193,11 @@ class CodeEditor {
|
|
|
3109
3193
|
|
|
3110
3194
|
getCharAtPos( cursor, offset = 0 ) {
|
|
3111
3195
|
|
|
3112
|
-
cursor = cursor ?? this.cursors.children[ 0 ];
|
|
3113
3196
|
return this.code.lines[ cursor.line ][ cursor.position + offset ];
|
|
3114
3197
|
}
|
|
3115
3198
|
|
|
3116
|
-
getWordAtPos( cursor,
|
|
3199
|
+
getWordAtPos( cursor, offset = 0 ) {
|
|
3117
3200
|
|
|
3118
|
-
roffset = roffset ?? loffset;
|
|
3119
|
-
cursor = cursor ?? this.cursors.children[ 0 ];
|
|
3120
3201
|
const col = cursor.line;
|
|
3121
3202
|
const words = this.code.lines[ col ];
|
|
3122
3203
|
|
|
@@ -3126,8 +3207,8 @@ class CodeEditor {
|
|
|
3126
3207
|
return (exceptions.indexOf( char ) > - 1) || (code > 47 && code < 58) || (code > 64 && code < 91) || (code > 96 && code < 123);
|
|
3127
3208
|
}
|
|
3128
3209
|
|
|
3129
|
-
let from = cursor.position +
|
|
3130
|
-
let to = cursor.position +
|
|
3210
|
+
let from = cursor.position + offset;
|
|
3211
|
+
let to = cursor.position + offset;
|
|
3131
3212
|
|
|
3132
3213
|
// Check left ...
|
|
3133
3214
|
|
|
@@ -3146,7 +3227,7 @@ class CodeEditor {
|
|
|
3146
3227
|
let word = words.substring( from, to );
|
|
3147
3228
|
if( word == ' ' )
|
|
3148
3229
|
{
|
|
3149
|
-
if(
|
|
3230
|
+
if( offset < 0 )
|
|
3150
3231
|
{
|
|
3151
3232
|
while( words[ from - 1 ] != undefined && words[ from - 1 ] == ' ' )
|
|
3152
3233
|
from--;
|
|
@@ -3319,8 +3400,10 @@ class CodeEditor {
|
|
|
3319
3400
|
|
|
3320
3401
|
hideAutoCompleteBox() {
|
|
3321
3402
|
|
|
3403
|
+
const isActive = this.isAutoCompleteActive;
|
|
3322
3404
|
this.isAutoCompleteActive = false;
|
|
3323
3405
|
this.autocomplete.classList.remove( 'show' );
|
|
3406
|
+
return isActive != this.isAutoCompleteActive;
|
|
3324
3407
|
}
|
|
3325
3408
|
|
|
3326
3409
|
autoCompleteWord( cursor, suggestion ) {
|
|
@@ -3521,12 +3604,21 @@ class CodeEditor {
|
|
|
3521
3604
|
return;
|
|
3522
3605
|
|
|
3523
3606
|
this.codeScroller.scrollTo( 0, Math.max( line - 15 ) * this.lineHeight );
|
|
3607
|
+
|
|
3608
|
+
// Select line ?
|
|
3609
|
+
var cursor = this._getCurrentCursor( true );
|
|
3610
|
+
this.cursorToLine( cursor, line - 1, true );
|
|
3524
3611
|
}
|
|
3525
3612
|
|
|
3526
3613
|
_updateDataInfoPanel( signal, value ) {
|
|
3527
3614
|
|
|
3528
3615
|
if( !this.skipCodeInfo )
|
|
3529
3616
|
{
|
|
3617
|
+
if( this.cursors.childElementCount > 1 )
|
|
3618
|
+
{
|
|
3619
|
+
value = "";
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3530
3622
|
LX.emit( signal, value );
|
|
3531
3623
|
}
|
|
3532
3624
|
}
|
|
@@ -3541,7 +3633,7 @@ class CodeEditor {
|
|
|
3541
3633
|
let line = this.code.childNodes[ old_local ];
|
|
3542
3634
|
|
|
3543
3635
|
if( !line )
|
|
3544
|
-
|
|
3636
|
+
return;
|
|
3545
3637
|
|
|
3546
3638
|
line.classList.remove( 'active-line' );
|
|
3547
3639
|
|
package/build/lexgui.css
CHANGED
|
@@ -131,7 +131,7 @@ body.nocursor * {
|
|
|
131
131
|
#global_search {
|
|
132
132
|
position: absolute;
|
|
133
133
|
background-color: var(--global-blur-background);
|
|
134
|
-
|
|
134
|
+
--webkit-backdrop-filter: blur(12px);
|
|
135
135
|
backdrop-filter: blur(12px);
|
|
136
136
|
border-radius: 8px;
|
|
137
137
|
border: 1px solid #d0d0ec6b;
|
|
@@ -142,6 +142,7 @@ body.nocursor * {
|
|
|
142
142
|
flex-wrap: wrap;
|
|
143
143
|
z-index: 105;
|
|
144
144
|
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); /* this fixes the overflow:hidden in Chrome/Opera */
|
|
145
|
+
mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); /* this fixes the overflow:hidden in Chrome/Opera */
|
|
145
146
|
/* box-shadow: 0 2px 10px black; */
|
|
146
147
|
}
|
|
147
148
|
|
|
@@ -1195,6 +1196,7 @@ input::-webkit-inner-spin-button {
|
|
|
1195
1196
|
|
|
1196
1197
|
/* Firefox */
|
|
1197
1198
|
input[type=number] {
|
|
1199
|
+
appearance: textfield;
|
|
1198
1200
|
-moz-appearance: textfield;
|
|
1199
1201
|
}
|
|
1200
1202
|
|
|
@@ -2732,8 +2734,33 @@ ul.lexassetscontent {
|
|
|
2732
2734
|
letter-spacing: 0em !important;
|
|
2733
2735
|
}
|
|
2734
2736
|
|
|
2735
|
-
.codebasearea .
|
|
2737
|
+
.codebasearea .lexareatabs {
|
|
2736
2738
|
padding: 0px;
|
|
2739
|
+
margin: 0px;
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
.codebasearea .lexareatab {
|
|
2743
|
+
padding: 5px;
|
|
2744
|
+
border-radius: 0px !important;
|
|
2745
|
+
margin: 0px !important;
|
|
2746
|
+
border: 1px solid #91909036;
|
|
2747
|
+
border-right: none;
|
|
2748
|
+
background-color: var(--global-color-primary) !important;
|
|
2749
|
+
transition: none;
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2752
|
+
.codebasearea .lexareatab:hover {
|
|
2753
|
+
background-color: var(--global-color-secondary) !important;
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
.codebasearea .lexareatab:last-child {
|
|
2757
|
+
border-right: 1px solid #91909036;
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
.codebasearea .lexareatab.selected {
|
|
2761
|
+
background-color: var(--global-color-secondary) !important;
|
|
2762
|
+
border-top: 1px solid var(--global-selected);
|
|
2763
|
+
border-bottom: none;
|
|
2737
2764
|
}
|
|
2738
2765
|
|
|
2739
2766
|
.codebasearea .lexareatab i {
|
|
@@ -2792,7 +2819,7 @@ ul.lexassetscontent {
|
|
|
2792
2819
|
width: 48px;
|
|
2793
2820
|
height: calc(100% - 62px);
|
|
2794
2821
|
background-color: var(--global-branch-darker);
|
|
2795
|
-
margin-top:
|
|
2822
|
+
margin-top: 28px;
|
|
2796
2823
|
overflow: hidden;
|
|
2797
2824
|
position: absolute;
|
|
2798
2825
|
}
|
package/build/lexgui.js
CHANGED
|
@@ -12,7 +12,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
var LX = global.LX = {
|
|
15
|
-
version: "0.1.
|
|
15
|
+
version: "0.1.23",
|
|
16
16
|
ready: false,
|
|
17
17
|
components: [], // specific pre-build components
|
|
18
18
|
signals: {} // events and triggers
|
package/build/lexgui.module.js
CHANGED
package/changelog.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# lexgui.js changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.23
|
|
4
|
+
|
|
5
|
+
Begin integration of multiple cursors ("Ctrl+ArrowDown").
|
|
6
|
+
Code tabs have new VS Code-alike style.
|
|
7
|
+
Improved CSS highlighting.
|
|
8
|
+
Add Undo Steps to some actions that were missing.
|
|
9
|
+
When using Ctrl+G, the selected line is now highlighted.
|
|
10
|
+
General bug fixes.
|
|
11
|
+
|
|
3
12
|
## 0.1.22
|
|
4
13
|
|
|
5
14
|
Added REDO using "Ctrl+Y".
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
5
6
|
<title>LexGUI Code Editor Demo</title>
|
|
6
7
|
<link rel="stylesheet" href="../build/lexgui.css">
|
|
7
8
|
<link rel="icon" href="../images/icon.png">
|
|
@@ -20,14 +21,16 @@
|
|
|
20
21
|
import { LX } from 'lexgui';
|
|
21
22
|
import 'lexgui/components/codeeditor.js';
|
|
22
23
|
|
|
24
|
+
window.LX = LX;
|
|
25
|
+
|
|
23
26
|
// init library and get main area
|
|
24
27
|
let area = LX.init();
|
|
25
28
|
|
|
26
|
-
const file_explorer =
|
|
29
|
+
const file_explorer = false;
|
|
27
30
|
|
|
28
31
|
if( !file_explorer )
|
|
29
32
|
{
|
|
30
|
-
var [leftArea, rightArea] = area.split({ sizes:["
|
|
33
|
+
var [leftArea, rightArea] = area.split({ sizes:["40%","60%"] });
|
|
31
34
|
|
|
32
35
|
var canvas = document.createElement('canvas');
|
|
33
36
|
canvas.id = "mycanvas";
|
|
@@ -52,13 +55,13 @@
|
|
|
52
55
|
file_explorer: file_explorer
|
|
53
56
|
});
|
|
54
57
|
|
|
55
|
-
editor.loadFile( "../
|
|
56
|
-
editor.loadFile( "../data/json_sample.json" );
|
|
57
|
-
editor.loadFile( "../data/css_sample.css" );
|
|
58
|
-
editor.loadFile( "../data/cpp_sample.cpp" );
|
|
59
|
-
editor.loadFile( "../data/xml_sample.xml" );
|
|
60
|
-
editor.loadFile( "../data/python_sample.py" );
|
|
61
|
-
editor.loadFile( "../data/rust_sample.rs" );
|
|
58
|
+
editor.loadFile( "../demo.js" );
|
|
59
|
+
// editor.loadFile( "../data/json_sample.json" );
|
|
60
|
+
// editor.loadFile( "../data/css_sample.css" );
|
|
61
|
+
// editor.loadFile( "../data/cpp_sample.cpp" );
|
|
62
|
+
// editor.loadFile( "../data/xml_sample.xml" );
|
|
63
|
+
// editor.loadFile( "../data/python_sample.py" );
|
|
64
|
+
// editor.loadFile( "../data/rust_sample.rs" );
|
|
62
65
|
// editor.loadFile( "../localhost.bat" );
|
|
63
66
|
|
|
64
67
|
if( !file_explorer )
|