Skip to content

feat: add APIs, commands and tests for syntax-highlighting in the REPL #2291

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

Merged
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7aa2a2d
feat: add APIs to programmatically control syntax-highlighter
Snehil-Shah Jun 1, 2024
31b5134
feat: add REPL commands to control syntax-highlighting
Snehil-Shah Jun 1, 2024
6858433
feat: add setting to enable/disable syntax-highlighting
Snehil-Shah Jun 1, 2024
0c3e6d3
test: fix failing tests
Snehil-Shah Jun 1, 2024
d5a00a8
feat: add options for syntax-highlighting upon REPL startup
Snehil-Shah Jun 1, 2024
56c30bf
refactor: update API and command signatures
Snehil-Shah Jun 2, 2024
f466ab3
refactor: move `await` keyword to a control keyword
Snehil-Shah Jun 2, 2024
1fd6070
fix: resolve `null` try parameters crashing the REPL
Snehil-Shah Jun 2, 2024
f8c10a4
fix: don't throw error if a node doesn't match a declaration
Snehil-Shah Jun 2, 2024
5c9b7f6
fix: handle member expressions like `foo['bar']`
Snehil-Shah Jun 2, 2024
3e7d7ba
test: add tests for the syntax highlighter
Snehil-Shah Jun 2, 2024
570f24e
refactor: clean code logic
Snehil-Shah Jun 2, 2024
7f31a89
docs: document added prototype methods and settings
Snehil-Shah Jun 2, 2024
028f477
test: update test case
Snehil-Shah Jun 2, 2024
7c99ef7
fix: handle recursive `MemberExpressions`
Snehil-Shah Jun 3, 2024
1b79a3c
refactor: clean code logic
Snehil-Shah Jun 3, 2024
765c19b
fix: correct string formatting
Snehil-Shah Jun 3, 2024
4480879
fix: ignore placeholder nodes
Snehil-Shah Jun 3, 2024
0ea6e2e
fix: setting themes during startup
Snehil-Shah Jun 4, 2024
de9e1e8
docs: keep it consistent
Snehil-Shah Jun 4, 2024
802d602
refactor: return theme object in `getTheme` command
Snehil-Shah Jun 4, 2024
4e2af9a
fix: suggestions
Snehil-Shah Jun 5, 2024
7bc6f92
Apply suggestions from code review
kgryte Jun 7, 2024
7c7dbeb
Apply suggestions from code review
kgryte Jun 7, 2024
3f7d885
Apply suggestions from code review
kgryte Jun 7, 2024
3d80c69
Apply suggestions from code review
kgryte Jun 7, 2024
8938c74
Apply suggestions from code review
kgryte Jun 7, 2024
7de50f5
Apply suggestions from code review
kgryte Jun 7, 2024
3798c65
Apply suggestions from code review
kgryte Jun 7, 2024
ba7ac55
fix: suggestions
Snehil-Shah Jun 8, 2024
81bdca7
Apply suggestions from code review
kgryte Jun 8, 2024
6ea845f
Apply suggestions from code review
kgryte Jun 8, 2024
6913e06
Apply suggestions from code review
kgryte Jun 8, 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
143 changes: 143 additions & 0 deletions lib/node_modules/@stdlib/repl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ The function accepts the following `options`:
- **outputPrompt**: output prompt. If the output prompt includes the character sequence `%d`, the output prompt includes line numbers. Default: `'Out[%d]: '`.
- **welcome**: welcome message.
- **padding**: number of empty lines between consecutive commands. Default: `1`.
- **themes**: table mapping of color themes to load for syntax highlighting.
- **load**: file path specifying a JavaScript file to load and evaluate line-by-line (e.g., a previous REPL history file).
- **save**: file path specifying where to save REPL command history.
- **log**: file path specifying where to save REPL commands and printed output.
Expand All @@ -83,6 +84,28 @@ The function supports specifying the following settings:
- **autoDeletePairs**: boolean indicating whether to automatically delete adjacent matching brackets, parentheses, and quotes. Default: `true`.
- **autoPage**: boolean indicating whether to automatically page return values having a display size exceeding the visible screen. When streams are TTY, the default is `true`; otherwise, the default is `false`.
- **completionPreviews**: boolean indicating whether to display completion previews for auto-completion. When streams are TTY, the default is `true`; otherwise, the default is `false`.
- **syntaxHighlighting**: boolean indicating whether to enable syntax highlighting of the input. When streams are TTY, the default is `true`; otherwise, the default is `false`.
- **theme**: initial color theme for syntax highlighting. Default: `default`.
- **defaultTheme**: default theme for syntax highlighting. Default: `default`.

#### REPL.prototype.viewport()

Returns the REPL viewport.

