Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add syntax highlighting in the REPL #2254

Merged
merged 23 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0e9f467
feat: add syntax highlighting in the REPL
Snehil-Shah May 20, 2024
ceaa8c0
fix: cache line to avoid highlighting when no change detected
Snehil-Shah May 21, 2024
c422e71
feat: explicitly define keywords like `let`
Snehil-Shah May 21, 2024
295633f
style: stick to conventions
Snehil-Shah May 25, 2024
5af1fa7
fix: suggestions
Snehil-Shah May 25, 2024
c4d1748
feat: add more token types
Snehil-Shah May 25, 2024
1ebc27f
fix: add missing `return` statement
Snehil-Shah May 26, 2024
3c19a6b
docs: change jsdoc
Snehil-Shah May 26, 2024
1e4ea8c
fix: incorrect color name
Snehil-Shah May 26, 2024
33eb6a0
feat: resolve local identifiers & declarations
Snehil-Shah May 26, 2024
f197dcc
docs: update jsdoc and variable names
Snehil-Shah May 26, 2024
f9ad172
feat: update control keywords
Snehil-Shah May 26, 2024
bfe7408
fix: handle edge cases
Snehil-Shah May 27, 2024
a72346a
fix: use `contains.factory`
Snehil-Shah May 27, 2024
bbd1e11
fix: variable names and using `contains.factory`
Snehil-Shah May 27, 2024
7a94ce4
refactor: return all local nodes after resolving them
Snehil-Shah May 27, 2024
c7cd532
docs: update jsdoc
Snehil-Shah May 27, 2024
186bbac
fix: handle reserved names
Snehil-Shah May 28, 2024
76afa3c
fix: suggestions
Snehil-Shah May 28, 2024
34f53d0
docs: clarify comments
Snehil-Shah May 28, 2024
94c2e01
fix: avoid conflicts between reserved names and object properties
Snehil-Shah May 28, 2024
b2fd379
fix: detect if identifier exists before pushing a `name` token
Snehil-Shah May 28, 2024
9e5015d
style: fix bracket spacing
Snehil-Shah May 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions lib/node_modules/@stdlib/repl/lib/ansi_colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* @license Apache-2.0
*
* Copyright (c) 2024 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MAIN //

/**
* Table mapping generic color names to their ANSI color codes.
*
* @private
* @name ANSI
* @type {Object}
*/
var ANSI = {
// Original colors:
'black': '\u001b[30m',
Copy link
Member

@Planeshifter Planeshifter May 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's get this in for now as-is, but as a follow-up it may be worthwhile to add a separate package specifically for colors, as an alternative to https://www.npmjs.com/package/colors or https://www.npmjs.com/package/chalk. Similar to what chalk is doing, we could do feature detection in there for which ANSI colors are supported and adjust the exports accordingly. A potential location for such a package may be @stdlib/cli/colors, with color support detection potentially living in the assert namespace.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be nice to have! will add it as a TODO.

'red': '\u001b[31m',
'green': '\u001b[32m',
'yellow': '\u001b[33m',
'blue': '\u001b[34m',
'magenta': '\u001b[35m',
'cyan': '\u001b[36m',
'white': '\u001b[37m',

// Bright colors:
'brightBlack': '\u001b[90m',
'brightRed': '\u001b[91m',
'brightGreen': '\u001b[92m',
'brightYellow': '\u001b[93m',
'brightBlue': '\u001b[94m',
'brightMagenta': '\u001b[95m',
'brightCyan': '\u001b[96m',
'brightWhite': '\u001b[97m',

// Reset colors:
'reset': '\u001b[0m'
};


// EXPORTS //

