Skip to content

Commit f34f431

Browse files
committed
feat(repl): add settings and prototype methods for keybindings
Signed-off-by: Snehil Shah <[email protected]>
1 parent a974755 commit f34f431

File tree

8 files changed

+331
-30
lines changed

8 files changed

+331
-30
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2024 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MAIN //
22+
23+
/**
24+
* List of REPL actions.
25+
*
26+
* @private
27+
* @name ACTIONS
28+
* @type {Object}
29+
*/
30+
var ACTIONS = [
31+
'moveRight',
32+
'moveLeft',
33+
'moveWordRight',
34+
'moveWordLeft',
35+
'moveBeginning',
36+
'moveEnd',
37+
'tab',
38+
'indentLineRight',
39+
'indentLineLeft',
40+
'deleteLeft',
41+
'deleteRight',
42+
'deleteWordLeft',
43+
'deleteWordRight',
44+
'deleteLineLeft',
45+
'deleteLineRight',
46+
'yankKilled',
47+
'yankPop',
48+
'undo',
49+
'redo',
50+
'transposeAboutCursor',
51+
'uppercaseNextWord',
52+
'capitalizeNextWord',
53+
'lowercaseNextWord',
54+
'clearScreen'
55+
];
56+
57+
58+
// EXPORTS //
59+
60+
module.exports = ACTIONS;

