lexgui 0.1.24 → 0.1.25
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 +310 -135
- package/build/lexgui.css +4 -4
- package/build/lexgui.js +63 -37
- package/build/lexgui.module.js +53 -27
- package/changelog.md +11 -0
- package/package.json +1 -1
|
@@ -26,7 +26,8 @@ function sliceChars( str, idx, n = 1 ) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function firstNonspaceIndex( str ) {
|
|
29
|
-
|
|
29
|
+
const index = str.search(/\S|$/)
|
|
30
|
+
return index < str.length ? index : -1;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
function indexOfFrom( str, reg, from, reverse ) {
|
|
@@ -118,7 +119,7 @@ class CodeSelection {
|
|
|
118
119
|
this.editor.selections.appendChild(domEl);
|
|
119
120
|
|
|
120
121
|
// Hide active line background
|
|
121
|
-
this.editor.
|
|
122
|
+
this.editor._hideActiveLine();
|
|
122
123
|
}
|
|
123
124
|
};
|
|
124
125
|
|
|
@@ -201,8 +202,8 @@ class CodeEditor {
|
|
|
201
202
|
static WORD_TYPE_METHOD = 0;
|
|
202
203
|
static WORD_TYPE_CLASS = 1;
|
|
203
204
|
|
|
204
|
-
static CODE_MAX_FONT_SIZE = 22;
|
|
205
205
|
static CODE_MIN_FONT_SIZE = 9;
|
|
206
|
+
static CODE_MAX_FONT_SIZE = 22;
|
|
206
207
|
|
|
207
208
|
/**
|
|
208
209
|
* @param {*} options
|
|
@@ -493,7 +494,8 @@ class CodeEditor {
|
|
|
493
494
|
this.state = {
|
|
494
495
|
focused: false,
|
|
495
496
|
selectingText: false,
|
|
496
|
-
activeLine: null
|
|
497
|
+
activeLine: null,
|
|
498
|
+
keyChain: null
|
|
497
499
|
}
|
|
498
500
|
|
|
499
501
|
// Code
|
|
@@ -550,84 +552,16 @@ class CodeEditor {
|
|
|
550
552
|
'End', 'Tab', 'Escape'
|
|
551
553
|
];
|
|
552
554
|
|
|
553
|
-
this.
|
|
554
|
-
'JavaScript': ['var', 'let', 'const', 'this', 'in', 'of', 'true', 'false', 'new', 'function', 'NaN', 'static', 'class', 'constructor', 'null', 'typeof', 'debugger', 'abstract',
|
|
555
|
-
'arguments', 'extends', 'instanceof'],
|
|
556
|
-
'C++': ['int', 'float', 'double', 'bool', 'char', 'wchar_t', 'const', 'static_cast', 'dynamic_cast', 'new', 'delete', 'void', 'true', 'false', 'auto', 'struct', 'typedef', 'nullptr',
|
|
557
|
-
'NULL', 'unsigned', 'namespace'],
|
|
558
|
-
'JSON': ['true', 'false'],
|
|
559
|
-
'GLSL': ['true', 'false', 'function', 'int', 'float', 'vec2', 'vec3', 'vec4', 'mat2x2', 'mat3x3', 'mat4x4', 'struct'],
|
|
560
|
-
'CSS': ['body', 'html', 'canvas', 'div', 'input', 'span', '.'],
|
|
561
|
-
'WGSL': ['var', 'let', 'true', 'false', 'fn', 'bool', 'u32', 'i32', 'f16', 'f32', 'vec2f', 'vec3f', 'vec4f', 'mat2x2f', 'mat3x3f', 'mat4x4f', 'array', 'atomic', 'struct',
|
|
562
|
-
'sampler', 'sampler_comparison', 'texture_depth_2d', 'texture_depth_2d_array', 'texture_depth_cube', 'texture_depth_cube_array', 'texture_depth_multisampled_2d',
|
|
563
|
-
'texture_external', 'texture_1d', 'texture_2d', 'texture_2d_array', 'texture_3d', 'texture_cube', 'texture_cube_array', 'texture_storage_1d', 'texture_storage_2d',
|
|
564
|
-
'texture_storage_2d_array', 'texture_storage_3d'],
|
|
565
|
-
'Rust': ['as', 'const', 'crate', 'enum', 'extern', 'false', 'fn', 'impl', 'in', 'let', 'mod', 'move', 'mut', 'pub', 'ref', 'self', 'Self', 'static', 'struct', 'super', 'trait', 'true',
|
|
566
|
-
'type', 'unsafe', 'use', 'where', 'abstract', 'become', 'box', 'final', 'macro', 'override', 'priv', 'typeof', 'unsized', 'virtual'],
|
|
567
|
-
'Python': ['False', 'def', 'None', 'True', 'in', 'is', 'and', 'lambda', 'nonlocal', 'not', 'or'],
|
|
568
|
-
'Batch': ['set', 'SET', 'echo', 'ECHO', 'off', 'OFF', 'del', 'DEL', 'defined', 'DEFINED', 'setlocal', 'SETLOCAL', 'enabledelayedexpansion', 'ENABLEDELAYEDEXPANSION', 'driverquery',
|
|
569
|
-
'DRIVERQUERY', 'print', 'PRINT'],
|
|
570
|
-
'HTML': ['html', 'meta', 'title', 'link', 'script', 'body', 'DOCTYPE', 'head', 'br', 'i', 'a', 'li', 'img', 'tr', 'td', 'h1', 'h2', 'h3', 'h4', 'h5'],
|
|
571
|
-
'Markdown': ['br', 'i', 'a', 'li', 'img', 'table', 'title', 'tr', 'td', 'h1', 'h2', 'h3', 'h4', 'h5'],
|
|
572
|
-
};
|
|
573
|
-
this.utils = { // These ones don't have hightlight, used as suggestions to autocomplete only...
|
|
574
|
-
'JavaScript': ['querySelector', 'body', 'addEventListener', 'removeEventListener', 'remove', 'sort', 'keys', 'filter', 'isNaN', 'parseFloat', 'parseInt', 'EPSILON', 'isFinite',
|
|
575
|
-
'bind', 'prototype', 'length', 'assign', 'entries', 'values', 'concat', 'substring', 'substr', 'splice', 'slice', 'buffer', 'appendChild', 'createElement', 'prompt',
|
|
576
|
-
'alert'],
|
|
577
|
-
'WGSL': ['textureSample'],
|
|
578
|
-
'Python': ['abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod',
|
|
579
|
-
'enumerate', 'eval', 'exec', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
|
|
580
|
-
'issubclass', 'iter', 'len', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr',
|
|
581
|
-
'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
|
|
582
|
-
};
|
|
583
|
-
this.types = {
|
|
584
|
-
'JavaScript': ['Object', 'String', 'Function', 'Boolean', 'Symbol', 'Error', 'Number', 'TextEncoder', 'TextDecoder'],
|
|
585
|
-
'Rust': ['u128'],
|
|
586
|
-
'Python': ['int', 'type', 'float', 'map', 'list', 'ArithmeticError', 'AssertionError', 'AttributeError', 'Exception', 'EOFError', 'FloatingPointError', 'GeneratorExit',
|
|
587
|
-
'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotImplementedError', 'OSError',
|
|
588
|
-
'OverflowError', 'ReferenceError', 'RuntimeError', 'StopIteration', 'SyntaxError', 'TabError', 'SystemError', 'SystemExit', 'TypeError', 'UnboundLocalError',
|
|
589
|
-
'UnicodeError', 'UnicodeEncodeError', 'UnicodeDecodeError', 'UnicodeTranslateError', 'ValueError', 'ZeroDivisionError'],
|
|
590
|
-
'C++': ['uint8_t', 'uint16_t', 'uint32_t']
|
|
591
|
-
};
|
|
592
|
-
this.builtin = {
|
|
593
|
-
'JavaScript': ['document', 'console', 'window', 'navigator', 'performance'],
|
|
594
|
-
'CSS': ['*', '!important'],
|
|
595
|
-
'C++': ['vector', 'list', 'map'],
|
|
596
|
-
'HTML': ['type', 'xmlns', 'PUBLIC', 'http-equiv', 'src', 'style', 'lang', 'href', 'rel', 'content', 'xml', 'alt'], // attributes
|
|
597
|
-
'Markdown': ['type', 'src', 'style', 'lang', 'href', 'rel', 'content', 'valign', 'alt'], // attributes
|
|
598
|
-
};
|
|
599
|
-
this.statementsAndDeclarations = {
|
|
600
|
-
'JavaScript': ['for', 'if', 'else', 'case', 'switch', 'return', 'while', 'continue', 'break', 'do', 'import', 'from', 'throw', 'async', 'try', 'catch', 'await'],
|
|
601
|
-
'CSS': ['@', 'import'],
|
|
602
|
-
'C++': ['std', 'for', 'if', 'else', 'return', 'continue', 'break', 'case', 'switch', 'while', 'using', 'glm', 'spdlog'],
|
|
603
|
-
'GLSL': ['for', 'if', 'else', 'return', 'continue', 'break'],
|
|
604
|
-
'WGSL': ['const','for', 'if', 'else', 'return', 'continue', 'break', 'storage', 'read', 'uniform'],
|
|
605
|
-
'Rust': ['break', 'else', 'continue', 'for', 'if', 'loop', 'match', 'return', 'while', 'do', 'yield'],
|
|
606
|
-
'Python': ['if', 'raise', 'del', 'import', 'return', 'elif', 'try', 'else', 'while', 'as', 'except', 'with', 'assert', 'finally', 'yield', 'break', 'for', 'class', 'continue',
|
|
607
|
-
'global', 'pass'],
|
|
608
|
-
'Batch': ['if', 'IF', 'for', 'FOR', 'in', 'IN', 'do', 'DO', 'call', 'CALL', 'goto', 'GOTO', 'exit', 'EXIT']
|
|
609
|
-
};
|
|
610
|
-
this.symbols = {
|
|
611
|
-
'JavaScript': ['<', '>', '[', ']', '{', '}', '(', ')', ';', '=', '|', '||', '&', '&&', '?', '??'],
|
|
612
|
-
'C++': ['<', '>', '[', ']', '{', '}', '(', ')', ';', '=', '|', '||', '&', '&&', '?', '::', '*', '-', '+'],
|
|
613
|
-
'JSON': ['[', ']', '{', '}', '(', ')'],
|
|
614
|
-
'GLSL': ['[', ']', '{', '}', '(', ')'],
|
|
615
|
-
'WGSL': ['[', ']', '{', '}', '(', ')', '->'],
|
|
616
|
-
'CSS': ['{', '}', '(', ')', '*'],
|
|
617
|
-
'Rust': ['<', '>', '[', ']', '(', ')', '='],
|
|
618
|
-
'Python': ['<', '>', '[', ']', '(', ')', '='],
|
|
619
|
-
'Batch': ['[', ']', '(', ')', '%'],
|
|
620
|
-
'HTML': ['<', '>', '/']
|
|
621
|
-
};
|
|
555
|
+
this._blockCommentCache = [];
|
|
622
556
|
|
|
623
557
|
// Convert reserved word arrays to maps so we can search tokens faster
|
|
624
558
|
|
|
625
|
-
for( let lang in
|
|
626
|
-
for( let lang in
|
|
627
|
-
for( let lang in
|
|
628
|
-
for( let lang in
|
|
629
|
-
for( let lang in
|
|
630
|
-
for( let lang in
|
|
559
|
+
for( let lang in CodeEditor.keywords ) CodeEditor.keywords[lang] = CodeEditor.keywords[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
560
|
+
for( let lang in CodeEditor.utils ) CodeEditor.utils[lang] = CodeEditor.utils[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
561
|
+
for( let lang in CodeEditor.types ) CodeEditor.types[lang] = CodeEditor.types[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
562
|
+
for( let lang in CodeEditor.builtin ) CodeEditor.builtin[lang] = CodeEditor.builtin[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
563
|
+
for( let lang in CodeEditor.statementsAndDeclarations ) CodeEditor.statementsAndDeclarations[lang] = CodeEditor.statementsAndDeclarations[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
564
|
+
for( let lang in CodeEditor.symbols ) CodeEditor.symbols[lang] = CodeEditor.symbols[lang].reduce((a, v) => ({ ...a, [v]: true}), {});
|
|
631
565
|
|
|
632
566
|
// Action keys
|
|
633
567
|
|
|
@@ -881,7 +815,7 @@ class CodeEditor {
|
|
|
881
815
|
|
|
882
816
|
// Go to end of line if out of range
|
|
883
817
|
if( !letter || !canGoDown ) {
|
|
884
|
-
this.
|
|
818
|
+
this.cursorToPosition( cursor, Math.max(this.code.lines[ cursor.line ].length, 0) );
|
|
885
819
|
}
|
|
886
820
|
|
|
887
821
|
if( e.shiftKey ) {
|
|
@@ -1227,7 +1161,7 @@ class CodeEditor {
|
|
|
1227
1161
|
|
|
1228
1162
|
return;
|
|
1229
1163
|
}
|
|
1230
|
-
|
|
1164
|
+
|
|
1231
1165
|
let cursor = document.createElement( 'div' );
|
|
1232
1166
|
cursor.className = "cursor";
|
|
1233
1167
|
cursor.innerHTML = " ";
|
|
@@ -1348,6 +1282,8 @@ class CodeEditor {
|
|
|
1348
1282
|
|
|
1349
1283
|
this.restoreCursor( currentCursor, step.cursors[ i ] );
|
|
1350
1284
|
}
|
|
1285
|
+
|
|
1286
|
+
this._hideActiveLine();
|
|
1351
1287
|
}
|
|
1352
1288
|
|
|
1353
1289
|
_addRedoStep( cursor ) {
|
|
@@ -1837,8 +1773,7 @@ class CodeEditor {
|
|
|
1837
1773
|
if( !this.selection )
|
|
1838
1774
|
this.startSelection( cursor );
|
|
1839
1775
|
|
|
1840
|
-
|
|
1841
|
-
this.code.childNodes.forEach( e => e.classList.remove( 'active-line' ) );
|
|
1776
|
+
this._hideActiveLine();
|
|
1842
1777
|
|
|
1843
1778
|
// Update selection
|
|
1844
1779
|
if( !keep_range )
|
|
@@ -1994,14 +1929,21 @@ class CodeEditor {
|
|
|
1994
1929
|
const key = e.key ?? e.detail.key;
|
|
1995
1930
|
const target = e.detail.targetCursor;
|
|
1996
1931
|
|
|
1932
|
+
// Global keys
|
|
1933
|
+
|
|
1934
|
+
if( this._processGlobalKeys( e, key ) ) {
|
|
1935
|
+
// Stop propagation..
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
// By cursor keys
|
|
1940
|
+
|
|
1997
1941
|
if( target !== undefined )
|
|
1998
1942
|
{
|
|
1999
1943
|
this.processKeyAtTargetCursor( e, key, target );
|
|
2000
1944
|
return;
|
|
2001
1945
|
}
|
|
2002
1946
|
|
|
2003
|
-
// By cursor keys
|
|
2004
|
-
|
|
2005
1947
|
this._lastProcessedCursorIndex = null;
|
|
2006
1948
|
|
|
2007
1949
|
var lastProcessedCursor = null;
|
|
@@ -2033,10 +1975,6 @@ class CodeEditor {
|
|
|
2033
1975
|
cursorOffset.y += ( cursor.line - lastProcessedCursor.line );
|
|
2034
1976
|
}
|
|
2035
1977
|
|
|
2036
|
-
// Global keys
|
|
2037
|
-
|
|
2038
|
-
this._processGlobalKeys( e, key );
|
|
2039
|
-
|
|
2040
1978
|
// Clear tmp
|
|
2041
1979
|
|
|
2042
1980
|
delete this._lastProcessedCursorIndex;
|
|
@@ -2054,7 +1992,7 @@ class CodeEditor {
|
|
|
2054
1992
|
this._processGlobalKeys( e, key );
|
|
2055
1993
|
}
|
|
2056
1994
|
|
|
2057
|
-
|
|
1995
|
+
_processGlobalKeys( e, key ) {
|
|
2058
1996
|
|
|
2059
1997
|
let cursor = this._getCurrentCursor();
|
|
2060
1998
|
|
|
@@ -2065,30 +2003,48 @@ class CodeEditor {
|
|
|
2065
2003
|
switch( key.toLowerCase() ) {
|
|
2066
2004
|
case 'a': // select all
|
|
2067
2005
|
this.selectAll();
|
|
2068
|
-
|
|
2006
|
+
return true;
|
|
2007
|
+
case 'c': // k+c, comment line
|
|
2008
|
+
if( this.state.keyChain == 'k' ) {
|
|
2009
|
+
this._commentLines();
|
|
2010
|
+
return true;
|
|
2011
|
+
}
|
|
2012
|
+
return false;
|
|
2069
2013
|
case 'f': // find/search
|
|
2070
2014
|
this.showSearchBox();
|
|
2071
|
-
|
|
2015
|
+
return true;
|
|
2072
2016
|
case 'g': // find line
|
|
2073
2017
|
this.showSearchLineBox();
|
|
2074
|
-
|
|
2018
|
+
return true;
|
|
2019
|
+
case 'k': // shortcut chain
|
|
2020
|
+
this.state.keyChain = 'k';
|
|
2021
|
+
return true;
|
|
2075
2022
|
case 's': // save
|
|
2076
2023
|
this.onsave( this.getText() );
|
|
2077
|
-
|
|
2024
|
+
return true;
|
|
2025
|
+
case 'u': // k+u, uncomment line
|
|
2026
|
+
if( this.state.keyChain == 'k' ) {
|
|
2027
|
+
this._uncommentLines();
|
|
2028
|
+
return true;
|
|
2029
|
+
}
|
|
2030
|
+
return false;
|
|
2078
2031
|
case 'y': // redo
|
|
2079
2032
|
this._doRedo( cursor );
|
|
2080
|
-
|
|
2033
|
+
return true;
|
|
2081
2034
|
case 'z': // undo
|
|
2082
2035
|
this._doUndo( cursor );
|
|
2083
|
-
|
|
2036
|
+
return true;
|
|
2084
2037
|
case '+': // increase size
|
|
2085
2038
|
this._increaseFontSize();
|
|
2086
|
-
|
|
2039
|
+
return true;
|
|
2087
2040
|
case '-': // decrease size
|
|
2088
2041
|
this._decreaseFontSize();
|
|
2089
|
-
|
|
2042
|
+
return true;
|
|
2090
2043
|
}
|
|
2091
2044
|
}
|
|
2045
|
+
|
|
2046
|
+
this.state.keyChain = null;
|
|
2047
|
+
return false;
|
|
2092
2048
|
}
|
|
2093
2049
|
|
|
2094
2050
|
async _processKeyAtCursor( e, key, cursor ) {
|
|
@@ -2345,6 +2301,114 @@ class CodeEditor {
|
|
|
2345
2301
|
this.hideAutoCompleteBox();
|
|
2346
2302
|
}
|
|
2347
2303
|
|
|
2304
|
+
_commentLines() {
|
|
2305
|
+
|
|
2306
|
+
this.state.keyChain = null;
|
|
2307
|
+
|
|
2308
|
+
if( this.selection )
|
|
2309
|
+
{
|
|
2310
|
+
var cursor = this._getCurrentCursor();
|
|
2311
|
+
this._addUndoStep( cursor, true );
|
|
2312
|
+
|
|
2313
|
+
const selectedLines = this.code.lines.slice( this.selection.fromY, this.selection.toY );
|
|
2314
|
+
const minIdx = Math.min(...selectedLines.map( v => {
|
|
2315
|
+
var idx = firstNonspaceIndex( v );
|
|
2316
|
+
return idx < 0 ? 1e10 : idx;
|
|
2317
|
+
} ));
|
|
2318
|
+
|
|
2319
|
+
for( var i = this.selection.fromY; i <= this.selection.toY; ++i )
|
|
2320
|
+
{
|
|
2321
|
+
this._commentLine( cursor, i, minIdx );
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
else
|
|
2325
|
+
{
|
|
2326
|
+
for( let cursor of this.cursors.children )
|
|
2327
|
+
{
|
|
2328
|
+
this._addUndoStep( cursor, true );
|
|
2329
|
+
this._commentLine( cursor, cursor.line );
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
this.processLines();
|
|
2334
|
+
this._hideActiveLine();
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
_commentLine( cursor, line, minNonspaceIdx ) {
|
|
2338
|
+
|
|
2339
|
+
const lang = this.languages[ this.highlight ];
|
|
2340
|
+
|
|
2341
|
+
if( !( lang.singleLineComments ?? true ))
|
|
2342
|
+
return;
|
|
2343
|
+
|
|
2344
|
+
const token = ( lang.singleLineCommentToken ?? this.defaultSingleLineCommentToken ) + ' ';
|
|
2345
|
+
const string = this.code.lines[ line ];
|
|
2346
|
+
|
|
2347
|
+
let idx = firstNonspaceIndex( string );
|
|
2348
|
+
if( idx > -1 )
|
|
2349
|
+
{
|
|
2350
|
+
// Update idx using min of the selected lines (if necessary..)
|
|
2351
|
+
idx = minNonspaceIdx ?? idx;
|
|
2352
|
+
|
|
2353
|
+
this.code.lines[ line ] = [
|
|
2354
|
+
string.substring( 0, idx ),
|
|
2355
|
+
token,
|
|
2356
|
+
string.substring( idx )
|
|
2357
|
+
].join( '' );
|
|
2358
|
+
|
|
2359
|
+
this.cursorToString( cursor, token );
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
_uncommentLines() {
|
|
2364
|
+
|
|
2365
|
+
this.state.keyChain = null;
|
|
2366
|
+
|
|
2367
|
+
if( this.selection )
|
|
2368
|
+
{
|
|
2369
|
+
var cursor = this._getCurrentCursor();
|
|
2370
|
+
this._addUndoStep( cursor, true );
|
|
2371
|
+
|
|
2372
|
+
for( var i = this.selection.fromY; i <= this.selection.toY; ++i )
|
|
2373
|
+
{
|
|
2374
|
+
this._uncommentLine( cursor, i );
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
else
|
|
2378
|
+
{
|
|
2379
|
+
for( let cursor of this.cursors.children )
|
|
2380
|
+
{
|
|
2381
|
+
this._addUndoStep( cursor, true );
|
|
2382
|
+
this._uncommentLine( cursor, cursor.line );
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
this.processLines();
|
|
2387
|
+
this._hideActiveLine();
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
_uncommentLine( cursor, line ) {
|
|
2391
|
+
|
|
2392
|
+
const lang = this.languages[ this.highlight ];
|
|
2393
|
+
|
|
2394
|
+
if( !( lang.singleLineComments ?? true ))
|
|
2395
|
+
return;
|
|
2396
|
+
|
|
2397
|
+
const token = lang.singleLineCommentToken ?? this.defaultSingleLineCommentToken;
|
|
2398
|
+
const string = this.code.lines[ line ];
|
|
2399
|
+
|
|
2400
|
+
if( string.includes( token ) )
|
|
2401
|
+
{
|
|
2402
|
+
this.code.lines[ line ] = string.replace( token + ' ', '' );
|
|
2403
|
+
|
|
2404
|
+
// try deleting token + space, and then if not, delete only the token
|
|
2405
|
+
if( string.length == this.code.lines[ line ].length )
|
|
2406
|
+
this.code.lines[ line ] = string.replace( token, '' );
|
|
2407
|
+
|
|
2408
|
+
this.cursorToString( cursor, 'X'.repeat( Math.abs( string.length - this.code.lines[ line ].length ) ), true );
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2348
2412
|
action( key, deleteSelection, fn ) {
|
|
2349
2413
|
|
|
2350
2414
|
this.actions[ key ] = {
|
|
@@ -2379,6 +2443,7 @@ class CodeEditor {
|
|
|
2379
2443
|
processLines( mode ) {
|
|
2380
2444
|
|
|
2381
2445
|
var code_html = "";
|
|
2446
|
+
this._blockCommentCache.length = 0;
|
|
2382
2447
|
|
|
2383
2448
|
// Reset all lines content
|
|
2384
2449
|
this.code.innerHTML = "";
|
|
@@ -2423,6 +2488,13 @@ class CodeEditor {
|
|
|
2423
2488
|
|
|
2424
2489
|
processLine( linenum, force ) {
|
|
2425
2490
|
|
|
2491
|
+
// Check if we are in block comment sections..
|
|
2492
|
+
if( !force && this._inBlockCommentSection( linenum ) )
|
|
2493
|
+
{
|
|
2494
|
+
this.processLines();
|
|
2495
|
+
return;
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2426
2498
|
const lang = this.languages[ this.highlight ];
|
|
2427
2499
|
const local_line_num = this.toLocalLine( linenum );
|
|
2428
2500
|
const gutter_line = "<span class='line-gutter'>" + (linenum + 1) + "</span>";
|
|
@@ -2431,6 +2503,7 @@ class CodeEditor {
|
|
|
2431
2503
|
if( !force ) // Single line update
|
|
2432
2504
|
{
|
|
2433
2505
|
this.code.childNodes[ local_line_num ].innerHTML = gutter_line + html;
|
|
2506
|
+
this._setActiveLine( linenum );
|
|
2434
2507
|
this._clearTmpVariables();
|
|
2435
2508
|
}
|
|
2436
2509
|
else // Update all lines at once
|
|
@@ -2457,6 +2530,9 @@ class CodeEditor {
|
|
|
2457
2530
|
return UPDATE_LINE( linestring );
|
|
2458
2531
|
}
|
|
2459
2532
|
|
|
2533
|
+
this._currentLineNumber = linenum;
|
|
2534
|
+
this._currentLineString = linestring;
|
|
2535
|
+
|
|
2460
2536
|
const tokensToEvaluate = this._getTokensFromLine( linestring );
|
|
2461
2537
|
|
|
2462
2538
|
if( !tokensToEvaluate.length )
|
|
@@ -2487,7 +2563,7 @@ class CodeEditor {
|
|
|
2487
2563
|
{
|
|
2488
2564
|
const blockCommentsToken = ( lang.blockCommentsTokens ?? this.defaultBlockCommentTokens )[ 0 ];
|
|
2489
2565
|
if( token.substr( 0, blockCommentsToken.length ) == blockCommentsToken )
|
|
2490
|
-
this._buildingBlockComment =
|
|
2566
|
+
this._buildingBlockComment = linenum;
|
|
2491
2567
|
}
|
|
2492
2568
|
|
|
2493
2569
|
line_inner_html += this._evaluateToken( {
|
|
@@ -2525,19 +2601,12 @@ class CodeEditor {
|
|
|
2525
2601
|
var matches = (linestring.substring( 0, idx ).match( re ) || []);
|
|
2526
2602
|
return (matches.length % 2) !== 0;
|
|
2527
2603
|
} );
|
|
2528
|
-
err |= stringKeys.some( function(v) {
|
|
2529
|
-
var re = new RegExp( v, "g" );
|
|
2530
|
-
var matches = (linestring.substring( idx ).match( re ) || []);
|
|
2531
|
-
return (matches.length % 2) !== 0;
|
|
2532
|
-
} );
|
|
2533
2604
|
return err ? undefined : idx;
|
|
2534
2605
|
}
|
|
2535
2606
|
}
|
|
2536
2607
|
|
|
2537
2608
|
_getTokensFromLine( linestring, skipNonWords ) {
|
|
2538
2609
|
|
|
2539
|
-
this._currentLineString = linestring;
|
|
2540
|
-
|
|
2541
2610
|
// Check if line comment
|
|
2542
2611
|
const ogLine = linestring;
|
|
2543
2612
|
const hasCommentIdx = this._lineHasComment( linestring );
|
|
@@ -2594,12 +2663,12 @@ class CodeEditor {
|
|
|
2594
2663
|
|
|
2595
2664
|
if( this.highlight == 'C++' || this.highlight == 'CSS' )
|
|
2596
2665
|
{
|
|
2597
|
-
var idx = tokens.slice( offset ).findIndex( ( value, index ) => this.
|
|
2666
|
+
var idx = tokens.slice( offset ).findIndex( ( value, index ) => this._isNumber( value ) );
|
|
2598
2667
|
if( idx > -1 )
|
|
2599
2668
|
{
|
|
2600
2669
|
idx += offset; // Add offset to compute within the whole array of tokens
|
|
2601
2670
|
let data = tokens[ idx ] + tokens[ ++idx ];
|
|
2602
|
-
while( this.
|
|
2671
|
+
while( this._isNumber( data ) )
|
|
2603
2672
|
{
|
|
2604
2673
|
tokens[ idx - 1 ] += tokens[ idx ];
|
|
2605
2674
|
tokens.splice( idx, 1 );
|
|
@@ -2647,7 +2716,7 @@ class CodeEditor {
|
|
|
2647
2716
|
// Manage strings
|
|
2648
2717
|
this._stringEnded = false;
|
|
2649
2718
|
|
|
2650
|
-
if( usePreviousTokenToCheckString || (
|
|
2719
|
+
if( usePreviousTokenToCheckString || ( this._buildingBlockComment === undefined && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) ) )
|
|
2651
2720
|
{
|
|
2652
2721
|
const checkIfStringEnded = t => {
|
|
2653
2722
|
const idx = Object.values( customStringKeys ).indexOf( t );
|
|
@@ -2696,22 +2765,22 @@ class CodeEditor {
|
|
|
2696
2765
|
else if( this._buildingString != undefined )
|
|
2697
2766
|
discardToken = this._appendStringToken( token );
|
|
2698
2767
|
|
|
2699
|
-
else if( this._mustHightlightWord( token,
|
|
2768
|
+
else if( this._mustHightlightWord( token, CodeEditor.keywords ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
|
|
2700
2769
|
token_classname = "cm-kwd";
|
|
2701
2770
|
|
|
2702
|
-
else if( this._mustHightlightWord( token,
|
|
2771
|
+
else if( this._mustHightlightWord( token, CodeEditor.builtin ) && ( lang.tags ?? false ? ( this._enclosedByTokens( token, tokenIndex, '<', '>' ) ) : true ) )
|
|
2703
2772
|
token_classname = "cm-bln";
|
|
2704
2773
|
|
|
2705
|
-
else if( this._mustHightlightWord( token,
|
|
2774
|
+
else if( this._mustHightlightWord( token, CodeEditor.statementsAndDeclarations ) )
|
|
2706
2775
|
token_classname = "cm-std";
|
|
2707
2776
|
|
|
2708
|
-
else if( this._mustHightlightWord( token,
|
|
2777
|
+
else if( this._mustHightlightWord( token, CodeEditor.symbols ) )
|
|
2709
2778
|
token_classname = "cm-sym";
|
|
2710
2779
|
|
|
2711
2780
|
else if( token.substr( 0, singleLineCommentToken.length ) == singleLineCommentToken )
|
|
2712
2781
|
token_classname = "cm-com";
|
|
2713
2782
|
|
|
2714
|
-
else if( this.
|
|
2783
|
+
else if( this._isNumber( token ) || this._isNumber( token.replace(/[px]|[em]|%/g,'') ) )
|
|
2715
2784
|
token_classname = "cm-dec";
|
|
2716
2785
|
|
|
2717
2786
|
else if( this._isCSSClass( token, prev, next ) )
|
|
@@ -2723,7 +2792,7 @@ class CodeEditor {
|
|
|
2723
2792
|
else if ( highlight == 'batch' && ( token == '@' || prev == ':' || prev == '@' ) )
|
|
2724
2793
|
token_classname = "cm-kwd";
|
|
2725
2794
|
|
|
2726
|
-
else if (
|
|
2795
|
+
else if ( [ 'cpp', 'wgsl', 'glsl' ].indexOf( highlight ) > -1 && token.includes( '#' ) ) // C++ preprocessor
|
|
2727
2796
|
token_classname = "cm-ppc";
|
|
2728
2797
|
|
|
2729
2798
|
else if ( highlight == 'cpp' && prev == '<' && (next == '>' || next == '*') ) // Defining template type in C++
|
|
@@ -2748,9 +2817,10 @@ class CodeEditor {
|
|
|
2748
2817
|
token_classname = "cm-mtd";
|
|
2749
2818
|
|
|
2750
2819
|
|
|
2751
|
-
if( usesBlockComments && this._buildingBlockComment
|
|
2820
|
+
if( usesBlockComments && this._buildingBlockComment != undefined
|
|
2752
2821
|
&& token.substr( 0, blockCommentsTokens[ 1 ].length ) == blockCommentsTokens[ 1 ] )
|
|
2753
2822
|
{
|
|
2823
|
+
this._blockCommentCache.push( new LX.vec2( this._buildingBlockComment, this._currentLineNumber ) );
|
|
2754
2824
|
delete this._buildingBlockComment;
|
|
2755
2825
|
}
|
|
2756
2826
|
|
|
@@ -2799,16 +2869,27 @@ class CodeEditor {
|
|
|
2799
2869
|
_enclosedByTokens( token, tokenIndex, tagStart, tagEnd ) {
|
|
2800
2870
|
|
|
2801
2871
|
const tokenStartIndex = this._currentTokenPositions[ tokenIndex ];
|
|
2802
|
-
const tagStartIndex = indexOfFrom(this._currentLineString, tagStart, tokenStartIndex, true );
|
|
2872
|
+
const tagStartIndex = indexOfFrom( this._currentLineString, tagStart, tokenStartIndex, true );
|
|
2803
2873
|
if( tagStartIndex < 0 ) // Not found..
|
|
2804
2874
|
return;
|
|
2805
|
-
const tagEndIndex = indexOfFrom(this._currentLineString, tagEnd, tokenStartIndex );
|
|
2875
|
+
const tagEndIndex = indexOfFrom( this._currentLineString, tagEnd, tokenStartIndex );
|
|
2806
2876
|
if( tagEndIndex < 0 ) // Not found..
|
|
2807
2877
|
return;
|
|
2808
2878
|
|
|
2809
2879
|
return ( tagStartIndex < tokenStartIndex ) && ( tagEndIndex >= ( tokenStartIndex + token.length ) );
|
|
2810
2880
|
}
|
|
2811
2881
|
|
|
2882
|
+
_inBlockCommentSection( line ) {
|
|
2883
|
+
|
|
2884
|
+
for( var section of this._blockCommentCache )
|
|
2885
|
+
{
|
|
2886
|
+
if( line >= section.x && line <= section.y )
|
|
2887
|
+
return true;
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2890
|
+
return false;
|
|
2891
|
+
}
|
|
2892
|
+
|
|
2812
2893
|
_isCSSClass( token, prev, next ) {
|
|
2813
2894
|
|
|
2814
2895
|
if( this.highlight != 'CSS' )
|
|
@@ -2819,20 +2900,26 @@ class CodeEditor {
|
|
|
2819
2900
|
|| ( token[ 0 ] == '#' && prev != ':' ) );
|
|
2820
2901
|
}
|
|
2821
2902
|
|
|
2822
|
-
|
|
2903
|
+
_isNumber( token ) {
|
|
2823
2904
|
|
|
2824
2905
|
if(this.highlight == 'C++')
|
|
2825
2906
|
{
|
|
2826
2907
|
if( token.lastChar == 'f' )
|
|
2827
|
-
return this.
|
|
2908
|
+
return this._isNumber( token.substring(0, token.length - 1) )
|
|
2828
2909
|
else if( token.lastChar == 'u' )
|
|
2829
|
-
return !(token.includes('.')) && this.
|
|
2910
|
+
return !(token.includes('.')) && this._isNumber( token.substring(0, token.length - 1) );
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2913
|
+
else if(this.highlight == 'WGSL')
|
|
2914
|
+
{
|
|
2915
|
+
if( token.lastChar == 'u' )
|
|
2916
|
+
return !(token.includes('.')) && this._isNumber( token.substring(0, token.length - 1) );
|
|
2830
2917
|
}
|
|
2831
2918
|
|
|
2832
2919
|
else if(this.highlight == 'CSS')
|
|
2833
2920
|
{
|
|
2834
2921
|
if( token.lastChar == '%' )
|
|
2835
|
-
return this.
|
|
2922
|
+
return this._isNumber( token.substring(0, token.length - 1) )
|
|
2836
2923
|
}
|
|
2837
2924
|
|
|
2838
2925
|
return token.length && token != ' ' && !Number.isNaN(+token);
|
|
@@ -2841,7 +2928,7 @@ class CodeEditor {
|
|
|
2841
2928
|
_isType( token, prev, next ) {
|
|
2842
2929
|
|
|
2843
2930
|
// Common case
|
|
2844
|
-
if( this._mustHightlightWord( token,
|
|
2931
|
+
if( this._mustHightlightWord( token, CodeEditor.types ) )
|
|
2845
2932
|
return true;
|
|
2846
2933
|
|
|
2847
2934
|
if( this.highlight == 'JavaScript' )
|
|
@@ -2854,11 +2941,12 @@ class CodeEditor {
|
|
|
2854
2941
|
}
|
|
2855
2942
|
else if ( this.highlight == 'WGSL' )
|
|
2856
2943
|
{
|
|
2857
|
-
const
|
|
2858
|
-
return
|
|
2859
|
-
|
|
2944
|
+
const not_kwd = !this._mustHightlightWord( token, CodeEditor.keywords );
|
|
2945
|
+
return (prev == 'struct' && next == '{') ||
|
|
2946
|
+
(not_kwd && prev == ':' && next == ';') ||
|
|
2947
|
+
( not_kwd &&
|
|
2860
2948
|
( prev == ':' && next == ')' || prev == ':' && next == ',' || prev == '>' && next == '{'
|
|
2861
|
-
|| prev == '<' && next == ',' || prev == '<' && next == '>' || prev == '>' && !next ));
|
|
2949
|
+
|| prev == '<' && next == ',' || prev == '<' && next == '>' || prev == '>' && token != ';' && !next ));
|
|
2862
2950
|
}
|
|
2863
2951
|
}
|
|
2864
2952
|
|
|
@@ -3486,11 +3574,11 @@ class CodeEditor {
|
|
|
3486
3574
|
|
|
3487
3575
|
// Add language special keys...
|
|
3488
3576
|
suggestions = suggestions.concat(
|
|
3489
|
-
Object.keys(
|
|
3490
|
-
Object.keys(
|
|
3491
|
-
Object.keys(
|
|
3492
|
-
Object.keys(
|
|
3493
|
-
Object.keys(
|
|
3577
|
+
Object.keys( CodeEditor.builtin[ this.highlight ] ?? {} ),
|
|
3578
|
+
Object.keys( CodeEditor.keywords[ this.highlight ] ?? {} ),
|
|
3579
|
+
Object.keys( CodeEditor.statementsAndDeclarations[ this.highlight ] ?? {} ),
|
|
3580
|
+
Object.keys( CodeEditor.types[ this.highlight ] ?? {} ),
|
|
3581
|
+
Object.keys( CodeEditor.utils[ this.highlight ] ?? {} )
|
|
3494
3582
|
);
|
|
3495
3583
|
|
|
3496
3584
|
// Add words in current tab plus remove current word
|
|
@@ -3512,9 +3600,9 @@ class CodeEditor {
|
|
|
3512
3600
|
|
|
3513
3601
|
var icon = document.createElement( 'a' );
|
|
3514
3602
|
|
|
3515
|
-
if( this._mustHightlightWord( s,
|
|
3603
|
+
if( this._mustHightlightWord( s, CodeEditor.utils ) )
|
|
3516
3604
|
icon.className = "fa fa-cube";
|
|
3517
|
-
else if( this._mustHightlightWord( s,
|
|
3605
|
+
else if( this._mustHightlightWord( s, CodeEditor.types ) )
|
|
3518
3606
|
icon.className = "fa fa-code";
|
|
3519
3607
|
else
|
|
3520
3608
|
icon.className = "fa fa-font";
|
|
@@ -3762,7 +3850,7 @@ class CodeEditor {
|
|
|
3762
3850
|
|
|
3763
3851
|
goToLine( line ) {
|
|
3764
3852
|
|
|
3765
|
-
if( !this.
|
|
3853
|
+
if( !this._isNumber( line ) )
|
|
3766
3854
|
return;
|
|
3767
3855
|
|
|
3768
3856
|
this.codeScroller.scrollTo( 0, Math.max( line - 15 ) * this.lineHeight );
|
|
@@ -3809,6 +3897,11 @@ class CodeEditor {
|
|
|
3809
3897
|
}
|
|
3810
3898
|
}
|
|
3811
3899
|
|
|
3900
|
+
_hideActiveLine() {
|
|
3901
|
+
|
|
3902
|
+
this.code.querySelectorAll( '.active-line' ).forEach( e => e.classList.remove( 'active-line' ) );
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3812
3905
|
_increaseFontSize() {
|
|
3813
3906
|
|
|
3814
3907
|
// Change font size
|
|
@@ -3864,6 +3957,7 @@ class CodeEditor {
|
|
|
3864
3957
|
_clearTmpVariables() {
|
|
3865
3958
|
|
|
3866
3959
|
delete this._currentLineString;
|
|
3960
|
+
delete this._currentLineNumber;
|
|
3867
3961
|
delete this._buildingString;
|
|
3868
3962
|
delete this._pendingString;
|
|
3869
3963
|
delete this._buildingBlockComment;
|
|
@@ -3871,6 +3965,87 @@ class CodeEditor {
|
|
|
3871
3965
|
}
|
|
3872
3966
|
}
|
|
3873
3967
|
|
|
3968
|
+
CodeEditor.keywords = {
|
|
3969
|
+
|
|
3970
|
+
'JavaScript': ['var', 'let', 'const', 'this', 'in', 'of', 'true', 'false', 'new', 'function', 'NaN', 'static', 'class', 'constructor', 'null', 'typeof', 'debugger', 'abstract',
|
|
3971
|
+
'arguments', 'extends', 'instanceof'],
|
|
3972
|
+
'C++': ['int', 'float', 'double', 'bool', 'char', 'wchar_t', 'const', 'static_cast', 'dynamic_cast', 'new', 'delete', 'void', 'true', 'false', 'auto', 'struct', 'typedef', 'nullptr',
|
|
3973
|
+
'NULL', 'unsigned', 'namespace'],
|
|
3974
|
+
'JSON': ['true', 'false'],
|
|
3975
|
+
'GLSL': ['true', 'false', 'function', 'int', 'float', 'vec2', 'vec3', 'vec4', 'mat2x2', 'mat3x3', 'mat4x4', 'struct'],
|
|
3976
|
+
'CSS': ['body', 'html', 'canvas', 'div', 'input', 'span', '.'],
|
|
3977
|
+
'WGSL': ['var', 'let', 'true', 'false', 'fn', 'bool', 'u32', 'i32', 'f16', 'f32', 'vec2f', 'vec3f', 'vec4f', 'mat2x2f', 'mat3x3f', 'mat4x4f', 'array', 'atomic', 'struct',
|
|
3978
|
+
'sampler', 'sampler_comparison', 'texture_depth_2d', 'texture_depth_2d_array', 'texture_depth_cube', 'texture_depth_cube_array', 'texture_depth_multisampled_2d',
|
|
3979
|
+
'texture_external', 'texture_1d', 'texture_2d', 'texture_2d_array', 'texture_3d', 'texture_cube', 'texture_cube_array', 'texture_storage_1d', 'texture_storage_2d',
|
|
3980
|
+
'texture_storage_2d_array', 'texture_storage_3d', 'vec2u', 'vec3u', 'vec4u'],
|
|
3981
|
+
'Rust': ['as', 'const', 'crate', 'enum', 'extern', 'false', 'fn', 'impl', 'in', 'let', 'mod', 'move', 'mut', 'pub', 'ref', 'self', 'Self', 'static', 'struct', 'super', 'trait', 'true',
|
|
3982
|
+
'type', 'unsafe', 'use', 'where', 'abstract', 'become', 'box', 'final', 'macro', 'override', 'priv', 'typeof', 'unsized', 'virtual'],
|
|
3983
|
+
'Python': ['False', 'def', 'None', 'True', 'in', 'is', 'and', 'lambda', 'nonlocal', 'not', 'or'],
|
|
3984
|
+
'Batch': ['set', 'SET', 'echo', 'ECHO', 'off', 'OFF', 'del', 'DEL', 'defined', 'DEFINED', 'setlocal', 'SETLOCAL', 'enabledelayedexpansion', 'ENABLEDELAYEDEXPANSION', 'driverquery',
|
|
3985
|
+
'DRIVERQUERY', 'print', 'PRINT'],
|
|
3986
|
+
'HTML': ['html', 'meta', 'title', 'link', 'script', 'body', 'DOCTYPE', 'head', 'br', 'i', 'a', 'li', 'img', 'tr', 'td', 'h1', 'h2', 'h3', 'h4', 'h5'],
|
|
3987
|
+
'Markdown': ['br', 'i', 'a', 'li', 'img', 'table', 'title', 'tr', 'td', 'h1', 'h2', 'h3', 'h4', 'h5'],
|
|
3988
|
+
};
|
|
3989
|
+
|
|
3990
|
+
CodeEditor.utils = { // These ones don't have hightlight, used as suggestions to autocomplete only...
|
|
3991
|
+
|
|
3992
|
+
'JavaScript': ['querySelector', 'body', 'addEventListener', 'removeEventListener', 'remove', 'sort', 'keys', 'filter', 'isNaN', 'parseFloat', 'parseInt', 'EPSILON', 'isFinite',
|
|
3993
|
+
'bind', 'prototype', 'length', 'assign', 'entries', 'values', 'concat', 'substring', 'substr', 'splice', 'slice', 'buffer', 'appendChild', 'createElement', 'prompt',
|
|
3994
|
+
'alert'],
|
|
3995
|
+
'WGSL': ['textureSample'],
|
|
3996
|
+
'Python': ['abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod',
|
|
3997
|
+
'enumerate', 'eval', 'exec', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
|
|
3998
|
+
'issubclass', 'iter', 'len', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr',
|
|
3999
|
+
'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
|
|
4000
|
+
};
|
|
4001
|
+
|
|
4002
|
+
CodeEditor.types = {
|
|
4003
|
+
|
|
4004
|
+
'JavaScript': ['Object', 'String', 'Function', 'Boolean', 'Symbol', 'Error', 'Number', 'TextEncoder', 'TextDecoder'],
|
|
4005
|
+
'Rust': ['u128'],
|
|
4006
|
+
'Python': ['int', 'type', 'float', 'map', 'list', 'ArithmeticError', 'AssertionError', 'AttributeError', 'Exception', 'EOFError', 'FloatingPointError', 'GeneratorExit',
|
|
4007
|
+
'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotImplementedError', 'OSError',
|
|
4008
|
+
'OverflowError', 'ReferenceError', 'RuntimeError', 'StopIteration', 'SyntaxError', 'TabError', 'SystemError', 'SystemExit', 'TypeError', 'UnboundLocalError',
|
|
4009
|
+
'UnicodeError', 'UnicodeEncodeError', 'UnicodeDecodeError', 'UnicodeTranslateError', 'ValueError', 'ZeroDivisionError'],
|
|
4010
|
+
'C++': ['uint8_t', 'uint16_t', 'uint32_t']
|
|
4011
|
+
};
|
|
4012
|
+
|
|
4013
|
+
CodeEditor.builtin = {
|
|
4014
|
+
|
|
4015
|
+
'JavaScript': ['document', 'console', 'window', 'navigator', 'performance'],
|
|
4016
|
+
'CSS': ['*', '!important'],
|
|
4017
|
+
'C++': ['vector', 'list', 'map'],
|
|
4018
|
+
'HTML': ['type', 'xmlns', 'PUBLIC', 'http-equiv', 'src', 'style', 'lang', 'href', 'rel', 'content', 'xml', 'alt'], // attributes
|
|
4019
|
+
'Markdown': ['type', 'src', 'style', 'lang', 'href', 'rel', 'content', 'valign', 'alt'], // attributes
|
|
4020
|
+
};
|
|
4021
|
+
|
|
4022
|
+
CodeEditor.statementsAndDeclarations = {
|
|
4023
|
+
|
|
4024
|
+
'JavaScript': ['for', 'if', 'else', 'case', 'switch', 'return', 'while', 'continue', 'break', 'do', 'import', 'from', 'throw', 'async', 'try', 'catch', 'await'],
|
|
4025
|
+
'CSS': ['@', 'import'],
|
|
4026
|
+
'C++': ['std', 'for', 'if', 'else', 'return', 'continue', 'break', 'case', 'switch', 'while', 'using', 'glm', 'spdlog'],
|
|
4027
|
+
'GLSL': ['for', 'if', 'else', 'return', 'continue', 'break'],
|
|
4028
|
+
'WGSL': ['const','for', 'if', 'else', 'return', 'continue', 'break', 'storage', 'read', 'read_write', 'uniform', 'function', 'workgroup'],
|
|
4029
|
+
'Rust': ['break', 'else', 'continue', 'for', 'if', 'loop', 'match', 'return', 'while', 'do', 'yield'],
|
|
4030
|
+
'Python': ['if', 'raise', 'del', 'import', 'return', 'elif', 'try', 'else', 'while', 'as', 'except', 'with', 'assert', 'finally', 'yield', 'break', 'for', 'class', 'continue',
|
|
4031
|
+
'global', 'pass'],
|
|
4032
|
+
'Batch': ['if', 'IF', 'for', 'FOR', 'in', 'IN', 'do', 'DO', 'call', 'CALL', 'goto', 'GOTO', 'exit', 'EXIT']
|
|
4033
|
+
};
|
|
4034
|
+
|
|
4035
|
+
CodeEditor.symbols = {
|
|
4036
|
+
|
|
4037
|
+
'JavaScript': ['<', '>', '[', ']', '{', '}', '(', ')', ';', '=', '|', '||', '&', '&&', '?', '??'],
|
|
4038
|
+
'C++': ['<', '>', '[', ']', '{', '}', '(', ')', ';', '=', '|', '||', '&', '&&', '?', '::', '*', '-', '+'],
|
|
4039
|
+
'JSON': ['[', ']', '{', '}', '(', ')'],
|
|
4040
|
+
'GLSL': ['[', ']', '{', '}', '(', ')'],
|
|
4041
|
+
'WGSL': ['[', ']', '{', '}', '(', ')', '->'],
|
|
4042
|
+
'CSS': ['{', '}', '(', ')', '*'],
|
|
4043
|
+
'Rust': ['<', '>', '[', ']', '(', ')', '='],
|
|
4044
|
+
'Python': ['<', '>', '[', ']', '(', ')', '='],
|
|
4045
|
+
'Batch': ['[', ']', '(', ')', '%'],
|
|
4046
|
+
'HTML': ['<', '>', '/']
|
|
4047
|
+
};
|
|
4048
|
+
|
|
3874
4049
|
LX.CodeEditor = CodeEditor;
|
|
3875
4050
|
|
|
3876
4051
|
export { CodeEditor };
|
package/build/lexgui.css
CHANGED
|
@@ -3125,7 +3125,7 @@ pre .line-gutter {
|
|
|
3125
3125
|
|
|
3126
3126
|
/* Common */
|
|
3127
3127
|
.cm-str { color: #ca7d59; } /* string */
|
|
3128
|
-
.cm-std { color: #
|
|
3128
|
+
.cm-std { color: #d181d1; } /* statements & declarations */
|
|
3129
3129
|
.cm-kwd { color: #2194ce; } /* keyword */
|
|
3130
3130
|
.cm-com { color: #5cab5a; } /* comment */
|
|
3131
3131
|
|
|
@@ -3152,16 +3152,16 @@ pre .line-gutter {
|
|
|
3152
3152
|
.cm-sym.json { color: #cf6dcf; } /* symbol */
|
|
3153
3153
|
|
|
3154
3154
|
.cm-typ.glsl { color: #36c0b0; } /* type */
|
|
3155
|
-
.cm-bln.glsl { color: #cfc159; } /* builtin */
|
|
3156
3155
|
.cm-dec.glsl { color: #b1ce9b; } /* decimal */
|
|
3157
3156
|
.cm-sym.glsl { color: #f9cb20; } /* symbol */
|
|
3158
3157
|
.cm-mtd.glsl { color: #e0cc68; } /* method */
|
|
3159
3158
|
|
|
3160
3159
|
.cm-typ.wgsl { color: #36c0b0; } /* type */
|
|
3161
|
-
.cm-bln.wgsl { color: #cfc159; } /* builtin */
|
|
3162
3160
|
.cm-dec.wgsl { color: #b1ce9b; } /* decimal */
|
|
3161
|
+
.cm-mtd.wgsl { color: #dfe093; } /* method */
|
|
3163
3162
|
.cm-sym.wgsl { color: #f9cb20; } /* symbol */
|
|
3164
|
-
.cm-
|
|
3163
|
+
.cm-ppc.wgsl { color: #99caf1; } /* preprocessor */
|
|
3164
|
+
|
|
3165
3165
|
|
|
3166
3166
|
.cm-typ.rust { color: #36c0b0; } /* type */
|
|
3167
3167
|
.cm-dec.rust { color: #b1ce9b; } /* decimal */
|
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.25",
|
|
16
16
|
ready: false,
|
|
17
17
|
components: [], // specific pre-build components
|
|
18
18
|
signals: {} // events and triggers
|
|
@@ -2179,6 +2179,8 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
|
|
|
2179
2179
|
|
|
2180
2180
|
if( this.onSetValue )
|
|
2181
2181
|
this.onSetValue( value );
|
|
2182
|
+
|
|
2183
|
+
console.warn("Can't set value of " + this.typeName());
|
|
2182
2184
|
}
|
|
2183
2185
|
|
|
2184
2186
|
oncontextmenu(e) {
|
|
@@ -3029,6 +3031,7 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
|
|
|
3029
3031
|
let domName = document.createElement('div');
|
|
3030
3032
|
domName.className = "lexwidgetname";
|
|
3031
3033
|
domName.innerHTML = name || "";
|
|
3034
|
+
domName.title = options.title ?? domName.innerHTML;
|
|
3032
3035
|
domName.style.width = options.nameWidth || LX.DEFAULT_NAME_WIDTH;
|
|
3033
3036
|
element.appendChild(domName);
|
|
3034
3037
|
element.domName = domName;
|
|
@@ -4288,47 +4291,70 @@ console.warn( 'Script "build/lexgui.js" is depracated and will be removed soon.
|
|
|
4288
4291
|
|
|
4289
4292
|
addList( name, values, value, callback, options = {} ) {
|
|
4290
4293
|
|
|
4291
|
-
let widget = this.create_widget(name, Widget.LIST, options);
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4294
|
+
let widget = this.create_widget( name, Widget.LIST, options );
|
|
4295
|
+
|
|
4296
|
+
widget.onGetValue = () => {
|
|
4297
|
+
return value;
|
|
4298
|
+
};
|
|
4299
|
+
|
|
4300
|
+
widget.onSetValue = ( newValue ) => {
|
|
4301
|
+
listContainer.querySelectorAll( '.lexlistitem' ).forEach( e => e.classList.remove( 'selected' ) );
|
|
4302
|
+
const idx = values.indexOf( newValue );
|
|
4303
|
+
if( idx == -1 ) return;
|
|
4304
|
+
listContainer.children[ idx ].classList.toggle( 'selected' );
|
|
4305
|
+
value = newValue;
|
|
4306
|
+
this._trigger( new IEvent( name, newValue ), callback );
|
|
4307
|
+
};
|
|
4308
|
+
|
|
4309
|
+
widget.updateValues = ( newValues ) => {
|
|
4310
|
+
|
|
4311
|
+
values = newValues;
|
|
4312
|
+
listContainer.innerHTML = "";
|
|
4313
|
+
|
|
4314
|
+
for( let i = 0; i < values.length; ++i )
|
|
4306
4315
|
{
|
|
4307
|
-
icon =
|
|
4308
|
-
|
|
4316
|
+
let icon = null;
|
|
4317
|
+
let itemValue = values[ i ];
|
|
4318
|
+
|
|
4319
|
+
if( itemValue.constructor === Array )
|
|
4320
|
+
{
|
|
4321
|
+
icon = itemValue[ 1 ];
|
|
4322
|
+
itemValue = itemValue[ 0 ];
|
|
4323
|
+
}
|
|
4324
|
+
|
|
4325
|
+
let listElement = document.createElement( 'div' );
|
|
4326
|
+
listElement.className = "lexlistitem" + ( value == itemValue ? " selected" : "" );
|
|
4327
|
+
listElement.innerHTML = "<span>" + itemValue + "</span>" + ( icon ? "<a class='" + icon + "'></a>" : "" );
|
|
4328
|
+
|
|
4329
|
+
listElement.addEventListener( 'click', e => {
|
|
4330
|
+
listContainer.querySelectorAll( '.lexlistitem' ).forEach( e => e.classList.remove( 'selected' ) );
|
|
4331
|
+
listElement.classList.toggle( 'selected' );
|
|
4332
|
+
value = itemValue;
|
|
4333
|
+
this._trigger( new IEvent( name, itemValue, e ), callback );
|
|
4334
|
+
});
|
|
4335
|
+
|
|
4336
|
+
listContainer.appendChild( listElement );
|
|
4309
4337
|
}
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
}
|
|
4323
|
-
|
|
4338
|
+
};
|
|
4339
|
+
|
|
4340
|
+
let element = widget.domEl;
|
|
4341
|
+
|
|
4342
|
+
// Show list
|
|
4343
|
+
|
|
4344
|
+
let listContainer = document.createElement( 'div' );
|
|
4345
|
+
listContainer.className = "lexlist";
|
|
4346
|
+
listContainer.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
4347
|
+
|
|
4348
|
+
widget.updateValues( values );
|
|
4349
|
+
|
|
4324
4350
|
// Remove branch padding and margins
|
|
4325
|
-
if(!widget.name) {
|
|
4351
|
+
if( !widget.name ) {
|
|
4326
4352
|
element.className += " noname";
|
|
4327
|
-
|
|
4353
|
+
listContainer.style.width = "100%";
|
|
4328
4354
|
}
|
|
4329
|
-
|
|
4330
|
-
element.appendChild(
|
|
4331
|
-
|
|
4355
|
+
|
|
4356
|
+
element.appendChild( listContainer );
|
|
4357
|
+
|
|
4332
4358
|
return widget;
|
|
4333
4359
|
}
|
|
4334
4360
|
|
package/build/lexgui.module.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
var LX = {
|
|
11
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.25",
|
|
12
12
|
ready: false,
|
|
13
13
|
components: [], // specific pre-build components
|
|
14
14
|
signals: {} // events and triggers
|
|
@@ -2175,6 +2175,8 @@ class Widget {
|
|
|
2175
2175
|
|
|
2176
2176
|
if( this.onSetValue )
|
|
2177
2177
|
this.onSetValue( value );
|
|
2178
|
+
|
|
2179
|
+
console.warn("Can't set value of " + this.typeName());
|
|
2178
2180
|
}
|
|
2179
2181
|
|
|
2180
2182
|
oncontextmenu(e) {
|
|
@@ -3025,6 +3027,7 @@ class Panel {
|
|
|
3025
3027
|
let domName = document.createElement('div');
|
|
3026
3028
|
domName.className = "lexwidgetname";
|
|
3027
3029
|
domName.innerHTML = name || "";
|
|
3030
|
+
domName.title = options.title ?? domName.innerHTML;
|
|
3028
3031
|
domName.style.width = options.nameWidth || LX.DEFAULT_NAME_WIDTH;
|
|
3029
3032
|
element.appendChild(domName);
|
|
3030
3033
|
element.domName = domName;
|
|
@@ -4284,46 +4287,69 @@ class Panel {
|
|
|
4284
4287
|
|
|
4285
4288
|
addList( name, values, value, callback, options = {} ) {
|
|
4286
4289
|
|
|
4287
|
-
let widget = this.create_widget(name, Widget.LIST, options);
|
|
4288
|
-
let element = widget.domEl;
|
|
4290
|
+
let widget = this.create_widget( name, Widget.LIST, options );
|
|
4289
4291
|
|
|
4290
|
-
|
|
4292
|
+
widget.onGetValue = () => {
|
|
4293
|
+
return value;
|
|
4294
|
+
};
|
|
4291
4295
|
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4296
|
+
widget.onSetValue = ( newValue ) => {
|
|
4297
|
+
listContainer.querySelectorAll( '.lexlistitem' ).forEach( e => e.classList.remove( 'selected' ) );
|
|
4298
|
+
const idx = values.indexOf( newValue );
|
|
4299
|
+
if( idx == -1 ) return;
|
|
4300
|
+
listContainer.children[ idx ].classList.toggle( 'selected' );
|
|
4301
|
+
value = newValue;
|
|
4302
|
+
this._trigger( new IEvent( name, newValue ), callback );
|
|
4303
|
+
};
|
|
4295
4304
|
|
|
4296
|
-
|
|
4297
|
-
{
|
|
4298
|
-
let icon = null;
|
|
4299
|
-
let item_value = values[i];
|
|
4305
|
+
widget.updateValues = ( newValues ) => {
|
|
4300
4306
|
|
|
4301
|
-
|
|
4307
|
+
values = newValues;
|
|
4308
|
+
listContainer.innerHTML = "";
|
|
4309
|
+
|
|
4310
|
+
for( let i = 0; i < values.length; ++i )
|
|
4302
4311
|
{
|
|
4303
|
-
icon =
|
|
4304
|
-
|
|
4312
|
+
let icon = null;
|
|
4313
|
+
let itemValue = values[ i ];
|
|
4314
|
+
|
|
4315
|
+
if( itemValue.constructor === Array )
|
|
4316
|
+
{
|
|
4317
|
+
icon = itemValue[ 1 ];
|
|
4318
|
+
itemValue = itemValue[ 0 ];
|
|
4319
|
+
}
|
|
4320
|
+
|
|
4321
|
+
let listElement = document.createElement( 'div' );
|
|
4322
|
+
listElement.className = "lexlistitem" + ( value == itemValue ? " selected" : "" );
|
|
4323
|
+
listElement.innerHTML = "<span>" + itemValue + "</span>" + ( icon ? "<a class='" + icon + "'></a>" : "" );
|
|
4324
|
+
|
|
4325
|
+
listElement.addEventListener( 'click', e => {
|
|
4326
|
+
listContainer.querySelectorAll( '.lexlistitem' ).forEach( e => e.classList.remove( 'selected' ) );
|
|
4327
|
+
listElement.classList.toggle( 'selected' );
|
|
4328
|
+
value = itemValue;
|
|
4329
|
+
this._trigger( new IEvent( name, itemValue, e ), callback );
|
|
4330
|
+
});
|
|
4331
|
+
|
|
4332
|
+
listContainer.appendChild( listElement );
|
|
4305
4333
|
}
|
|
4334
|
+
};
|
|
4306
4335
|
|
|
4307
|
-
|
|
4308
|
-
list_item.className = "lexlistitem" + (value == item_value ? " selected" : "");
|
|
4309
|
-
list_item.innerHTML = "<span>" + item_value + "</span>" + (icon ? "<a class='" + icon + "'></a>" : "");
|
|
4336
|
+
let element = widget.domEl;
|
|
4310
4337
|
|
|
4311
|
-
|
|
4312
|
-
list_container.querySelectorAll('.lexlistitem').forEach( e => e.classList.remove('selected'));
|
|
4313
|
-
list_item.classList.toggle( 'selected' );
|
|
4314
|
-
this._trigger( new IEvent(name, item_value, e), callback );
|
|
4315
|
-
});
|
|
4338
|
+
// Show list
|
|
4316
4339
|
|
|
4317
|
-
|
|
4318
|
-
|
|
4340
|
+
let listContainer = document.createElement( 'div' );
|
|
4341
|
+
listContainer.className = "lexlist";
|
|
4342
|
+
listContainer.style.width = "calc( 100% - " + LX.DEFAULT_NAME_WIDTH + ")";
|
|
4343
|
+
|
|
4344
|
+
widget.updateValues( values );
|
|
4319
4345
|
|
|
4320
4346
|
// Remove branch padding and margins
|
|
4321
|
-
if(!widget.name) {
|
|
4347
|
+
if( !widget.name ) {
|
|
4322
4348
|
element.className += " noname";
|
|
4323
|
-
|
|
4349
|
+
listContainer.style.width = "100%";
|
|
4324
4350
|
}
|
|
4325
4351
|
|
|
4326
|
-
element.appendChild(
|
|
4352
|
+
element.appendChild( listContainer );
|
|
4327
4353
|
|
|
4328
4354
|
return widget;
|
|
4329
4355
|
}
|
package/changelog.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# lexgui.js changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.25
|
|
4
|
+
|
|
5
|
+
Code Editor:
|
|
6
|
+
- Added Ctrl+K + C/U Shortcuts to Comment/Uncomment lines.
|
|
7
|
+
- Improved WGSL highlighting.
|
|
8
|
+
- Minor bug fixes.
|
|
9
|
+
|
|
10
|
+
Added title attribute by default to Widget Name Dom elements.
|
|
11
|
+
Added value getter/setter for LIST widget.
|
|
12
|
+
Added updateValues method for modify list options in LIST widget.
|
|
13
|
+
|
|
3
14
|
## 0.1.24
|
|
4
15
|
|
|
5
16
|
Code Editor:
|