-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Early support for reading program arguments from env-variable (issue #712) #734
Conversation
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.
Looks great so far, I think if we make those two simple changes I'd be good with a merge.
src/app/mod.rs
Outdated
@@ -30,6 +31,8 @@ use errors::Result as ClapResult; | |||
pub use self::settings::AppSettings; | |||
use completions::Shell; | |||
|
|||
const DEFAULT_ARGS_ENV_VAR: &'static str = "VAR"; |
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 we can do away with a default variable name. The user typing None
is just as if they'd typed the env var name VAR
src/app/mod.rs
Outdated
/// env-var `env_var_name`. | ||
/// | ||
/// Defaults to read from "VAR" if `env_var_name` is `None`. | ||
pub fn get_matches_with_env(self, env_var_name: Option<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.
Let's change this function declaration to:
pub fn get_matches_with_env<S: Into<&'b str>(self, env_var_name: S) -> ArgMatches<'a> {
This will allow people to use string slices too and not have to allocate a string if they don't need to. This will also require a few lines to change inside the function too, but not many.
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.
Ahh right, I've used the Into-trait once or twice before. I always have to lookup the syntax though :)
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.
Shouldn't that be <S:AsRef<str>(self, env_var_name: &S)
?
env_var_name
isn't stored anywhere, so why the lifetime 'b
?
And &str
doesn't implement From<&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.
@tormol Good catch! Yeah the AsRef
trait should be used, not Into
Also, when you change these commits, could you use the commit subject to something like This will allow that commit to be picked up automatically by |
Ah yeah, and the unit tests are fine where they are. I'm good with using those or placing them as integration tests in the |
About the commit-message, should I rebase the history to a single commit? EDIT: Nevermind, I found the contribution-guidelines! |
I just realized that this simple solution might be too simple. Take the following case:
if the program calls |
src/app/mod.rs
Outdated
.chain(vargs.split(0x20) | ||
.into_iter() | ||
.map(|s| s.to_os_string())) | ||
.collect(); |
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 b' '
instead of 0x20
.split()
returns an iterator (osstringext::OsSplit
), so .into_iter()
does nothing.
Vec
implements std::iter::Extend
so this can be written as args.extend(vargs.split(b' ').map(...))
.
There are some other issues with concatenating:
Fixing that might be difficult, and i'd guess environmental variables will mostly be used to set options, so I don't think this is a big problem. Separating arguments with bash doesn't seem to split on non-ASCII whitespace either, so that's probably fine but you might want to separate on tabs and newlines too. |
Ah yeah, I'd forgotten we talked about that. There's not really a good way around this, unless we keep track of how a particular argument was matched. That may be quite a bit more complicated to implement. |
@tormol regards to your bullet points above, I think so long as the env args are always first, or last it's fine. So long as it's deterministic and documented that way. Personally I'd prefer that the env args come first. Allowing them to be overriden if the consumer of the library uses There are quite a few edge cases that have many different correct answers depending on use case. If an option allows multiple values, should |
We could also have different methods for _pre_pending vs _ap_pending these env args. |
Just pushed a rebased commit, but I'm having a problem with an error I haven't seen before:
Doesn't sound like a difficult error but I don't understand what I tried splitting on space, tab, and newline but |
The error comes from |
I have written an iterator that returns the arguments in a variable. |
src/app/mod.rs
Outdated
/// Similar to [`App::get_matches`] but also reads args from | ||
/// env-var `env_var_name`. | ||
/// | ||
/// If the same argument is specified both as program argument |
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.
Let's change this to say, "The env var args are appended to the manually entered arguments (if any) and thus if an argument is provided both in the env var and manually, this could result in either a conflict, override, or additional value depending on the specific rules for said arg."
@purew looks great! Could you just change that one comment so that it's more explicit? This way people know no magic is happening, and they must be careful. Once that is done, @tormol if you'd like to give any other advice I think this will be good for a merge. Once this is merged I'd also be interested in adding in the splitting that @tormol wrote once we can add some tests which could be done as a separate PR. |
@purew: safe/unsafe for who? |
@tormol I was merely curious about byte-sequences in env-vars and if common shell's allow that? |
VAR=`echo -e '\xff'` works in bash. |
@purew see #748 where @casey mentions having a |
☔ The latest upstream changes (presumably #784) made this pull request unmergeable. Please resolve the merge conflicts. |
I'm going to close this due to inactivity and punting on this issue until I have a little more free-time to work on it - feel free to re-open and we can re-energize it. |
Ok, are all "upstream" blockers resolved? You mentioned solidifying a particular API before continuing on this PR:
|
@purew for single args getting a value from the ENV all blockers are solved. That could be merged today. The precedence is CLI overrides all, ENV overrides default vals, and defaults override empty values. The The allowing an ENV var to hold an arbitrary number of args (such as |
Hi Kevin,
This is Anders from Thursday's meetup. Take a look at the code and let me know what you want changed or what is missing?
Also, I wasn't sure where you put the unit-tests so it went in the same file. I also didn't spend any time on documentation until the interface is ironed out.
This change is