```javascript
var debug = require( '@stdlib/streams/node/debug-sink' );

// Create a new REPL:
var repl = new REPL({
'output': debug()
});

// Query the REPL viewport:
var v = repl.viewport();

// Close the REPL:
repl.close();
```

#### REPL.prototype.createContext()

Expand Down Expand Up @@ -176,6 +199,126 @@ repl.clearUserDocs();
repl.close();
```

#### Repl.prototype.themes()

Returns all available themes in the syntax-highlighter.

```javascript
var debug = require( '@stdlib/streams/node/debug-sink' );

// Create a new REPL:
var repl = new REPL({
'output': debug()
});

// ...

// Fetch all available themes:
repl.themes();

// ...

// Close the REPL:
repl.close();
```

#### Repl.prototype.getTheme()

Returns a theme's color palette from the syntax-highlighter.

```javascript
var debug = require( '@stdlib/streams/node/debug-sink' );

// Create a new REPL:
var repl = new REPL({
'output': debug()
});

// ...

// Fetch all available themes:
repl.themes();

// ...

// Close the REPL:
repl.close();
```

#### Repl.prototype.addTheme()

Adds a color theme to the syntax-highlighter.

```javascript
var debug = require( '@stdlib/streams/node/debug-sink' );

// Create a new REPL:
var repl = new REPL({
'output': debug()
});

// ...

// Add a user-defined theme:
repl.addTheme( 'myTheme', {
'keyword': 'red',
'variable': 'green'

// ...
});

// ...

// Close the REPL:
repl.close();
```

#### Repl.prototype.deleteTheme()

Deletes a specified theme from the syntax-highlighter.

```javascript
var debug = require( '@stdlib/streams/node/debug-sink' );

// Create a new REPL:
var repl = new REPL({
'output': debug()
});

// ...

// Delete an existing theme:
repl.deleteTheme( 'myTheme' );

// ...

// Close the REPL:
repl.close();
```

#### Repl.prototype.renameTheme()

Renames a specified theme in the syntax-highlighter.

```javascript
var debug = require( '@stdlib/streams/node/debug-sink' );

// Create a new REPL:
var repl = new REPL({
'output': debug()
});

// ...

// Rename an existing theme:
repl.renameTheme( 'myTheme', 'yourTheme' );

// ...

