-
Notifications
You must be signed in to change notification settings - Fork 10
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
cli: implement autocompletion for cli commands #132
Conversation
Now it splits 'str' till limit is bound or no more separators left in 'str' if leaveEmpty is true then multiple separators in sequence are written in the resulting array as one empty string (''), else they are skipped and doesn't get counted to limit
@lundibundi can you please add the |
tools/cli.js
Outdated
|
||
const result = []; | ||
let start = 0; | ||
|
||
// eslint-disable-next-line no-unmodified-loop-condition | ||
for (let i = 0; !limit || i < limit; i++) { | ||
while (!limit || limit - result.length > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, rewriting second condition as
result.length < limit
will make it more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
e2d1b75
to
f5b461f
Compare
@aqrln done |
tools/cli.js
Outdated
const split = str.indexOf(separator, start); | ||
if (split === -1) break; | ||
if (!shouldTrim(start, split)) { | ||
if (start !== split || leaveEmpty && !isLastEmpty(result)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This complex condition really needs parentheses.
tools/cli.js
Outdated
@@ -24,14 +24,64 @@ const log = (msg) => { | |||
if (userInput) rl.write(userInput); | |||
}; | |||
|
|||
function completeByFields(input, object) { | |||
return Object.keys(object) | |||
.filter(c => !c.startsWith('_') && (!input || c.startsWith(input))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What type can input
have? If it's always a string, then the !input
check is superfluous, c.startsWith('')
will always return true
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aqrln the problem is it can be undefined when you press tab with no input, not sure how to handle this better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, well then. If it can be undefined
, the check is completely valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aqrln, but isn't it redundant? As far as I know, String.prototype.startsWith
will return false
when first argument is undefined
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aqrln, oh, I am sorry, I see why this check is OK here.
// splits 'str' till limit is bound or no more separators left in 'str' | ||
// if leaveEmpty is true then multiple separators in sequence are written in | ||
// resulting array as one empty string (''), else they are skipped | ||
// and doesn't get counted to limit | ||
function _split(str, separator, limit, leaveEmpty) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this PR, but why does this function start with an underscore? It isn't exported so it's private anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tools/cli.js
Outdated
} | ||
start = split + separator.length; | ||
} | ||
if (!shouldTrim(start, str.length)) { | ||
if (start !== str.length || leaveEmpty && !isLastEmpty(result)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is almost the same condition as on line 192, you should probably replace it with function, like it was before with shouldTrim
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@belochub yeah, but i'm not sure if it's okay to use shouldTrim (name) as it will also add '' when needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lundibundi, I didn't say that you should leave shouldTrim
the way it was before. I meant that you you should replace repetitive conditions with function, like it was done before with shouldTrim
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@belochub I know, I meant that I couldn't come up with a good name for it.
tools/cli.js
Outdated
} | ||
|
||
function tryComplete(input, completer) { | ||
const completions = completer._complete([input], 0)[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I understand the completer
interface, _complete
and _help
are its public methods. Why do they start with underscores?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. It's a hack to make objects which serve as sources for completions completers themselves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aqrln hm, at first I thought to always use fields for completion, but now I see that it'd to be better to state the completions manually, then i can get rid of the underscore.
tools/cli.js
Outdated
} | ||
return [completions, help]; | ||
} | ||
const [newCompletions, newDepth] = completer._complete(inputs, depth); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc comment above this function states:
// completer - object that has '_complete(inputs, depth)' function or ._help()
// or neither (no completions or help available)
But if the completer
object has no _complete
method, this line will fail with a TypeError
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, forgot about first entrance, thanks for catching that.
tools/cli.js
Outdated
return helper(newDepth, depth, nextCompleter, newCompletions); | ||
} | ||
if (inputs[oldDepth] === completions[0]) { | ||
completions.shift(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement modifies the completions
array. Won't it have any unwanted side-effects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's needed to remove completion if user has already entered full command, what sort of side-effects? Actually it is possible to use it's own return statement there as completions will always by empty at that time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, I was thinking of some global array of completions that unexpectedly gets deteriorated as user keeps hitting Tab. That's not the case here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, it's not related to the current PR if that's how it is actually implemented in the CLI. It's a matter of a separate issue and PR.
Sorry, wrong thread.
tools/cli.js
Outdated
commandProcessor.event = (interfaceName, eventName, args, callback) => { | ||
if (!state.client) return callback(new Error('Not connected')); | ||
state.connection.emitRemoteEvent(interfaceName, eventName, args); | ||
callback(); | ||
}; | ||
|
||
commandProcessor.event._help = () => ( | ||
'event <interfaceName> <eventName> [ <arg> [ , ... ] ]' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Events in JSTP don't have a concept of arguments, like methods do. They only have a single argument that can be of any type. Is it just the help that is incorrect here or that's how it is actually implemented so that it's a bug in CLI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aqrln not sure what you meant, the '[ <arg> [ , ... ] ]' will be passed as an array as a third argument to Connection.emitRemoteEvent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but it's not supposed to be an array. It can be an arbitrary JavaScript value. At least, in the current version of the protocol.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway, it's not related to the current PR if that's how it is actually implemented in the CLI. It's a matter of a separate issue and PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it is implemented like that, so we should open an issue for that.
If anyone passed 'completer' that has no _complete method it'd have failed with TypeError
tools/cli.js
Outdated
function _split(str, separator, limit, leaveEmpty) { | ||
const shouldTrim = (start, split) => !leaveEmpty && start === split; | ||
const isLastEmpty = arr => !arr[arr.length - 1]; | ||
|
||
const result = []; | ||
let start = 0; | ||
|
||
// eslint-disable-next-line no-unmodified-loop-condition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the linter still fail without this directive with the new loop condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aqrln yeah(
Get rid of underscore methods and state available completions manually in complete method
* don't use shift, just return empty array * extract complex condition to separate arrow function
tools/cli.js
Outdated
// limit - resulting length of output array - 1 (last one is what's left), | ||
// if !limit === true => means no limit and split till no more | ||
// separators found | ||
// leaveEmpty - if true multiple separators in sequence will be added as empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Word 'empty' is repeated twice here, probably a typo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
tools/cli.js
Outdated
@@ -109,17 +109,18 @@ const state = { | |||
connection: null | |||
}; | |||
|
|||
commandProcessor._complete = (inputs, depth) => { | |||
commandProcessor.complete = (inputs, depth) => { | |||
const completions = ['call', 'event', 'connect', 'disconnect', 'exit']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer these to be sorted alphabetically, though I don't feel strongly for it.
tools/cli.js
Outdated
const state = { | ||
client: null, | ||
connection: null | ||
}; | ||
|
||
commandProcessor.complete = (inputs, depth) => { | ||
const completions = ['call', 'event', 'connect', 'disconnect', 'exit']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer these to be sorted alphabetically, though I don't feel strongly for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok with me
* sort available completions in commandProcessor * fix a typo in iterativeCompletion doc
It was working incorrectly with multiple leading separators
20946fe
to
ad1e61a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Now it splits 'str' till limit is bound or no more separators left in 'str' if leaveEmpty is true then multiple separators in sequence are written in the resulting array as one empty string (''), else they are skipped and doesn't get counted to limit PR-URL: #132 Reviewed-By: Mykola Bilochub <nbelochub@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Now it splits 'str' till limit is bound or no more separators left in 'str' if leaveEmpty is true then multiple separators in sequence are written in the resulting array as one empty string (''), else they are skipped and doesn't get counted to limit PR-URL: #132 Reviewed-By: Mykola Bilochub <nbelochub@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Now it splits 'str' till limit is bound or no more separators left in 'str' if leaveEmpty is true then multiple separators in sequence are written in the resulting array as one empty string (''), else they are skipped and doesn't get counted to limit PR-URL: #132 Reviewed-By: Mykola Bilochub <nbelochub@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Now it splits 'str' till limit is bound or no more separators left in 'str' if leaveEmpty is true then multiple separators in sequence are written in the resulting array as one empty string (''), else they are skipped and doesn't get counted to limit PR-URL: metarhia/jstp#132 Reviewed-By: Mykola Bilochub <nbelochub@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
PR-URL: metarhia/jstp#132 Refs: metarhia/jstp#125 Reviewed-By: Mykola Bilochub <nbelochub@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Now it splits 'str' till limit is bound or no more separators left in 'str' if leaveEmpty is true then multiple separators in sequence are written in the resulting array as one empty string (''), else they are skipped and doesn't get counted to limit PR-URL: metarhia/jstp#132 Reviewed-By: Mykola Bilochub <nbelochub@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
PR-URL: metarhia/jstp#132 Refs: metarhia/jstp#125 Reviewed-By: Mykola Bilochub <nbelochub@gmail.com> Reviewed-By: Alexey Orlenko <eaglexrlnk@gmail.com>
Implements 'Autocompletion for CLI commands' and allows to implement 'Autocompletion for method names' (#125)
The behavior is as follows: