-
-
Notifications
You must be signed in to change notification settings - Fork 66
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(command): parse without execute #707
base: main
Are you sure you want to change the base?
Conversation
if (ctx.execute) { | ||
return await this.execute(ctx.env, ctx.unknown); | ||
} else { | ||
// TODO: Resolve typing for options |
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 sure how to satisfy options
here since it's normally parsed later with more context.
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 should work:
return { cmd: this, options, literal: [], args: ctx.unknown };
@@ -1750,6 +1761,9 @@ export class Command< | |||
const args = this.parseArguments(ctx, options); | |||
this.literalArgs = ctx.literal; | |||
|
|||
// | |||
// TODO: How can we defer executing this when ctx.execute is false? | |||
// | |||
// Execute option action. | |||
if (ctx.actions.length) { |
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 is the problematic part that is executed only in the parse flow. I haven't given it much thought, but this probably needs to be deferred somehow and/or unified with the execute
method so it's consistently handled.
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.
Yes, this should somehow be moved to the execute
method.
I was looking into this some time ago and noticed this as well. I have indeed thought about exposing the context, because I have also thought about customizing the ActionHandler
to have a context as well as an argument instead of the options
and args
arguments. But since this would be a major change, i have planned to look into this again for cliffy v2.
But maybe we find a nother way to solve this issue for v1.
} catch (error: unknown) { | ||
this.handleError(error); | ||
if (ctx.execute) { |
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 wasn't sure about this, but I don't think we want the help execution/etc. run and displayed on the command line when the user has provided execute: false
.
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 think throwing an error is fine, but we need to call the handleError
method and maybe add a throw
option to it to throw the error.
import { CompletionsCommand } from '../../command/completions/completions_command.ts'; | ||
import { HelpCommand } from '../../command/help/help_command.ts'; | ||
|
||
function getCommandFullname(command: Command<any> | undefined): string { |
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.
Is there a way to avoid using Command<any>
for this sort of thing. I've had this problem in my own code using cliffy as well.
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.
no currently not. i decided to not add any
as default value for the first generic param to make it clear that this type is using any
, but i would be also fine to add any
as default value.
But in generally i'm also not very happy with the generic type params, maybe i will refactor them in cliffy v2.
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.
Thx @andrewthauer for looking into this! 👍 I have added a few comments.
if (ctx.execute) { | ||
return await this.execute(ctx.env, ctx.unknown); | ||
} else { | ||
// TODO: Resolve typing for options |
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 should work:
return { cmd: this, options, literal: [], args: ctx.unknown };
@@ -1750,6 +1761,9 @@ export class Command< | |||
const args = this.parseArguments(ctx, options); | |||
this.literalArgs = ctx.literal; | |||
|
|||
// | |||
// TODO: How can we defer executing this when ctx.execute is false? | |||
// | |||
// Execute option action. | |||
if (ctx.actions.length) { |
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.
Yes, this should somehow be moved to the execute
method.
I was looking into this some time ago and noticed this as well. I have indeed thought about exposing the context, because I have also thought about customizing the ActionHandler
to have a context as well as an argument instead of the options
and args
arguments. But since this would be a major change, i have planned to look into this again for cliffy v2.
But maybe we find a nother way to solve this issue for v1.
} catch (error: unknown) { | ||
this.handleError(error); | ||
if (ctx.execute) { |
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 think throwing an error is fine, but we need to call the handleError
method and maybe add a throw
option to it to throw the error.
import { CompletionsCommand } from '../../command/completions/completions_command.ts'; | ||
import { HelpCommand } from '../../command/help/help_command.ts'; | ||
|
||
function getCommandFullname(command: Command<any> | undefined): string { |
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.
no currently not. i decided to not add any
as default value for the first generic param to make it clear that this type is using any
, but i would be also fine to add any
as default value.
But in generally i'm also not very happy with the generic type params, maybe i will refactor them in cliffy v2.
closes #647
@c4spar - This is a very early draft at implementing your suggested approach to allow the
parse
method to be called without executing. I've got this mostly working with minimal changes. However there are a couple of initial things I'm not sure how to proceed with and would love your guidance/suggestions:--help
) are not executed insideparseCommand
and not by theexecute
function. TheParsingContext
is the only thing that tracks these actions at the moment, and I suspect we don't want to expose that. We likely this needs to be unified into the execute command somehow?literal
field in place ofargs
which satisfies the return type shape. However, the current nameliteral
isn't the most intuitive either imo. Maybe it makes sense to renameliteral
toargs
if possible?I've added an example which demonstrates the current usage. It seems to mostly work except for when passing
--help
. I've also added some inline comments on areas I think need work.