lib/node_modules/@stdlib/repl/lib/commands.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var onHelp = require( './commands/help.js' );
4848
var onInfo = require( './commands/info.js' );
4949
var isWorkspace = require( './commands/is_workspace.js' );
5050
var isKeyword = require( './commands/is_keyword.js' );
51+
var onKeybindings = require( './commands/keybindings.js' );
5152
var onLicense = require( './commands/license_text.js' );
5253
var onLoad = require( './commands/load.js' );
5354
var onLoadWorkspace = require( './commands/load_workspace.js' );
@@ -60,6 +61,7 @@ var onRenameWorkspace = require( './commands/rename_workspace.js' );
6061
var onRerequire = require( './commands/rerequire.js' );
6162
var onRerun = require( './commands/rerun.js' );
6263
var onReset = require( './commands/reset.js' );
64+
var onSetKeybinding = require( './commands/set_keybinding.js' );
6365
var onSettings = require( './commands/settings.js' );
6466
var onThemes = require( './commands/themes.js' );
6567
var onTutorial = require( './commands/tutorial.js' );
@@ -122,6 +124,7 @@ function commands( repl ) {
122124
cmds.push( [ 'info', onInfo( repl, cmds ), false ] );
123125
cmds.push( [ 'isKeyword', isKeyword( repl ), false ] );
124126
cmds.push( [ 'isWorkspace', isWorkspace( repl ), false ] );
127+
cmds.push( [ 'keybindings', onKeybindings( repl ), false ] );
125128
cmds.push( [ 'license', onLicense( repl ), false ] );
126129
cmds.push( [ 'load', onLoad( repl ), false ] );
127130
cmds.push( [ 'loadWorkspace', onLoadWorkspace( repl ), false ] );
@@ -134,6 +137,7 @@ function commands( repl ) {
134137
cmds.push( [ 'rerequire', onRerequire( repl ), false ] );
135138
cmds.push( [ 'rerun', onRerun( repl ), false ] );
136139
cmds.push( [ 'reset', onReset( repl ), false ] );
140+
cmds.push( [ 'setKeybinding', onSetKeybinding( repl ), false ] );
137141
cmds.push( [ 'settings', onSettings( repl ), false ] );
138142
cmds.push( [ 'themes', onThemes( repl ), false ] );
139143
cmds.push( [ 'tutorial', onTutorial( repl ), false ] );
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2024 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/* eslint-disable no-underscore-dangle */
20+
21+
'use strict';
22+
23+
// MODULES //
24+
25+
var format = require( '@stdlib/string/format' );
26+
var contains = require( '@stdlib/assert/contains' );
27+
var isString = require( '@stdlib/assert/is-string' );
28+
var ACTIONS = require( './../actions.js' );
29+
30+
31+
// MAIN //
32+
33+
/**
34+
* Returns a callback to be invoked upon calling the `keybindings` command.
35+
*
36+
* @private
37+
* @param {REPL} repl - REPL instance
38+
* @returns {Function} callback
39+
*/
40+
function command( repl ) {
41+
return onCommand;
42+
43+
/**
44+
* Returns all (or select) keybindings.
45+
*
46+
* @private
47+
* @param {string} [action] - action name
48+
* @returns {(Object|Array<Object>)} keybindings object or a list of keybindings for an action
49+
*/
50+
function onCommand() {
51+
var action;
52+
var nargs;
53+
54+
nargs = arguments.length;
55+
if ( nargs === 0 ) {
56+
return repl.keybindings();
57+
}
58+
if ( nargs === 1 ) {
59+
action = arguments[ 0 ];
60+
if ( !isString( action ) ) {
61+
repl._ostream.write( format( 'Error: invalid argument. First argument must be a string. Value: `%s`.', action ) );
62+
return;
63+
}
64+
if ( !contains( ACTIONS, action ) ) {
65+
repl._ostream.write( format( 'Error: invalid argument. First argument must be a valid action name. Value: `%s`.', action ) );
66+
return;
67+
}
68+
return repl.keybindings()[ action ];
69+
}
70+
}
71+
}
72+
73+
74+
// EXPORTS //
75+
76+
module.exports = command;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2024 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/* eslint-disable no-underscore-dangle */
20+
21+
'use strict';
22+
23+
// MODULES //
24+
25+
var format = require( '@stdlib/string/format' );
26+
var contains = require( '@stdlib/assert/contains' );
27+
var isString = require( '@stdlib/assert/is-string' );
28+
var ACTIONS = require( './../actions.js' );
29+
30+
31+
// MAIN //
32+
33+
/**
34+
* Returns a callback to be invoked upon calling the `setKeybinding` command.
35+
*
36+
* @private
37+
* @param {REPL} repl - REPL instance
38+
* @returns {Function} callback
39+
*/
40+
function command( repl ) {
41+
return onCommand;
42+
43+
/**
44+
* Allows the user to set a keybinding.
45+
*
46+
* @private
47+
* @param {string} action - action name
48+
* @returns {void}
49+
*/
50+
function onCommand( action ) {
51+
if ( !isString( action ) ) {
52+
repl._ostream.write( format( 'Error: invalid argument. First argument must be a string. Value: `%s`.', action ) );
53+
return;
54+
}
55+
if ( !contains( ACTIONS, action ) ) {
56+
repl._ostream.write( format( 'Error: invalid argument. First argument must be a valid action name. Value: `%s`.', action ) );
57+
return;
58+
}
59+
repl._ostream.write( 'Listening for keypresses...' );
60+
repl._isCapturingKeybinding = true;
61+
repl._targetAction = action;
62+
}
63+
}
64+
65+
66+
// EXPORTS //
67+
68+
module.exports = command;

lib/node_modules/@stdlib/repl/lib/display_prompt.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function displayPrompt( repl, preserveCursor ) {
4242
var ws;
4343

4444
// Avoid displaying a prompt if the REPL is currently in paging mode...
45-
if ( repl._ostream.isPaging ) {
45+
if ( repl._ostream.isPaging || repl._isCapturingKeybinding ) {
4646
return;
4747
}
4848
len = repl._cmd.length;

lib/node_modules/@stdlib/repl/lib/editor_actions.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ setNonEnumerableReadOnly( EditorActions.prototype, 'clearScreen', function clear
523523
* @returns {boolean} boolean indicating whether an editor action was triggered
524524
*/
525525
setNonEnumerableReadOnly( EditorActions.prototype, 'beforeKeypress', function beforeKeypress( data, key ) {
526+
var isTriggered;
526527
var actionKeys;
527528
var inputKeys;
528529
var i;
@@ -531,17 +532,18 @@ setNonEnumerableReadOnly( EditorActions.prototype, 'beforeKeypress', function be
531532
return false;
532533
}
533534
inputKeys = parseKey( key );
535+
isTriggered = false;
534536
for ( i = 0; i < EDITOR_ACTIONS.length; i++ ) {
535537
actionKeys = this._keybindings[ EDITOR_ACTIONS[ i ] ];
536538
if ( !actionKeys ) {
537539
continue; // no keybindings configured for the action
538540
}
539541
if ( matchKeybindings( inputKeys, actionKeys ) ) {
540542
this[ EDITOR_ACTIONS[ i ] ]();
541-
return true;
543+
isTriggered = true;
542544
}
543545
}
544-
return false;
546+
return isTriggered;
545547
});
546548

547549

0 commit comments

Comments
 (0)