-
-
Notifications
You must be signed in to change notification settings - Fork 816
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
Allow -exec to work as --exec #226
Conversation
If we encounter -exec, it is simply parsed to be --exec, this ensures that exec works in this fashion, but sadly removes short arg support for all those xec files. Rename function, shorten names of types. Also, do not bother running the map over if no entries are specifically exec.
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.
Cool idea! Thank you very much!
Could you please also add a small test?
With this approach, there is a small danger when someone wants to pass -exec
to a command that is called via --exec
😄
src/main.rs
Outdated
@@ -170,3 +172,25 @@ fn main() { | |||
Err(err) => error(err.description()), | |||
} | |||
} | |||
|
|||
fn transform_args_with_exec() -> Vec<OsString> { | |||
let target = { |
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.
You can use OsString::from("-exec")
.
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.
Thanks! I had missed that
src/main.rs
Outdated
ex | ||
}; | ||
|
||
if !std::env::args_os().any(|v| v == target) { |
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.
If we are going to traverse the arguments anyway, I think we can leave out this check. Just try to replace -exec
with --exec
below.
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've removed this, but please see my comment below
src/main.rs
Outdated
}; | ||
|
||
env::args_os() | ||
.map(|v| if v == target { replacement.clone() } else { v }) |
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.
Instead of replacement.clone()
, you can use OsString::from("--exec")
here.
src/main.rs
Outdated
@@ -170,3 +172,25 @@ fn main() { | |||
Err(err) => error(err.description()), | |||
} | |||
} | |||
|
|||
fn transform_args_with_exec() -> Vec<OsString> { |
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.
Could we add a doc-string here to describe what the function does?
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.
For sure, no problem
It is true that -exec passed as an argument to a previous --exec option of fd would result in an unexpected change of the given parameter. My initial thought was to only change the first instance of -exec, but as exec is a parameter that can be repeated this would not work. I suppose it comes down to how much weight we want to give to -exec appearing as an arg to another command? Should it be similar to .xec where we simply don't worry about the possibility? Or would limiting the number of --exec occurrences to one be a potential solution for better consistency (causing it's own problems when coming before positional arguments however)? If multiple is desired, and we are worried about changing -exec given to the --exec target, then a more complex solution such as a full-on pre-parser seem to be the only option left. |
Oh, actually
I'd be okay with that.
I think that would be even better. |
Also, limit usage of --exec option to single instance.
Ok, so I've tried to reach a middle ground with the handling. I have limited --exec to a single occurrence (as opt for fd). This means I am not able to only transform the first instance of -exec as it will no longer cause an error in clap. I've added some tests, both to the handling of the incoming args, and the overall operation. An option of -exec passed to a secondary command will also be transformed, but at least this allows the downstream to provide it's own error explanation. |
Why not? Clap will not throw an error because it knows that the other A possible implementation could look like this: /// Replace the first occurence of `-exec` with `--exec`.
fn transform_args_with_exec<I>(original: I) -> Vec<OsString>
where
I: Iterator<Item = OsString>,
{
let mut new_args: Vec<OsString> = original.collect();
let target = OsString::from("-exec");
let result = new_args.iter().position(|arg| *arg == target);
if let Some(pos) = result {
new_args[pos] = OsString::from("--exec");
}
return new_args;
} (you can use this in your tests via It works as expected:
This will actually still leave us with a problem if someone passes the actual
|
To be 99.9% foolproof, we could actually only replace the first |
When only the first is changed, clap will later on see the second -exec passed to fd as --extension instead. As I removed the .multiple from the exec arg, it is now relying on the validation from clap. Currently this means the only error that will occur is when someone tries to pass -exec to the given executable and not fd |
Oh, you mean if someone passes |
Yes, this causes a strange hybrid behavior in which we have new action for the first -exec but then the same error from the original bug for any further -exec |
I figured that leaving any errors to the downstream makes at least our behavior consistent, and since -exec isn't the most common option (I only know of find) then this is probably the least impactful |
@sharkdp I've created a small state machine that will keep track of it's current position (in exec option or out) and properly convert -exec as expected. It will need some cleanup and some code should be moved around, but it could do the trick. |
Oh wow, nice! 👍 (we could move that code to the |
Thanks! I've actually gone over it again and reduced it to a single fold that does the same thing without all the extra junk. It's pretty concise and works as expected, we change any -exec to --exec, but not when inside of a previous --exec, -exec, or -x block, delimited with the terminator ; |
Have you considered using the validator method in clap to solve this problem? https://docs.rs/clap/2.29.2/clap/struct.Arg.html#method.validator |
I had looked at it, but it does not seem to provide a way to change one argument into another. It's not really validation that is being looked for, rather to keep some level of similarity to the standard find utility. |
@sharkdp This is pretty much done for what we wanted to do. Any more changes you'd like me to make? |
No, it looks great. Thank you very much! |
This will check for the presence of -exec and change it to --exec prior to passing the args to clap to support the request of #221
There may be some merit to updating the help docs for -e option to ensure it is known that an .xec file extension will require the --extension option instead. But that may not really be needed as .xec files don't really seem to be a common type.