lexgui 0.1.26 → 0.1.28
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 +222 -143
- package/build/components/nodegraph.js +431 -233
- package/build/lexgui.css +331 -163
- package/build/lexgui.js +162 -51
- package/build/lexgui.module.js +164 -53
- package/changelog.md +18 -0
- package/demo.js +1 -1
- package/examples/code_editor.html +9 -12
- package/examples/index.html +2 -1
- package/examples/node_graph.html +4 -4
- package/examples/side_bar.html +80 -0
- package/package.json +1 -1
|
@@ -313,7 +313,7 @@ class CodeEditor {
|
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
this.base_area = area;
|
|
316
|
-
this.area = new LX.Area( { className: "lexcodeeditor", height: "
|
|
316
|
+
this.area = new LX.Area( { className: "lexcodeeditor", height: "100%", no_append: true } );
|
|
317
317
|
|
|
318
318
|
this.tabs = this.area.addTabs( { onclose: (name) => {
|
|
319
319
|
delete this.openedTabs[ name ];
|
|
@@ -377,17 +377,7 @@ class CodeEditor {
|
|
|
377
377
|
this.xPadding = "48px";
|
|
378
378
|
|
|
379
379
|
// Add main cursor
|
|
380
|
-
|
|
381
|
-
this._addCursor( 0, 0, true, true );
|
|
382
|
-
|
|
383
|
-
Object.defineProperty( this, 'line', {
|
|
384
|
-
get: (v) => { return this._getCurrentCursor().line }
|
|
385
|
-
} );
|
|
386
|
-
|
|
387
|
-
Object.defineProperty( this, 'position', {
|
|
388
|
-
get: (v) => { return this._getCurrentCursor().position }
|
|
389
|
-
} );
|
|
390
|
-
}
|
|
380
|
+
this._addCursor( 0, 0, true, true );
|
|
391
381
|
|
|
392
382
|
// Scroll stuff
|
|
393
383
|
{
|
|
@@ -600,12 +590,17 @@ class CodeEditor {
|
|
|
600
590
|
|
|
601
591
|
// Convert reserved word arrays to maps so we can search tokens faster
|
|
602
592
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
593
|
+
if( !CodeEditor._staticReady )
|
|
594
|
+
{
|
|
595
|
+
for( let lang in CodeEditor.keywords ) CodeEditor.keywords[lang] = CodeEditor.keywords[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
596
|
+
for( let lang in CodeEditor.utils ) CodeEditor.utils[lang] = CodeEditor.utils[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
597
|
+
for( let lang in CodeEditor.types ) CodeEditor.types[lang] = CodeEditor.types[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
598
|
+
for( let lang in CodeEditor.builtin ) CodeEditor.builtin[lang] = CodeEditor.builtin[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
599
|
+
for( let lang in CodeEditor.statementsAndDeclarations ) CodeEditor.statementsAndDeclarations[lang] = CodeEditor.statementsAndDeclarations[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
600
|
+
for( let lang in CodeEditor.symbols ) CodeEditor.symbols[lang] = CodeEditor.symbols[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
601
|
+
|
|
602
|
+
CodeEditor._staticReady = true;
|
|
603
|
+
}
|
|
609
604
|
|
|
610
605
|
// Action keys
|
|
611
606
|
|
|
@@ -698,14 +693,31 @@ class CodeEditor {
|
|
|
698
693
|
|
|
699
694
|
this.action( 'Tab', true, ( ln, cursor, e ) => {
|
|
700
695
|
|
|
701
|
-
if( this.
|
|
696
|
+
if( this._skipTabs )
|
|
702
697
|
{
|
|
703
|
-
this.
|
|
704
|
-
|
|
698
|
+
this._skipTabs--;
|
|
699
|
+
if( !this._skipTabs )
|
|
700
|
+
delete this._skipTabs;
|
|
701
|
+
}
|
|
702
|
+
else if( this.isAutoCompleteActive )
|
|
705
703
|
{
|
|
706
|
-
this.
|
|
704
|
+
this.autoCompleteWord();
|
|
707
705
|
}
|
|
708
|
-
|
|
706
|
+
else
|
|
707
|
+
{
|
|
708
|
+
this._addUndoStep( cursor );
|
|
709
|
+
|
|
710
|
+
if( e && e.shiftKey )
|
|
711
|
+
{
|
|
712
|
+
this._removeSpaces( cursor );
|
|
713
|
+
}
|
|
714
|
+
else
|
|
715
|
+
{
|
|
716
|
+
const indentSpaces = this.tabSpaces - (cursor.position % this.tabSpaces);
|
|
717
|
+
this._addSpaces( indentSpaces );
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}, "shiftKey");
|
|
709
721
|
|
|
710
722
|
this.action( 'Home', false, ( ln, cursor, e ) => {
|
|
711
723
|
|
|
@@ -718,7 +730,8 @@ class CodeEditor {
|
|
|
718
730
|
let lastX = cursor.position;
|
|
719
731
|
|
|
720
732
|
this.resetCursorPos( CodeEditor.CURSOR_LEFT, cursor );
|
|
721
|
-
if(idx > 0)
|
|
733
|
+
if(idx > 0)
|
|
734
|
+
this.cursorToString( cursor, prestring );
|
|
722
735
|
this.setScrollLeft( 0 );
|
|
723
736
|
|
|
724
737
|
// Merge cursors
|
|
@@ -777,7 +790,7 @@ class CodeEditor {
|
|
|
777
790
|
// Add word
|
|
778
791
|
if( this.isAutoCompleteActive )
|
|
779
792
|
{
|
|
780
|
-
this.autoCompleteWord(
|
|
793
|
+
this.autoCompleteWord();
|
|
781
794
|
return;
|
|
782
795
|
}
|
|
783
796
|
|
|
@@ -804,10 +817,10 @@ class CodeEditor {
|
|
|
804
817
|
|
|
805
818
|
if( _c0 == '{' && _c1 == '}' ) {
|
|
806
819
|
this.code.lines.splice( cursor.line, 0, "" );
|
|
807
|
-
this.
|
|
820
|
+
this._addSpaceTabs( cursor, tabs + 1 );
|
|
808
821
|
this.code.lines[ cursor.line + 1 ] = " ".repeat(spaces) + this.code.lines[ cursor.line + 1 ];
|
|
809
822
|
} else {
|
|
810
|
-
this.
|
|
823
|
+
this._addSpaceTabs( cursor, tabs );
|
|
811
824
|
}
|
|
812
825
|
|
|
813
826
|
this.processLines();
|
|
@@ -892,19 +905,28 @@ class CodeEditor {
|
|
|
892
905
|
const [word, from, to] = this.getWordAtPos( cursor, -1 );
|
|
893
906
|
// If no length, we change line..
|
|
894
907
|
if( !word.length && this.lineUp( cursor, true ) ) {
|
|
908
|
+
const cS = e.cancelShift, kS = e.keepSelection;
|
|
895
909
|
e.cancelShift = true;
|
|
896
910
|
e.keepSelection = true;
|
|
897
911
|
this.actions[ 'End' ].callback( cursor.line, cursor, e );
|
|
898
|
-
|
|
899
|
-
|
|
912
|
+
e.cancelShift = cS;
|
|
913
|
+
e.keepSelection = kS;
|
|
900
914
|
}
|
|
901
915
|
var diff = Math.max( cursor.position - from, 1 );
|
|
902
916
|
var substr = word.substr( 0, diff );
|
|
917
|
+
|
|
903
918
|
// Selections...
|
|
904
|
-
if( e.shiftKey ) {
|
|
905
|
-
|
|
919
|
+
if( e.shiftKey ) {
|
|
920
|
+
if( !cursor.selection )
|
|
921
|
+
this.startSelection( cursor );
|
|
922
|
+
}
|
|
923
|
+
else
|
|
924
|
+
this.endSelection();
|
|
925
|
+
|
|
906
926
|
this.cursorToString( cursor, substr, true );
|
|
907
|
-
|
|
927
|
+
|
|
928
|
+
if( e.shiftKey )
|
|
929
|
+
this._processSelection( cursor, e );
|
|
908
930
|
}
|
|
909
931
|
else {
|
|
910
932
|
var letter = this.getCharAtPos( cursor, -1 );
|
|
@@ -1462,14 +1484,25 @@ class CodeEditor {
|
|
|
1462
1484
|
|
|
1463
1485
|
panel.sameLine();
|
|
1464
1486
|
panel.addLabel( this.code.title, { float: 'right', signal: "@tab-name" });
|
|
1465
|
-
panel.addLabel( "Ln " + 1, {
|
|
1466
|
-
panel.addLabel( "Col " + 1, {
|
|
1487
|
+
panel.addLabel( "Ln " + 1, { maxWidth: "48px", signal: "@cursor-line" });
|
|
1488
|
+
panel.addLabel( "Col " + 1, { maxWidth: "48px", signal: "@cursor-pos" });
|
|
1489
|
+
panel.addButton( null, "Spaces: " + this.tabSpaces, ( value, event ) => {
|
|
1490
|
+
LX.addContextMenu( "Spaces", event, m => {
|
|
1491
|
+
const options = [ 2, 4, 8 ];
|
|
1492
|
+
for( const n of options )
|
|
1493
|
+
m.add( n, (v) => {
|
|
1494
|
+
this.tabSpaces = v;
|
|
1495
|
+
this.processLines();
|
|
1496
|
+
this._updateDataInfoPanel( "@tab-spaces", "Spaces: " + this.tabSpaces );
|
|
1497
|
+
} );
|
|
1498
|
+
});
|
|
1499
|
+
}, { width: "10%", nameWidth: "15%", signal: "@tab-spaces" });
|
|
1467
1500
|
panel.addButton( "<b>{ }</b>", this.highlight, ( value, event ) => {
|
|
1468
1501
|
LX.addContextMenu( "Language", event, m => {
|
|
1469
1502
|
for( const lang of Object.keys(this.languages) )
|
|
1470
1503
|
m.add( lang, this._changeLanguage.bind(this) );
|
|
1471
1504
|
});
|
|
1472
|
-
}, { width: "
|
|
1505
|
+
}, { width: "17.5%", nameWidth: "15%", signal: "@highlight" });
|
|
1473
1506
|
panel.endLine();
|
|
1474
1507
|
|
|
1475
1508
|
return panel;
|
|
@@ -1878,8 +1911,8 @@ class CodeEditor {
|
|
|
1878
1911
|
let ccw = true;
|
|
1879
1912
|
|
|
1880
1913
|
// Check if we must change ccw or not ... (not with mouse)
|
|
1881
|
-
if( !isMouseEvent &&
|
|
1882
|
-
(
|
|
1914
|
+
if( !isMouseEvent && cursor.line >= cursor.selection.fromY &&
|
|
1915
|
+
(cursor.line == cursor.selection.fromY ? cursor.position >= cursor.selection.fromX : true) )
|
|
1883
1916
|
{
|
|
1884
1917
|
ccw = ( e && this._lastSelectionKeyDir && ( e.key == 'ArrowRight' || e.key == 'ArrowDown' || e.key == 'End' ) );
|
|
1885
1918
|
}
|
|
@@ -2188,12 +2221,13 @@ class CodeEditor {
|
|
|
2188
2221
|
this.hideAutoCompleteBox();
|
|
2189
2222
|
return;
|
|
2190
2223
|
case 'arrowdown': // add cursor below only for the main cursor..
|
|
2191
|
-
|
|
2224
|
+
// Make sure shift is not pressed..
|
|
2225
|
+
if( !e.shiftKey && isLastCursor && this.code.lines[ lidx + 1 ] != undefined )
|
|
2192
2226
|
{
|
|
2193
2227
|
var new_cursor = this._addCursor( cursor.line, cursor.position, true );
|
|
2194
2228
|
this.lineDown( new_cursor );
|
|
2229
|
+
return;
|
|
2195
2230
|
}
|
|
2196
|
-
return;
|
|
2197
2231
|
}
|
|
2198
2232
|
}
|
|
2199
2233
|
|
|
@@ -2231,10 +2265,12 @@ class CodeEditor {
|
|
|
2231
2265
|
|
|
2232
2266
|
for( const actKey in this.actions ) {
|
|
2233
2267
|
|
|
2234
|
-
if( key != actKey )
|
|
2268
|
+
if( key != actKey )
|
|
2269
|
+
continue;
|
|
2270
|
+
|
|
2235
2271
|
e.preventDefault();
|
|
2236
2272
|
|
|
2237
|
-
if( this.actions[ key ]
|
|
2273
|
+
if( this._actionMustDelete( cursor, this.actions[ key ], e ) )
|
|
2238
2274
|
this.actions['Backspace'].callback( lidx, cursor, e );
|
|
2239
2275
|
|
|
2240
2276
|
return this.actions[ key ].callback( lidx, cursor, e );
|
|
@@ -2529,14 +2565,22 @@ class CodeEditor {
|
|
|
2529
2565
|
}
|
|
2530
2566
|
}
|
|
2531
2567
|
|
|
2532
|
-
action( key, deleteSelection, fn ) {
|
|
2568
|
+
action( key, deleteSelection, fn, eventSkipDelete ) {
|
|
2533
2569
|
|
|
2534
2570
|
this.actions[ key ] = {
|
|
2571
|
+
"key": key,
|
|
2535
2572
|
"callback": fn,
|
|
2536
|
-
"deleteSelection": deleteSelection
|
|
2573
|
+
"deleteSelection": deleteSelection,
|
|
2574
|
+
"eventSkipDelete": eventSkipDelete
|
|
2537
2575
|
};
|
|
2538
2576
|
}
|
|
2539
2577
|
|
|
2578
|
+
_actionMustDelete( cursor, action, e ) {
|
|
2579
|
+
|
|
2580
|
+
return cursor.selection && action.deleteSelection &&
|
|
2581
|
+
( action.eventSkipDelete ? !e[ action.eventSkipDelete ] : true );
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2540
2584
|
scanWordSuggestions() {
|
|
2541
2585
|
|
|
2542
2586
|
this.code.tokens = {};
|
|
@@ -2861,111 +2905,98 @@ class CodeEditor {
|
|
|
2861
2905
|
|
|
2862
2906
|
const usesBlockComments = lang.blockComments ?? true;
|
|
2863
2907
|
const blockCommentsTokens = lang.blockCommentsTokens ?? this.defaultBlockCommentTokens;
|
|
2908
|
+
const singleLineCommentToken = lang.singleLineCommentToken ?? this.defaultSingleLineCommentToken;
|
|
2909
|
+
|
|
2910
|
+
let token_classname = "";
|
|
2911
|
+
let discardToken = false;
|
|
2864
2912
|
|
|
2865
|
-
if(
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
}
|
|
2874
|
-
else
|
|
2875
|
-
{
|
|
2876
|
-
const singleLineCommentToken = lang.singleLineCommentToken ?? this.defaultSingleLineCommentToken;
|
|
2877
|
-
|
|
2878
|
-
let token_classname = "";
|
|
2879
|
-
let discardToken = false;
|
|
2880
|
-
|
|
2881
|
-
if( this._buildingBlockComment != undefined )
|
|
2882
|
-
token_classname = "cm-com";
|
|
2883
|
-
|
|
2884
|
-
else if( this._buildingString != undefined )
|
|
2885
|
-
discardToken = this._appendStringToken( token );
|
|
2886
|
-
|
|
2887
|
-
else if( this._mustHightlightWord( token, CodeEditor.keywords ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
|
|
2888
|
-
token_classname = "cm-kwd";
|
|
2913
|
+
if( this._buildingBlockComment != undefined )
|
|
2914
|
+
token_classname = "cm-com";
|
|
2915
|
+
|
|
2916
|
+
else if( this._buildingString != undefined )
|
|
2917
|
+
discardToken = this._appendStringToken( token );
|
|
2918
|
+
|
|
2919
|
+
else if( this._mustHightlightWord( token, CodeEditor.keywords ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
|
|
2920
|
+
token_classname = "cm-kwd";
|
|
2889
2921
|
|
|
2890
|
-
|
|
2891
|
-
|
|
2922
|
+
else if( this._mustHightlightWord( token, CodeEditor.builtin ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
|
|
2923
|
+
token_classname = "cm-bln";
|
|
2892
2924
|
|
|
2893
|
-
|
|
2894
|
-
|
|
2925
|
+
else if( this._mustHightlightWord( token, CodeEditor.statementsAndDeclarations ) )
|
|
2926
|
+
token_classname = "cm-std";
|
|
2895
2927
|
|
|
2896
|
-
|
|
2897
|
-
|
|
2928
|
+
else if( this._mustHightlightWord( token, CodeEditor.symbols ) )
|
|
2929
|
+
token_classname = "cm-sym";
|
|
2898
2930
|
|
|
2899
|
-
|
|
2900
|
-
|
|
2931
|
+
else if( token.substr( 0, singleLineCommentToken.length ) == singleLineCommentToken )
|
|
2932
|
+
token_classname = "cm-com";
|
|
2901
2933
|
|
|
2902
|
-
|
|
2903
|
-
|
|
2934
|
+
else if( this._isNumber( token ) || this._isNumber( token.replace(/[px]|[em]|%/g,'') ) )
|
|
2935
|
+
token_classname = "cm-dec";
|
|
2904
2936
|
|
|
2905
|
-
|
|
2906
|
-
|
|
2937
|
+
else if( this._isCSSClass( token, prev, next ) )
|
|
2938
|
+
token_classname = "cm-kwd";
|
|
2907
2939
|
|
|
2908
|
-
|
|
2909
|
-
|
|
2940
|
+
else if ( this._isType( token, prev, next ) )
|
|
2941
|
+
token_classname = "cm-typ";
|
|
2910
2942
|
|
|
2911
|
-
|
|
2912
|
-
|
|
2943
|
+
else if ( highlight == 'batch' && ( token == '@' || prev == ':' || prev == '@' ) )
|
|
2944
|
+
token_classname = "cm-kwd";
|
|
2913
2945
|
|
|
2914
|
-
|
|
2915
|
-
|
|
2946
|
+
else if ( [ 'cpp', 'wgsl', 'glsl' ].indexOf( highlight ) > -1 && token.includes( '#' ) ) // C++ preprocessor
|
|
2947
|
+
token_classname = "cm-ppc";
|
|
2916
2948
|
|
|
2917
|
-
|
|
2918
|
-
|
|
2949
|
+
else if ( highlight == 'cpp' && prev == '<' && (next == '>' || next == '*') ) // Defining template type in C++
|
|
2950
|
+
token_classname = "cm-typ";
|
|
2919
2951
|
|
|
2920
|
-
|
|
2921
|
-
|
|
2952
|
+
else if ( highlight == 'cpp' && (next == '::' || prev == '::' && next != '(' )) // C++ Class
|
|
2953
|
+
token_classname = "cm-typ";
|
|
2922
2954
|
|
|
2923
|
-
|
|
2924
|
-
|
|
2955
|
+
else if ( highlight == 'css' && prev == ':' && (next == ';' || next == '!important') ) // CSS value
|
|
2956
|
+
token_classname = "cm-str";
|
|
2925
2957
|
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2958
|
+
else if ( highlight == 'css' && prev == undefined && next == ':' ) // CSS attribute
|
|
2959
|
+
token_classname = "cm-typ";
|
|
2960
|
+
|
|
2961
|
+
else if ( this._markdownHeader || ( highlight == 'markdown' && isFirstToken && token.replaceAll('#', '').length != token.length ) ) // Header
|
|
2962
|
+
{
|
|
2963
|
+
token_classname = "cm-kwd";
|
|
2964
|
+
this._markdownHeader = true;
|
|
2965
|
+
}
|
|
2934
2966
|
|
|
2935
|
-
|
|
2936
|
-
|
|
2967
|
+
else if ( token[ 0 ] != '@' && token[ 0 ] != ',' && next == '(' )
|
|
2968
|
+
token_classname = "cm-mtd";
|
|
2937
2969
|
|
|
2938
2970
|
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2971
|
+
if( usesBlockComments && this._buildingBlockComment != undefined
|
|
2972
|
+
&& token.substr( 0, blockCommentsTokens[ 1 ].length ) == blockCommentsTokens[ 1 ] )
|
|
2973
|
+
{
|
|
2974
|
+
this._blockCommentCache.push( new LX.vec2( this._buildingBlockComment, this._currentLineNumber ) );
|
|
2975
|
+
delete this._buildingBlockComment;
|
|
2976
|
+
}
|
|
2945
2977
|
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2978
|
+
// We finished constructing a string
|
|
2979
|
+
if( this._buildingString && ( this._stringEnded || isLastToken ) )
|
|
2980
|
+
{
|
|
2981
|
+
token = this._getCurrentString();
|
|
2982
|
+
token_classname = "cm-str";
|
|
2983
|
+
discardToken = false;
|
|
2984
|
+
}
|
|
2953
2985
|
|
|
2954
|
-
|
|
2955
|
-
|
|
2986
|
+
// Update state
|
|
2987
|
+
this._buildingString = this._stringEnded ? undefined : this._buildingString;
|
|
2956
2988
|
|
|
2957
|
-
|
|
2958
|
-
|
|
2989
|
+
if( discardToken )
|
|
2990
|
+
return "";
|
|
2959
2991
|
|
|
2960
|
-
|
|
2961
|
-
|
|
2992
|
+
token = token.replace( "<", "<" );
|
|
2993
|
+
token = token.replace( ">", ">" );
|
|
2962
2994
|
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2995
|
+
// No highlighting, no need to put it inside another span..
|
|
2996
|
+
if( !token_classname.length )
|
|
2997
|
+
return token;
|
|
2966
2998
|
|
|
2967
|
-
|
|
2968
|
-
}
|
|
2999
|
+
return "<span class='" + highlight + " " + token_classname + "'>" + token + "</span>";
|
|
2969
3000
|
}
|
|
2970
3001
|
|
|
2971
3002
|
_appendStringToken( token ) {
|
|
@@ -3204,6 +3235,7 @@ class CodeEditor {
|
|
|
3204
3235
|
delete this._tripleClickSelection;
|
|
3205
3236
|
delete this._lastSelectionKeyDir;
|
|
3206
3237
|
delete this._currentOcurrences;
|
|
3238
|
+
delete this._lastResult;
|
|
3207
3239
|
|
|
3208
3240
|
if( cursor )
|
|
3209
3241
|
{
|
|
@@ -3428,14 +3460,14 @@ class CodeEditor {
|
|
|
3428
3460
|
}
|
|
3429
3461
|
}
|
|
3430
3462
|
|
|
3431
|
-
|
|
3463
|
+
_addSpaceTabs( cursor, n ) {
|
|
3432
3464
|
|
|
3433
3465
|
for( var i = 0; i < n; ++i ) {
|
|
3434
|
-
this.actions[ 'Tab' ].callback();
|
|
3466
|
+
this.actions[ 'Tab' ].callback( cursor.line, cursor, null );
|
|
3435
3467
|
}
|
|
3436
3468
|
}
|
|
3437
3469
|
|
|
3438
|
-
|
|
3470
|
+
_addSpaces( n ) {
|
|
3439
3471
|
|
|
3440
3472
|
for( var i = 0; i < n; ++i ) {
|
|
3441
3473
|
this.root.dispatchEvent( new CustomEvent( 'keydown', { 'detail': {
|
|
@@ -3446,6 +3478,42 @@ class CodeEditor {
|
|
|
3446
3478
|
}
|
|
3447
3479
|
}
|
|
3448
3480
|
|
|
3481
|
+
_removeSpaces( cursor ) {
|
|
3482
|
+
|
|
3483
|
+
// Remove indentation
|
|
3484
|
+
const lidx = cursor.line;
|
|
3485
|
+
let lineStart = firstNonspaceIndex( this.code.lines[ lidx ] );
|
|
3486
|
+
|
|
3487
|
+
// Nothing to remove... we are at the start of the line
|
|
3488
|
+
if( lineStart == 0 )
|
|
3489
|
+
return;
|
|
3490
|
+
|
|
3491
|
+
// Only tabs/spaces in the line...
|
|
3492
|
+
if( lineStart == -1 ) {
|
|
3493
|
+
lineStart = this.code.lines[ lidx ].length;
|
|
3494
|
+
}
|
|
3495
|
+
|
|
3496
|
+
let indentSpaces = lineStart % this.tabSpaces;
|
|
3497
|
+
indentSpaces = indentSpaces == 0 ? this.tabSpaces : indentSpaces;
|
|
3498
|
+
const newStart = Math.max( lineStart - indentSpaces, 0 );
|
|
3499
|
+
|
|
3500
|
+
this.code.lines[ lidx ] = [
|
|
3501
|
+
this.code.lines[ lidx ].slice( 0, newStart ),
|
|
3502
|
+
this.code.lines[ lidx ].slice( lineStart )
|
|
3503
|
+
].join('');
|
|
3504
|
+
|
|
3505
|
+
this.processLine( lidx );
|
|
3506
|
+
|
|
3507
|
+
this.cursorToString( cursor, " ".repeat( indentSpaces ), true );
|
|
3508
|
+
|
|
3509
|
+
if( cursor.selection )
|
|
3510
|
+
{
|
|
3511
|
+
cursor.selection.invertIfNecessary();
|
|
3512
|
+
cursor.selection.fromX = Math.max( cursor.selection.fromX - indentSpaces, 0 );
|
|
3513
|
+
this._processSelection( cursor );
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3449
3517
|
getScrollLeft() {
|
|
3450
3518
|
|
|
3451
3519
|
if( !this.codeScroller ) return 0;
|
|
@@ -3715,8 +3783,11 @@ class CodeEditor {
|
|
|
3715
3783
|
|
|
3716
3784
|
showAutoCompleteBox( key, cursor ) {
|
|
3717
3785
|
|
|
3786
|
+
if( !cursor.isMain )
|
|
3787
|
+
return;
|
|
3788
|
+
|
|
3718
3789
|
const [word, start, end] = this.getWordAtPos( cursor, -1 );
|
|
3719
|
-
if(key == ' ' || !word.length) {
|
|
3790
|
+
if( key == ' ' || !word.length ) {
|
|
3720
3791
|
this.hideAutoCompleteBox();
|
|
3721
3792
|
return;
|
|
3722
3793
|
}
|
|
@@ -3763,7 +3834,7 @@ class CodeEditor {
|
|
|
3763
3834
|
pre.appendChild( icon );
|
|
3764
3835
|
|
|
3765
3836
|
pre.addEventListener( 'click', () => {
|
|
3766
|
-
this.autoCompleteWord(
|
|
3837
|
+
this.autoCompleteWord( s );
|
|
3767
3838
|
} );
|
|
3768
3839
|
|
|
3769
3840
|
// Highlight the written part
|
|
@@ -3795,8 +3866,8 @@ class CodeEditor {
|
|
|
3795
3866
|
// Show box
|
|
3796
3867
|
this.autocomplete.classList.toggle('show', true);
|
|
3797
3868
|
this.autocomplete.classList.toggle('no-scrollbar', !(this.autocomplete.scrollHeight > this.autocomplete.offsetHeight));
|
|
3798
|
-
this.autocomplete.style.left = (cursor._left +
|
|
3799
|
-
this.autocomplete.style.top = (cursor._top +
|
|
3869
|
+
this.autocomplete.style.left = (cursor._left + 48 - this.getScrollLeft()) + "px";
|
|
3870
|
+
this.autocomplete.style.top = (cursor._top + 28 + this.lineHeight - this.getScrollTop()) + "px";
|
|
3800
3871
|
|
|
3801
3872
|
this.isAutoCompleteActive = true;
|
|
3802
3873
|
}
|
|
@@ -3809,23 +3880,30 @@ class CodeEditor {
|
|
|
3809
3880
|
return isActive != this.isAutoCompleteActive;
|
|
3810
3881
|
}
|
|
3811
3882
|
|
|
3812
|
-
autoCompleteWord(
|
|
3883
|
+
autoCompleteWord( suggestion ) {
|
|
3813
3884
|
|
|
3814
3885
|
if( !this.isAutoCompleteActive )
|
|
3815
|
-
|
|
3886
|
+
return;
|
|
3816
3887
|
|
|
3817
3888
|
let [suggestedWord, idx] = this._getSelectedAutoComplete();
|
|
3818
3889
|
suggestedWord = suggestion ?? suggestedWord;
|
|
3819
3890
|
|
|
3820
|
-
|
|
3891
|
+
for( let cursor of this.cursors.children )
|
|
3892
|
+
{
|
|
3893
|
+
const [word, start, end] = this.getWordAtPos( cursor, -1 );
|
|
3894
|
+
|
|
3895
|
+
const lineString = this.code.lines[ cursor.line ];
|
|
3896
|
+
this.code.lines[ cursor.line ] =
|
|
3897
|
+
lineString.slice(0, start) + suggestedWord + lineString.slice( end );
|
|
3898
|
+
|
|
3899
|
+
// Process lines and remove suggestion box
|
|
3900
|
+
this.cursorToPosition( cursor, start + suggestedWord.length );
|
|
3901
|
+
this.processLine( cursor.line );
|
|
3902
|
+
}
|
|
3821
3903
|
|
|
3822
|
-
|
|
3823
|
-
this.
|
|
3824
|
-
lineString.slice(0, start) + suggestedWord + lineString.slice(end);
|
|
3904
|
+
// Only the main cursor autocompletes, skip the "Tab" event for the rest
|
|
3905
|
+
this._skipTabs = this.cursors.childElementCount - 1;
|
|
3825
3906
|
|
|
3826
|
-
// Process lines and remove suggestion box
|
|
3827
|
-
this.cursorToPosition(cursor, start + suggestedWord.length);
|
|
3828
|
-
this.processLine(cursor.line);
|
|
3829
3907
|
this.hideAutoCompleteBox();
|
|
3830
3908
|
}
|
|
3831
3909
|
|
|
@@ -4210,7 +4288,7 @@ class CodeEditor {
|
|
|
4210
4288
|
CodeEditor.keywords = {
|
|
4211
4289
|
|
|
4212
4290
|
'JavaScript': ['var', 'let', 'const', 'this', 'in', 'of', 'true', 'false', 'new', 'function', 'NaN', 'static', 'class', 'constructor', 'null', 'typeof', 'debugger', 'abstract',
|
|
4213
|
-
'arguments', 'extends', 'instanceof'],
|
|
4291
|
+
'arguments', 'extends', 'instanceof', 'Infinity'],
|
|
4214
4292
|
'C++': ['int', 'float', 'double', 'bool', 'char', 'wchar_t', 'const', 'static_cast', 'dynamic_cast', 'new', 'delete', 'void', 'true', 'false', 'auto', 'struct', 'typedef', 'nullptr',
|
|
4215
4293
|
'NULL', 'unsigned', 'namespace'],
|
|
4216
4294
|
'JSON': ['true', 'false'],
|
|
@@ -4243,7 +4321,8 @@ CodeEditor.utils = { // These ones don't have hightlight, used as suggestions to
|
|
|
4243
4321
|
|
|
4244
4322
|
CodeEditor.types = {
|
|
4245
4323
|
|
|
4246
|
-
'JavaScript': ['Object', 'String', 'Function', 'Boolean', 'Symbol', 'Error', 'Number', 'TextEncoder', 'TextDecoder'
|
|
4324
|
+
'JavaScript': ['Object', 'String', 'Function', 'Boolean', 'Symbol', 'Error', 'Number', 'TextEncoder', 'TextDecoder', 'Array', 'ArrayBuffer', 'InputEvent', 'MouseEvent',
|
|
4325
|
+
'Int8Array', 'Int16Array', 'Int32Array', 'Float32Array', 'Float64Array', 'Element'],
|
|
4247
4326
|
'Rust': ['u128'],
|
|
4248
4327
|
'Python': ['int', 'type', 'float', 'map', 'list', 'ArithmeticError', 'AssertionError', 'AttributeError', 'Exception', 'EOFError', 'FloatingPointError', 'GeneratorExit',
|
|
4249
4328
|
'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotImplementedError', 'OSError',
|