Skip to content
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

Read command line arguments from file #68

Open
isolaol opened this issue Mar 8, 2015 · 4 comments
Open

Read command line arguments from file #68

isolaol opened this issue Mar 8, 2015 · 4 comments
Labels

Comments

@isolaol
Copy link

isolaol commented Mar 8, 2015

Hi Adam,

This is slightly more involved enhancement idea but it could also set PowerArgs apart from the other command line parsers.

Commands can become lengthy at times. Especially when command line programs are part of an automated process. Reading selected argument values or even the entire list of arguments from a file become handy facility. Let's take email recipients as an example:

mail.exe -from [email protected] -to [email protected] [email protected] [email protected] -cc [email protected] -subject "Something strange has happened" -body "Hi friends, It's too lengthy to explain. We need to investigate it. I will call you shortly." -server smtp.disney.com -port 587 -priority high -user goofy -password funny

With some help from PowerArgs whis could become

mail.exe -from [email protected] -to @recipients.txt -subject "Something strange has happened" -body @message.txt -server smtp.disney.com -port 587 -priority high -user goofy -password funny

In this case, the recipients.txt file would contain:

.. and message.txt would contain:

Hi friends, It's too lengthy to explain. We need to investigate it. I will call you shortly.

Much better, now. Especially in automated environments where things like message.txt and recipients.txt are written by other programs.

The expansion of special command line arguments come in two variations, a) read entire command line from file and b) read some argument values from file. I will try sketch out few ways how the user could indicate that the expansion should happen. The first thing you need to decide is special marker that indicates expansion of argument value with text from file. I have selected '@' but you may come up with something else if you wish.

A) read entire command line from file

mail.exe @C:\Path\Arguments.txt

in which case Arguments.txt could contain:

-from [email protected]
-to [email protected] [email protected] [email protected]
-cc [email protected]
-subject "Something strange has happened"
-body "Hi friends, It's too lengthy to explain. We need to investigate it. I will call you shortly."
-server smtp.disney.com -port 587
-priority high
-user goofy -password funny

In this case PowerArgs will read the file and replace line breaks with spaces.

B) read an individual argument value from file
We will have multiple options to go with in this case.

  1. Replace argument prefix (-) with marker (@): mail.exe @recipients C:\Path\File.txt
  2. Add marker (@) between prefix (-) and argument name: mail.exe -@recipients C:\Path\File.txt
  3. Add marker (@) after the argument name: mail.exe -recipients@ C:\Path\File.txt
  4. Add marker (@) before argument value: mail.exe -recipients @C:\Path\File.txt

My personal favorites are 1. and 4. The decision is yours.

So, what it takes to implement this powerful feature?

The developer will have to call Args.Parse<MyArgs>(command); instead of Args.Parse<MyArgs>(args);. The command will usually come from Environment.CommandLine. Then the PowerArgs proceeds with these two extra steps:

  1. Special markers are expanded with contents from file.
  2. The resulting is split into parts just like C-library does.

The parsing process will continue normally after the second extra step since command line arguments look normal, now. All markers and file names are gone. Arguments are an array of strings.

The tricky part is to implement conversion of command line string to argument string array the same way C-library does it and without returning application name. The process is described in http://msdn.microsoft.com/en-us/library/a1y7w461.aspx

I have a working string splitter, I think. I am ready to contribute it in case you are interested to implement this advanced feature!

I could do this extra processing myself in between static void Main(string[] args) and Args.Parse<MyArgs>(args);. Anyhow, I think that PowerArgs it is a natural candidate to handle it since the entire purpose of PowerArgs is to make command line parsing easier (and so far it is very good at it!).

I have users Args.Parse() as an example of public interface modification. This expansion feature can be implemented as an overload of Args.Parse() method. The similar overload may be needed in other methods, too.

An extra consideration goes to text file encodings. And this is the part where we jump into attributes, again.

The text file expansion needs some attributes. The first one provides metadata about text file encoding, ArgExpansionEncodingAttribute(System.Text.Encoding encoding). The default could be either UTF-8 or Default (Current Windows ANSI codepage). But it should be possible to define CP850, for example. I see that this attribute can be argument class specific (common to all properties of argument class) or property specific. Making it property specific is playing safe... In a rare case when files will have differing encodings. On the other hand it's quite verbose.

The another atttribute which may be necessary is the one that provisions property to accept expansion with file contents. The developer should be able to put it in two levels: to argument class (default to all properties) or to single property. Something like ArgExpansion(boolean active). The same attribute could also have an argument that sets the accepted marker if developer wishes to use non-default marker.

Kind regards,
Olli-Pekka Isola

@isolaol
Copy link
Author

isolaol commented Mar 11, 2015

It's necessary to call Environment.ExpandEnvironmentVariables(string) -method for each line read from file during command line expansion. IT is a natural assumption that command line excerpts in file can have environment variables (%variable%) just like similar parts in the real command line string.

@adamabdelhamed
Copy link
Owner

This is an interesting set of suggestions. I'll want to make sure it integrates well with other PowerArgs features. Let me think on this for a while.

Thanks,
Adam

@bladeoflight16
Copy link

The first tool I'd reach for to solve a problem like this is a command line, such as bash or PowerShell. I'd create a script that invokes the command with the arguments. What can PowerArgs do better than they can?

@aasim
Copy link

aasim commented Mar 9, 2021

I really like this idea. I have something similar implemented in my current solution. The base problem is the same, there are too many arguments and you don't want to pass in all the arguments through the command line, you can also say that some arguments like logging level or service internals (like parallelism) are better suited to be provided from a config file.

The way I have it, all arguments are parsed first using PowerArgs, then I fill in the gaps in the params by reading the config file. Its not an elegant solution, but it might be a well known pattern.

I was planning on forking this project to add that feature, but if you begin working on this, let me know and I can contribute here.

Aasim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants