lexgui 0.1.26 → 0.1.27

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.
@@ -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
- for( let lang in CodeEditor.keywords ) CodeEditor.keywords[lang] = CodeEditor.keywords[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
604
- for( let lang in CodeEditor.utils ) CodeEditor.utils[lang] = CodeEditor.utils[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
605
- for( let lang in CodeEditor.types ) CodeEditor.types[lang] = CodeEditor.types[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
606
- for( let lang in CodeEditor.builtin ) CodeEditor.builtin[lang] = CodeEditor.builtin[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
607
- for( let lang in CodeEditor.statementsAndDeclarations ) CodeEditor.statementsAndDeclarations[lang] = CodeEditor.statementsAndDeclarations[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
608
- for( let lang in CodeEditor.symbols ) CodeEditor.symbols[lang] = CodeEditor.symbols[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
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.isAutoCompleteActive )
696
+ if( this._skipTabs )
697
+ {
698
+ this._skipTabs--;
699
+ if( !this._skipTabs )
700
+ delete this._skipTabs;
701
+ }
702
+ else if( this.isAutoCompleteActive )
702
703
  {
703
- this.autoCompleteWord( cursor );
704
- } else
704
+ this.autoCompleteWord();
705
+ }
706
+ else
705
707
  {
706
- this.addSpaces( this.tabSpaces );
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
+ }
707
719
  }
708
- });
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) this.cursorToString( cursor, prestring );
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( cursor );
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.addSpaceTabs( tabs + 1 );
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.addSpaceTabs( tabs );
823
+ this._addSpaceTabs( cursor, tabs );
811
824
  }
812
825
 
813
826
  this.processLines();
@@ -1462,14 +1475,25 @@ class CodeEditor {
1462
1475
 
1463
1476
  panel.sameLine();
1464
1477
  panel.addLabel( this.code.title, { float: 'right', signal: "@tab-name" });
1465
- panel.addLabel( "Ln " + 1, { width: "64px", signal: "@cursor-line" });
1466
- panel.addLabel( "Col " + 1, { width: "64px", signal: "@cursor-pos" });
1478
+ panel.addLabel( "Ln " + 1, { maxWidth: "48px", signal: "@cursor-line" });
1479
+ panel.addLabel( "Col " + 1, { maxWidth: "48px", signal: "@cursor-pos" });
1480
+ panel.addButton( null, "Spaces: " + this.tabSpaces, ( value, event ) => {
1481
+ LX.addContextMenu( "Spaces", event, m => {
1482
+ const options = [ 2, 4, 8 ];
1483
+ for( const n of options )
1484
+ m.add( n, (v) => {
1485
+ this.tabSpaces = v;
1486
+ this.processLines();
1487
+ this._updateDataInfoPanel( "@tab-spaces", "Spaces: " + this.tabSpaces );
1488
+ } );
1489
+ });
1490
+ }, { width: "10%", nameWidth: "15%", signal: "@tab-spaces" });
1467
1491
  panel.addButton( "<b>{ }</b>", this.highlight, ( value, event ) => {
1468
1492
  LX.addContextMenu( "Language", event, m => {
1469
1493
  for( const lang of Object.keys(this.languages) )
1470
1494
  m.add( lang, this._changeLanguage.bind(this) );
1471
1495
  });
1472
- }, { width: "25%", nameWidth: "15%", signal: "@highlight" });
1496
+ }, { width: "17.5%", nameWidth: "15%", signal: "@highlight" });
1473
1497
  panel.endLine();
1474
1498
 
1475
1499
  return panel;