// Close the REPL:
repl.close();
```

#### REPL.prototype.load( fpath, clbk )

Loads and evaluates a JavaScript file line-by-line.
Expand Down
10 changes: 10 additions & 0 deletions lib/node_modules/@stdlib/repl/lib/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

// MODULES //

var onAddTheme = require( './commands/add_theme.js' );
var onAlias2Pkg = require( './commands/alias2pkg.js' );
var onAlias2Related = require( './commands/alias2related.js' );
var onAns = require( './commands/ans.js' );
Expand All @@ -35,12 +36,14 @@ var onContributors = require( './commands/contributor.js' );
var onCopyright = require( './commands/copyright.js' );
var onCredits = require( './commands/credits.js' );
var onCurrentWorkspace = require( './commands/current_workspace.js' );
var onDeleteTheme = require( './commands/delete_theme.js' );
var onDeleteWorkspace = require( './commands/delete_workspace.js' );
var onDeeprerequire = require( './commands/deeprerequire.js' );
var onDonate = require( './commands/donate.js' );
var onDone = require( './commands/__done__.js' );
var onEvalin = require( './commands/evalin.js' );
var onExample = require( './commands/example.js' );
var onGetTheme = require( './commands/get_theme.js' );
var onHelp = require( './commands/help.js' );
var onInfo = require( './commands/info.js' );
var isWorkspace = require( './commands/is_workspace.js' );
Expand All @@ -52,11 +55,13 @@ var onPager = require( './commands/pager.js' );
var onPresentationStart = require( './commands/presentation_start.js' );
var onPresentationStop = require( './commands/presentation_stop.js' );
var onQuit = require( './commands/quit.js' );
var onRenameTheme = require( './commands/rename_theme.js' );
var onRenameWorkspace = require( './commands/rename_workspace.js' );
var onRerequire = require( './commands/rerequire.js' );
var onRerun = require( './commands/rerun.js' );
var onReset = require( './commands/reset.js' );
var onSettings = require( './commands/settings.js' );
var onThemes = require( './commands/themes.js' );
var onTutorial = require( './commands/tutorial.js' );
var onUserDoc = require( './commands/user_doc.js' );
var onVars = require( './commands/vars.js' );
Expand Down Expand Up @@ -90,6 +95,7 @@ function commands( repl ) {
// Define a list of REPL-specific commands (NOTE: keep in alphabetical order):
cmds = [];
cmds.push( [ '__done__', onDone( repl ), false ] );
cmds.push( [ 'addTheme', onAddTheme( repl ), false ] );
cmds.push( [ 'alias2pkg', onAlias2Pkg( repl ), false ] );
cmds.push( [ 'alias2related', onAlias2Related( repl, cmds ), false ] );
cmds.push( [ 'ans', onAns( repl ), true ] );
Expand All @@ -105,11 +111,13 @@ function commands( repl ) {
cmds.push( [ 'copyright', onCopyright( repl ), false ] );
cmds.push( [ 'credits', onCredits( repl ), false ] );
cmds.push( [ 'currentWorkspace', onCurrentWorkspace( repl ), true ] );
cmds.push( [ 'deleteTheme', onDeleteTheme( repl ), false ] );
cmds.push( [ 'deleteWorkspace', onDeleteWorkspace( repl ), false ] );
cmds.push( [ 'deeprerequire', onDeeprerequire( repl ), false ] );
cmds.push( [ 'donate', onDonate( repl ), false ] );
cmds.push( [ 'evalin', onEvalin( repl, cmds ), false ] );
cmds.push( [ 'example', onExample( repl, cmds ), false ] );
cmds.push( [ 'getTheme', onGetTheme( repl ), false ] );
cmds.push( [ 'help', onHelp( repl, cmds ), false ] );
cmds.push( [ 'info', onInfo( repl, cmds ), false ] );
cmds.push( [ 'isKeyword', isKeyword( repl ), false ] );
Expand All @@ -121,11 +129,13 @@ function commands( repl ) {
cmds.push( [ 'presentationStart', onPresentationStart( repl ), false ] );
cmds.push( [ 'presentationStop', onPresentationStop( repl ), false ] );
cmds.push( [ 'quit', onQuit( repl ), false ] );
cmds.push( [ 'renameTheme', onRenameTheme( repl ), false ] );
cmds.push( [ 'renameWorkspace', onRenameWorkspace( repl ), false ] );
cmds.push( [ 'rerequire', onRerequire( repl ), false ] );
cmds.push( [ 'rerun', onRerun( repl ), false ] );
cmds.push( [ 'reset', onReset( repl ), false ] );
cmds.push( [ 'settings', onSettings( repl ), false ] );
cmds.push( [ 'themes', onThemes( repl ), false ] );
cmds.push( [ 'tutorial', onTutorial( repl ), false ] );
cmds.push( [ 'userDoc', onUserDoc( repl ), false ] );
cmds.push( [ 'vars', onVars( repl ), false ] );
Expand Down
74 changes: 74 additions & 0 deletions lib/node_modules/@stdlib/repl/lib/commands/add_theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* @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.
*/

/* eslint-disable no-underscore-dangle */

'use strict';

// MODULES //

var format = require( '@stdlib/string/format' );
var log = require( './../log.js' );


// MAIN //

/**
* Returns a callback to be invoked upon calling the `addTheme` command.
*
* @private
* @param {REPL} repl - REPL instance
* @returns {Function} callback
*/
function command( repl ) {
return onCommand;

/**
* Adds a color theme to the syntax-highlighter.
*
* @private
* @param {string} [name] - theme name
* @param {Object} [theme] - theme object
* @returns {void}
*/
function onCommand() {
var theme;
var nargs;
var name;

nargs = arguments.length;
if ( nargs < 2 ) {
repl._ostream.write( 'Error: invalid operation. Provide a theme to add.\n' );
return;
}
name = arguments[ 0 ];
theme = arguments[ 1 ];
try {
repl.addTheme( name, theme );
} catch ( err ) {
repl._ostream.write( format( 'Error: %s\n', err.message ) );
return;
}
log( repl, format( '\nSuccessfully added theme `%s`.', name ) );
}
}


// EXPORTS //

module.exports = command;
71 changes: 71 additions & 0 deletions lib/node_modules/@stdlib/repl/lib/commands/delete_theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* @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.
*/

/* eslint-disable no-underscore-dangle */

'use strict';

// MODULES //

var format = require( '@stdlib/string/format' );
var log = require( './../log.js' );


// MAIN //

/**
* Returns a callback to be invoked upon calling the `deleteTheme` command.
*
* @private
* @param {REPL} repl - REPL instance
* @returns {Function} callback
*/
function command( repl ) {
return onCommand;

/**
* Deletes a color theme from the syntax-highlighter.
*
* @private
* @param {string} [name] - theme name
* @returns {void}
*/
function onCommand() {
var nargs;
var name;

nargs = arguments.length;
if ( nargs === 0 ) {
repl._ostream.write( 'Error: invalid operation. Provide a theme name to delete.\n' );
return;
}
name = arguments[ 0 ];
try {
repl.deleteTheme( name );
} catch ( err ) {
repl._ostream.write( format( 'Error: %s\n', err.message ) );
return;
}
log( repl, format( '\nSuccessfully deleted theme `%s`.', name ) );
}
}


// EXPORTS //

module.exports = command;
Loading
Loading