module.exports = ANSI;
2 changes: 1 addition & 1 deletion lib/node_modules/@stdlib/repl/lib/complete_expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
* @param {string} expression - expression to complete
* @returns {string} filter
*/
function complete( out, context, expression ) {

Check warning on line 57 in lib/node_modules/@stdlib/repl/lib/complete_expression.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Function 'complete' has too many statements (104). Maximum allowed is 100
var filter;
var script;
var node;
Expand All @@ -74,7 +74,7 @@
ast = parse( expression, AOPTS );

debug( 'Resolving local scopes within the AST.' );
ast = resolveLocalScopes( ast );
resolveLocalScopes( ast );

// Get the last program top-level AST "node":
debug( 'Number of statements: %d', ast.body.length );
Expand Down
8 changes: 8 additions & 0 deletions lib/node_modules/@stdlib/repl/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
var completerFactory = require( './completer.js' );
var PreviewCompleter = require( './completer_preview.js' );
var AutoCloser = require( './auto_close_pairs.js' );
var SyntaxHighlighter = require( './syntax_highlighter.js' );
var ALIAS_OVERRIDES = require( './alias_overrides.js' );
var SETTINGS = require( './settings.js' );
var SETTINGS_VALIDATORS = require( './settings_validators.js' );
Expand Down Expand Up @@ -270,11 +271,14 @@
// Initialize a preview completer:
setNonEnumerableReadOnly( this, '_previewCompleter', new PreviewCompleter( this._rli, this._completer, this._ostream, this._settings.completionPreviews ) );

// Initialize a syntax-highlighter:
setNonEnumerableReadOnly( this, '_syntaxHighlighter', new SyntaxHighlighter( this, this._ostream ) );

// Cache a reference to the private readline interface `ttyWrite` to allow calling the method when wanting default behavior:
setNonEnumerableReadOnly( this, '_ttyWrite', this._rli._ttyWrite );

// Overwrite the private `ttyWrite` method to allow processing input before a "keypress" event is triggered:
this._rli._ttyWrite = beforeKeypress; // WARNING: overwriting a private property

Check warning on line 281 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'warning' comment: 'WARNING: overwriting a private property'

// Add event listeners:
this._rli.on( 'close', onClose );
Expand All @@ -294,9 +298,9 @@
// Write a welcome message:
this._wstream.write( opts.welcome );

// TODO: check whether to synchronously initialize a REPL history file

Check warning on line 301 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'todo' comment: 'TODO: check whether to synchronously...'

// TODO: check whether to synchronously initialize a REPL log file

Check warning on line 303 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'todo' comment: 'TODO: check whether to synchronously...'

// Check whether to load and execute a JavaScript file (e.g., prior REPL history) upon startup...
if ( opts.load ) {
Expand Down Expand Up @@ -334,6 +338,7 @@
*/
function onKeypress( data, key ) {
var autoClosed;

if ( key && key.name === 'tab' ) {
return;
}
Expand All @@ -343,6 +348,9 @@
if ( autoClosed ) {
self._previewCompleter.clear();
}
if ( self._isTTY ) {
self._syntaxHighlighter.onKeypress();
}
self._previewCompleter.onKeypress( data, key );
}

Expand Down Expand Up @@ -445,9 +453,9 @@
// Update the internal command history buffer: [..., <id>, <cmd>, <success>, ...]
self._history.push( self._count, cmd, success );

// TODO: if successful and if necessary, (asynchronously?) write the command to a history file (question: do we only want to write successful commands to the history file? maybe we need to option for limiting to successful commands?)

Check warning on line 456 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'todo' comment: 'TODO: if successful and if necessary,...'

// TODO: if necessary, (asynchronously?) write the command and result to a log file (JSON serialization?)

Check warning on line 458 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'todo' comment: 'TODO: if necessary, (asynchronously?)...'
}
}

Expand Down Expand Up @@ -671,7 +679,7 @@

// Before creating a new execution context in a non-sandboxed environment, remove current workspace variables in order to allow garbage collection and avoid memory leaks (e.g., variables/functions declared during a REPL session which might remain bound to the environment `global` after clearing a REPL):
if ( this._sandbox === false ) {
// WARNING: in a non-sandboxed environment, if a global variable is externally introduced during a REPL session (i.e., introduced via a mechanism outside of the REPL environment), we will delete that global variable, which means the following logic may introduce unintended side-effects for this particular edge case (e.g., application code may expect the presence of the subsequently deleted global variable). While not ideal, (a) user applications should not be introducing globals to begin with and (b) the probability of a user running a REPL session, a user clearing that REPL session, AND a global variable being introduced between starting a REPL and clearing the REPL should be negligible.

Check warning on line 682 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'warning' comment: 'WARNING: in a non-sandboxed environment,...'
tmp = this._context.vars();
for ( i = 0; i < tmp.length; i++ ) {
if ( isConfigurableProperty( this._context, tmp[ i ] ) ) {
Expand Down Expand Up @@ -1064,9 +1072,9 @@
// Clear the command queue:
this._queue.clear();

// TODO: ensure REPL history is saved (flushed) to file before closing the REPL (see https://github.com/nodejs/node/blob/b21e7c7bcf23a2715951e4cd96180e4dbf1dcd4d/lib/repl.js#L805)

Check warning on line 1075 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'todo' comment: 'TODO: ensure REPL history is saved...'

// TODO: ensure REPL log is saved (flushed) to file before closing the REPL

Check warning on line 1077 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'todo' comment: 'TODO: ensure REPL log is saved (flushed)...'

nextTick( onTick );

Expand All @@ -1089,7 +1097,7 @@

// If this is a non-sandboxed REPL, remove global variables/properties which were introduced during context creation and by a user during a REPL session...
if ( self._sandbox === false ) {
// WARNING: in a non-sandboxed environment, if a global variable is externally introduced during a REPL session (i.e., introduced via a mechanism outside of the REPL environment), we will delete that global variable, which means the following logic may introduce unintended side-effects for this particular edge case (e.g., application code may expect the presence of the subsequently deleted global variable). While not ideal, (a) user applications should not be introducing globals to begin with and (b) the probability of a user running a REPL session, a user closing that REPL session, AND a global variable being introduced between starting a REPL and closing the REPL should be negligible.

Check warning on line 1100 in lib/node_modules/@stdlib/repl/lib/main.js

View workflow job for this annotation

GitHub Actions / Lint Changed Files

Unexpected 'warning' comment: 'WARNING: in a non-sandboxed environment,...'
tmp = self._context.vars(); // current workspace variables
for ( i = 0; i < tmp.length; i++ ) {
if ( isConfigurableProperty( self._context, tmp[ i ] ) ) {
Expand Down
2 changes: 1 addition & 1 deletion lib/node_modules/@stdlib/repl/lib/resolve_globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function resolveGlobals( ast ) {
globals = [];

// Resolve local scopes:
ast = resolveLocalScopes( ast );
resolveLocalScopes( ast );

// Define callbacks for relevant AST nodes:
visitors = {
Expand Down
Loading
Loading