@@ -1878,8 +1902,8 @@ class CodeEditor {
1878
1902
  let ccw = true;
1879
1903
 
1880
1904
  // Check if we must change ccw or not ... (not with mouse)
1881
- if( !isMouseEvent && this.line >= cursor.selection.fromY &&
1882
- (this.line == cursor.selection.fromY ? this.position >= cursor.selection.fromX : true) )
1905
+ if( !isMouseEvent && cursor.line >= cursor.selection.fromY &&
1906
+ (cursor.line == cursor.selection.fromY ? cursor.position >= cursor.selection.fromX : true) )
1883
1907
  {
1884
1908
  ccw = ( e && this._lastSelectionKeyDir && ( e.key == 'ArrowRight' || e.key == 'ArrowDown' || e.key == 'End' ) );
1885
1909
  }
@@ -2231,10 +2255,12 @@ class CodeEditor {
2231
2255
 
2232
2256
  for( const actKey in this.actions ) {
2233
2257
 
2234
- if( key != actKey ) continue;
2258
+ if( key != actKey )
2259
+ continue;
2260
+
2235
2261
  e.preventDefault();
2236
2262
 
2237
- if( this.actions[ key ].deleteSelection && cursor.selection )
2263
+ if( this._actionMustDelete( cursor, this.actions[ key ], e ) )
2238
2264
  this.actions['Backspace'].callback( lidx, cursor, e );
2239
2265
 
2240
2266
  return this.actions[ key ].callback( lidx, cursor, e );
@@ -2529,14 +2555,22 @@ class CodeEditor {
2529
2555
  }
2530
2556
  }
2531
2557
 
2532
- action( key, deleteSelection, fn ) {
2558
+ action( key, deleteSelection, fn, eventSkipDelete ) {
2533
2559
 
2534
2560
  this.actions[ key ] = {
2561
+ "key": key,
2535
2562
  "callback": fn,
2536
- "deleteSelection": deleteSelection
2563
+ "deleteSelection": deleteSelection,
2564
+ "eventSkipDelete": eventSkipDelete
2537
2565
  };
2538
2566
  }
2539
2567
 
2568
+ _actionMustDelete( cursor, action, e ) {
2569
+
2570
+ return cursor.selection && action.deleteSelection &&
2571
+ ( action.eventSkipDelete ? !e[ action.eventSkipDelete ] : true );
2572
+ }
2573
+
2540
2574
  scanWordSuggestions() {
2541
2575
 
2542
2576
  this.code.tokens = {};
@@ -2861,111 +2895,98 @@ class CodeEditor {
2861
2895
 
2862
2896
  const usesBlockComments = lang.blockComments ?? true;
2863
2897
  const blockCommentsTokens = lang.blockCommentsTokens ?? this.defaultBlockCommentTokens;
2898
+ const singleLineCommentToken = lang.singleLineCommentToken ?? this.defaultSingleLineCommentToken;
2899
+
2900
+ let token_classname = "";
2901
+ let discardToken = false;
2864
2902
 
2865
- if( !usePreviousTokenToCheckString && token == ' ' )
2866
- {
2867
- if( this._buildingString != undefined )
2868
- {
2869
- this._appendStringToken( token );
2870
- return "";
2871
- }
2872
- return token;
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";
2903
+ if( this._buildingBlockComment != undefined )
2904
+ token_classname = "cm-com";
2905
+
2906
+ else if( this._buildingString != undefined )
2907
+ discardToken = this._appendStringToken( token );
2908
+
2909
+ else if( this._mustHightlightWord( token, CodeEditor.keywords ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
2910
+ token_classname = "cm-kwd";
2889
2911
 
2890
- else if( this._mustHightlightWord( token, CodeEditor.builtin ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
2891
- token_classname = "cm-bln";
2912
+ else if( this._mustHightlightWord( token, CodeEditor.builtin ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
2913
+ token_classname = "cm-bln";
2892
2914
 
2893
- else if( this._mustHightlightWord( token, CodeEditor.statementsAndDeclarations ) )
2894
- token_classname = "cm-std";
2915
+ else if( this._mustHightlightWord( token, CodeEditor.statementsAndDeclarations ) )
2916
+ token_classname = "cm-std";
2895
2917
 
2896
- else if( this._mustHightlightWord( token, CodeEditor.symbols ) )
2897
- token_classname = "cm-sym";
2918
+ else if( this._mustHightlightWord( token, CodeEditor.symbols ) )
2919
+ token_classname = "cm-sym";
2898
2920
 
2899
- else if( token.substr( 0, singleLineCommentToken.length ) == singleLineCommentToken )
2900
- token_classname = "cm-com";
2921
+ else if( token.substr( 0, singleLineCommentToken.length ) == singleLineCommentToken )
2922
+ token_classname = "cm-com";
2901
2923
 
2902
- else if( this._isNumber( token ) || this._isNumber( token.replace(/[px]|[em]|%/g,'') ) )
2903
- token_classname = "cm-dec";
2924
+ else if( this._isNumber( token ) || this._isNumber( token.replace(/[px]|[em]|%/g,'') ) )
2925
+ token_classname = "cm-dec";
2904
2926
 
2905
- else if( this._isCSSClass( token, prev, next ) )
2906
- token_classname = "cm-kwd";
2927
+ else if( this._isCSSClass( token, prev, next ) )
2928
+ token_classname = "cm-kwd";
2907
2929
 
2908
- else if ( this._isType( token, prev, next ) )
2909
- token_classname = "cm-typ";
2930
+ else if ( this._isType( token, prev, next ) )
2931
+ token_classname = "cm-typ";
2910
2932
 
2911
- else if ( highlight == 'batch' && ( token == '@' || prev == ':' || prev == '@' ) )
2912
- token_classname = "cm-kwd";
2933
+ else if ( highlight == 'batch' && ( token == '@' || prev == ':' || prev == '@' ) )
2934
+ token_classname = "cm-kwd";
2913
2935
 
2914
- else if ( [ 'cpp', 'wgsl', 'glsl' ].indexOf( highlight ) > -1 && token.includes( '#' ) ) // C++ preprocessor
2915
- token_classname = "cm-ppc";
2936
+ else if ( [ 'cpp', 'wgsl', 'glsl' ].indexOf( highlight ) > -1 && token.includes( '#' ) ) // C++ preprocessor
2937
+ token_classname = "cm-ppc";
2916
2938
 
2917
- else if ( highlight == 'cpp' && prev == '<' && (next == '>' || next == '*') ) // Defining template type in C++
2918
- token_classname = "cm-typ";
2939
+ else if ( highlight == 'cpp' && prev == '<' && (next == '>' || next == '*') ) // Defining template type in C++
2940
+ token_classname = "cm-typ";
2919
2941
 
2920
- else if ( highlight == 'cpp' && (next == '::' || prev == '::' && next != '(' )) // C++ Class
2921
- token_classname = "cm-typ";
2942
+ else if ( highlight == 'cpp' && (next == '::' || prev == '::' && next != '(' )) // C++ Class
2943
+ token_classname = "cm-typ";
2922
2944
 
2923
- else if ( highlight == 'css' && prev == ':' && (next == ';' || next == '!important') ) // CSS value
2924
- token_classname = "cm-str";
2945
+ else if ( highlight == 'css' && prev == ':' && (next == ';' || next == '!important') ) // CSS value
2946
+ token_classname = "cm-str";
2925
2947
 
2926
- else if ( highlight == 'css' && prev == undefined && next == ':' ) // CSS attribute
2927
- token_classname = "cm-typ";
2928
-
2929
- else if ( this._markdownHeader || ( highlight == 'markdown' && isFirstToken && token.replaceAll('#', '').length != token.length ) ) // Header
2930
- {
2931
- token_classname = "cm-kwd";
2932
- this._markdownHeader = true;
2933
- }
2948
+ else if ( highlight == 'css' && prev == undefined && next == ':' ) // CSS attribute
2949
+ token_classname = "cm-typ";
2950
+
2951
+ else if ( this._markdownHeader || ( highlight == 'markdown' && isFirstToken && token.replaceAll('#', '').length != token.length ) ) // Header
2952
+ {
2953
+ token_classname = "cm-kwd";
2954
+ this._markdownHeader = true;
2955
+ }
2934
2956
 
2935
- else if ( token[ 0 ] != '@' && token[ 0 ] != ',' && next == '(' )
2936
- token_classname = "cm-mtd";
2957
+ else if ( token[ 0 ] != '@' && token[ 0 ] != ',' && next == '(' )
2958
+ token_classname = "cm-mtd";
2937
2959
 
2938
2960
 
2939
- if( usesBlockComments && this._buildingBlockComment != undefined
2940
- && token.substr( 0, blockCommentsTokens[ 1 ].length ) == blockCommentsTokens[ 1 ] )
2941
- {
2942
- this._blockCommentCache.push( new LX.vec2( this._buildingBlockComment, this._currentLineNumber ) );
2943
- delete this._buildingBlockComment;
2944
- }
2961
+ if( usesBlockComments && this._buildingBlockComment != undefined
2962
+ && token.substr( 0, blockCommentsTokens[ 1 ].length ) == blockCommentsTokens[ 1 ] )
2963
+ {
2964
+ this._blockCommentCache.push( new LX.vec2( this._buildingBlockComment, this._currentLineNumber ) );
2965
+ delete this._buildingBlockComment;
2966
+ }
2945
2967
 
2946
- // We finished constructing a string
2947
- if( this._buildingString && ( this._stringEnded || isLastToken ) )
2948
- {
2949
- token = this._getCurrentString();
2950
- token_classname = "cm-str";
2951
- discardToken = false;
2952
- }
2968
+ // We finished constructing a string
2969
+ if( this._buildingString && ( this._stringEnded || isLastToken ) )
2970
+ {
2971
+ token = this._getCurrentString();
2972
+ token_classname = "cm-str";
2973
+ discardToken = false;
2974
+ }
2953
2975
 
2954
- // Update state
2955
- this._buildingString = this._stringEnded ? undefined : this._buildingString;
2976
+ // Update state
2977
+ this._buildingString = this._stringEnded ? undefined : this._buildingString;
2956
2978
 
2957
- if( discardToken )
2958
- return "";
2979
+ if( discardToken )
2980
+ return "";
2959
2981
 
2960
- token = token.replace( "<", "&lt;" );
2961
- token = token.replace( ">", "&gt;" );
2982
+ token = token.replace( "<", "&lt;" );
2983
+ token = token.replace( ">", "&gt;" );
2962
2984
 
2963
- // No highlighting, no need to put it inside another span..
2964
- if( !token_classname.length )
2965
- return token;
2985
+ // No highlighting, no need to put it inside another span..
2986
+ if( !token_classname.length )
2987
+ return token;
2966
2988
 
2967
- return "<span class='" + highlight + " " + token_classname + "'>" + token + "</span>";
2968
- }
2989
+ return "<span class='" + highlight + " " + token_classname + "'>" + token + "</span>";
2969
2990
  }
2970
2991
 
2971
2992
  _appendStringToken( token ) {
@@ -3204,6 +3225,7 @@ class CodeEditor {
3204
3225
  delete this._tripleClickSelection;
3205
3226
  delete this._lastSelectionKeyDir;
3206
3227
  delete this._currentOcurrences;
3228
+ delete this._lastResult;
3207
3229
 
3208
3230
  if( cursor )
3209
3231
  {
@@ -3428,14 +3450,14 @@ class CodeEditor {
3428
3450
  }
3429
3451
  }
3430
3452
 
3431
- addSpaceTabs( n ) {
3453
+ _addSpaceTabs( cursor, n ) {
3432
3454
 
3433
3455
  for( var i = 0; i < n; ++i ) {
3434
- this.actions[ 'Tab' ].callback();
3456
+ this.actions[ 'Tab' ].callback( cursor.line, cursor, null );
3435
3457
  }
3436
3458
  }
3437
3459
 
3438
- addSpaces( n ) {
3460
+ _addSpaces( n ) {
3439
3461
 
3440
3462
  for( var i = 0; i < n; ++i ) {
3441
3463
  this.root.dispatchEvent( new CustomEvent( 'keydown', { 'detail': {
@@ -3446,6 +3468,37 @@ class CodeEditor {
3446
3468
  }
3447
3469
  }
3448
3470
 
3471
+ _removeSpaces( cursor ) {
3472
+
3473
+ // Remove indentation
3474
+ const lidx = cursor.line;
3475
+ const lineStart = firstNonspaceIndex( this.code.lines[ lidx ] );
3476
+
3477
+ // Nothing to remove...
3478
+ if( lineStart == 0 )
3479
+ return;
3480
+
3481
+ let indentSpaces = lineStart % this.tabSpaces;
3482
+ indentSpaces = indentSpaces == 0 ? this.tabSpaces : indentSpaces;
3483
+ const newStart = Math.max( lineStart - indentSpaces, 0 );
3484
+
3485
+ this.code.lines[ lidx ] = [
3486
+ this.code.lines[ lidx ].slice( 0, newStart ),
3487
+ this.code.lines[ lidx ].slice( lineStart )
3488
+ ].join('');
3489
+
3490
+ this.processLine( lidx );
3491
+
3492
+ this.cursorToString( cursor, " ".repeat( indentSpaces ), true );
3493
+
3494
+ if( cursor.selection )
3495
+ {
3496
+ cursor.selection.invertIfNecessary();
3497
+ cursor.selection.fromX = Math.max( cursor.selection.fromX - indentSpaces, 0 );
3498
+ this._processSelection( cursor );
3499
+ }
3500
+ }
3501
+
3449
3502
  getScrollLeft() {
3450
3503
 
3451
3504
  if( !this.codeScroller ) return 0;
@@ -3715,8 +3768,11 @@ class CodeEditor {
3715
3768
 
3716
3769
  showAutoCompleteBox( key, cursor ) {
3717
3770
 
3771
+ if( !cursor.isMain )
3772
+ return;
3773
+
3718
3774
  const [word, start, end] = this.getWordAtPos( cursor, -1 );
3719
- if(key == ' ' || !word.length) {
3775
+ if( key == ' ' || !word.length ) {
3720
3776
  this.hideAutoCompleteBox();
3721
3777
  return;
3722
3778
  }
@@ -3763,7 +3819,7 @@ class CodeEditor {
3763
3819
  pre.appendChild( icon );
3764
3820
 
3765
3821
  pre.addEventListener( 'click', () => {
3766
- this.autoCompleteWord( cursor, s );
3822
+ this.autoCompleteWord( s );
3767
3823
  } );
3768
3824
 
3769
3825
  // Highlight the written part
@@ -3795,8 +3851,8 @@ class CodeEditor {
3795
3851
  // Show box
3796
3852
  this.autocomplete.classList.toggle('show', true);
3797
3853
  this.autocomplete.classList.toggle('no-scrollbar', !(this.autocomplete.scrollHeight > this.autocomplete.offsetHeight));
3798
- this.autocomplete.style.left = (cursor._left + 36 - this.getScrollLeft()) + "px";
3799
- this.autocomplete.style.top = (cursor._top + 48 - this.getScrollTop()) + "px";
3854
+ this.autocomplete.style.left = (cursor._left + 48 - this.getScrollLeft()) + "px";
3855
+ this.autocomplete.style.top = (cursor._top + 28 + this.lineHeight - this.getScrollTop()) + "px";
3800
3856
 
3801
3857
  this.isAutoCompleteActive = true;
3802
3858
  }
@@ -3809,23 +3865,30 @@ class CodeEditor {
3809
3865
  return isActive != this.isAutoCompleteActive;
3810
3866
  }
3811
3867
 
3812
- autoCompleteWord( cursor, suggestion ) {
3868
+ autoCompleteWord( suggestion ) {
3813
3869
 
3814
3870
  if( !this.isAutoCompleteActive )
3815
- return;
3871
+ return;
3816
3872
 
3817
3873
  let [suggestedWord, idx] = this._getSelectedAutoComplete();
3818
3874
  suggestedWord = suggestion ?? suggestedWord;
3819
3875
 
3820
- const [word, start, end] = this.getWordAtPos( cursor, -1 );
3876
+ for( let cursor of this.cursors.children )
3877
+ {
3878
+ const [word, start, end] = this.getWordAtPos( cursor, -1 );
3879
+
3880
+ const lineString = this.code.lines[ cursor.line ];
3881
+ this.code.lines[ cursor.line ] =
3882
+ lineString.slice(0, start) + suggestedWord + lineString.slice( end );
3883
+
3884
+ // Process lines and remove suggestion box
3885
+ this.cursorToPosition( cursor, start + suggestedWord.length );
3886
+ this.processLine( cursor.line );
3887
+ }
3821
3888
 
3822
- const lineString = this.code.lines[ cursor.line ];
3823
- this.code.lines[ cursor.line ] =
3824
- lineString.slice(0, start) + suggestedWord + lineString.slice(end);
3889
+ // Only the main cursor autocompletes, skip the "Tab" event for the rest
3890
+ this._skipTabs = this.cursors.childElementCount - 1;
3825
3891
 
3826
- // Process lines and remove suggestion box
3827
- this.cursorToPosition(cursor, start + suggestedWord.length);
3828
- this.processLine(cursor.line);
3829
3892
  this.hideAutoCompleteBox();
3830
3893
  }
3831
3894
 
@@ -4210,7 +4273,7 @@ class CodeEditor {
4210
4273
  CodeEditor.keywords = {
4211
4274
 
4212
4275
  'JavaScript': ['var', 'let', 'const', 'this', 'in', 'of', 'true', 'false', 'new', 'function', 'NaN', 'static', 'class', 'constructor', 'null', 'typeof', 'debugger', 'abstract',
4213
- 'arguments', 'extends', 'instanceof'],
4276
+ 'arguments', 'extends', 'instanceof', 'Infinity'],
4214
4277
  'C++': ['int', 'float', 'double', 'bool', 'char', 'wchar_t', 'const', 'static_cast', 'dynamic_cast', 'new', 'delete', 'void', 'true', 'false', 'auto', 'struct', 'typedef', 'nullptr',
4215
4278
  'NULL', 'unsigned', 'namespace'],
4216
4279
  'JSON': ['true', 'false'],
@@ -4243,7 +4306,8 @@ CodeEditor.utils = { // These ones don't have hightlight, used as suggestions to
4243
4306
 
4244
4307
  CodeEditor.types = {
4245
4308
 
4246
- 'JavaScript': ['Object', 'String', 'Function', 'Boolean', 'Symbol', 'Error', 'Number', 'TextEncoder', 'TextDecoder'],
4309
+ 'JavaScript': ['Object', 'String', 'Function', 'Boolean', 'Symbol', 'Error', 'Number', 'TextEncoder', 'TextDecoder', 'Array', 'ArrayBuffer', 'InputEvent', 'MouseEvent',
4310
+ 'Int8Array', 'Int16Array', 'Int32Array', 'Float32Array', 'Float64Array', 'Element'],
4247
4311
  'Rust': ['u128'],
4248
4312
  'Python': ['int', 'type', 'float', 'map', 'list', 'ArithmeticError', 'AssertionError', 'AttributeError', 'Exception', 'EOFError', 'FloatingPointError', 'GeneratorExit',
4249
4313
  'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotImplementedError', 'OSError',
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.26",
15
+ version: "0.1.27",
16
16
  ready: false,
17
17
  components: [], // specific pre-build components
18
18
  signals: {} // events and triggers
@@ -3016,6 +3016,9 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
3016
3016
  if( options.width ) {
3017
3017
  element.style.width = element.style.minWidth = options.width;
3018
3018
  }
3019
+ if( options.maxWidth ) {
3020
+ element.style.maxWidth = options.maxWidth;
3021
+ }
3019
3022
  if( options.minWidth ) {
3020
3023
  element.style.minWidth = options.minWidth;
3021
3024
  }
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  var LX = {
11
- version: "0.1.26",
11
+ version: "0.1.27",
12
12
  ready: false,
13
13
  components: [], // specific pre-build components
14
14
  signals: {} // events and triggers
@@ -3012,6 +3012,9 @@ class Panel {
3012
3012
  if( options.width ) {
3013
3013
  element.style.width = element.style.minWidth = options.width;
3014
3014
  }
3015
+ if( options.maxWidth ) {
3016
+ element.style.maxWidth = options.maxWidth;
3017
+ }
3015
3018
  if( options.minWidth ) {
3016
3019
  element.style.minWidth = options.minWidth;
3017
3020
  }
package/changelog.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # lexgui.js changelog
2
2
 
3
+ ## 0.1.27
4
+
5
+ Code Editor:
6
+ - Tab key follows fixed 4 space layout indentation.
7
+ - Support for removing indentation using "Shift+Tab".
8
+ - Support for changing number of tab spaces from the info panel.
9
+ - Minor bugfixes.
10
+
11
+ Support "maxWidth" as options when creating a widget.
12
+
3
13
  ## 0.1.26
4
14
 
5
15
  Code Editor:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lexgui",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "JS library to create web graphical user interfaces",
5
5
  "type": "module",
6
6
  "main": "./build/lexgui.js",