29 Aug 2013 @ 2:35 AM 

Parameters and Arguments passed on the command line are something that we simply cannot seem to get rid of. Even with today’s UI-Centric Operating System and interaction Model, Application still expose a number of features through the use of Command-Line parameters and arguments.

There are a number of relatively complex libraries for dealing with Command Line parameters in any number of languages, most of which aim for the typical Command-line stuff; switches, switches with arguments, etcetera. Many of these are relatively complex; I created a COM Component in VB6 to parse Command Line Parameters and I believe I even created a C# Port to a self-contained file for some of my C# applications.

There is of course a simpler way of creating, parsing, and evaluating the arguments you are provided on the commandline, though many shrink from the idea- it involves simply changing up how you interpret arguments. Rather than switches, you instead simply interpret all your arguments as a set of key/value pairs.

Most Programming language environments will perform the task of actually splitting your command line at spaces. You have to workaround this since it might interfere with your own parsing. Some languages provide a way to directly access the CommandLine your application ran with, as a single string. Others, like Java, require you to simply paste together the arguments you are provided and hope for the best. (Java also has an anomoly when you are trying to pass arguments through a “java -jar” or “javaw -jar” call, too, but I’ll get to that in a moment).

The method I’ve found ideal is to simply have a method that accepts a string and then returns a HashMap consisting of key/value pairs, as present in the commandline. Both keys and values can be quoted to allow for spaces in their names, too. Here is a Java implementation of that Method:

The logic is exceedingly similar to some of the logic that was involved in my BASeParser XP Expression Evaluator. The ubiquitous “inquote” boolean makes a cameo in this Java implementation. the basic idea is that when it finds a quote, it toggles “inquote”; and it will only recognize separators (spaces) and equals signs (used to separate keys from values) when inquote is false. If it finds a space, it will take what it has for a key and the value it’s building and add those to the HashMap it is building. If it finds an equals sign, it will take what it’s currently got in ValueRunner and throw it into the Key. the purpose being to allow the key and name to be enclosed in quotes if they contain spaces, so they don’t get split apart.

An example usage would require the original command line to be rebuilt:

This works by simply rebuilding the arguments Java has so helpfully split for us.

HOWEVER: this does have some caveats. The first seems to be that Java removes the quotations around any quotes entries, and it obviously get’s confused by our non-standard arguments. So we need a custom Join method for this task:

OK so maybe the Join I had was a lot simpler and just a standard Join() that didn’t take spaces and add quotes to each one if they were found. I only realized the caveat involving quotes (which explains the massive mystery that took me 3 hours to solve this morning, which I ended up chalking up to a known netbeans bug, which no doubt did not help clarify the problems I was having. Ideally I would be able to get the pure unfiltered and untainted Command Line; (sort of like .NET’s Environment.CommandLine Property) But there doesn’t appear to be a good way to do that in Java, as near as I can tell, which is a shame.

And that’s that: Now you have a method to parse a command line like this:

Which will give us these pairs:

Key Value
Username billy
password Hunter42
main weapon slarpy Gun

Tada! And now you can add helper methods, or encapsulate this functionality into a class and give it those helper methods, for all sorts of different features that manipulate or return given parameters or sets of command parameters. I personally have a “popParameter()” method that takes the hashmap, a key name, and a default value, and will retrieve the existing value of the given key if found and remove it or if not found return the default value.

Posted By: BC_Programming
Last Edit: 29 Aug 2013 @ 02:35 AM

EmailPermalinkComments Off on Command Line Parameters: A Java Approach
Tags
 21 Mar 2013 @ 9:08 AM 

Most application frameworks/languages provide access to the Command Line parameters passed to your application. Generally it is passed to your application as either a string or an array of strings. What you do not get automatically is the functionality to parse out switches.

Command-line parameters used to be the only way to communicate with a program. Fundamentally, the command line was your UI into the program. Different platforms took different approaches. Unix-like systems typically take the “invasive” route; they replace wildcards and then pass the resulting command line to the application. This means that you don’t have to do any shell expansion of wildcards (as it is known) but you have to account for the fact that your command line could include a lot of files. It’s a trade-off, really. Either way, I figured for the purposes of this library, we could stick to the platform- if the program is run with a wildcard, you’ll see the wildcard on windows, but it will have been expanded if you run the same program on Linux. It might be worth adding an option to “auto-expand” wildcards- just for consistencies sake, but that seems like a post for another day.

Either way, most applications also include flags and switches. This is more a De Facto standard that has cropped up- there is no hard and fast rulebook about what flags and switches are or how you are supposed to pass arguments, which can cause no end of confusion when it comes to reading application documentation. the .NET language just gives you the string, and leaves it up to you to decide how to interpret it. Some language libraries provide functionality to parse the Command Line appropriately, such as Python. C# doesn’t come with such a class…. So let’s make one!

First we need to determine what exactly can exist in a command line. My method allows for two things: Switches, and arguments. A Switch can include an argument, separated from the switch with a colon. For example:

In this case, we have three switches- switch, sw, and doall. The first two include an argument. My “syntax” allows for quotes in the arguments of switches as well as the “loose” arguments. We will evidently need classes to represent and parse Arguments, and another one for Switches. The parsing can be done sequentially. Although it’s not a recommended best practice, I chose to use by reference parameters in the class constructors. In order to keep things generic and accessible, both Switches and Arguments will derive from a CommandLineElement abstract class, which will force each base class to implement toString(). the ArgumentItem class will be used for parsing both “loose” arguments, as well as arguments found after a switch.

Arguments

Arguments are simple- if the first letter of the position is a quote, we look for the next quote that isn’t doubled up. Otherwise, we look for either the next whitespace or the end of the string. Each argument only needs the actual argument value.

The constructor is where the important stuff happens. the by reference parameter is used to define the starting position, and we update it when the constructor returns to point at the character after the argument. The class also defines some statics for implicit conversions to and from a string.

Now that we have the Argument class, we can define the Switch class. The actual syntax of switches often depends on the application but also seems to depend on the platform. for example, Linux tools favour the hyphen for single letter flags, and double hyphens for multi-character flags. Switches are also called flags. forward slash is not generally used as a switch or flag indicator. Windows platforms prefer the forward slash but generally allow for single hyphens as well. We aim to support all three syntaxes, and make the client application not have to worry about which it is. We also add support for arguments- a switch can be specific as such:

The element after the colon will be parsed as an argument and attached to the switch itself. But enough waffling- on to the Switch:

With the basic parsing logic completed, we need to consider how we want this to be used. Best way is to think of how we would like to use them:

Some basic take-aways from this. First, the Core Parser Object needs to provide an Indexer. In the above example, we see it is accessing Switches by passing in the Switch name. Other possibilities include using direct numeric indexes to refer to any argument- much like you would access elements in the framework provided args[] String array. Another possibility is to have the Argument of a switch auto-populate, rather than be null, when accessed:

Posted By: BC_Programming
Last Edit: 21 Mar 2013 @ 09:10 AM

EmailPermalinkComments Off on The Lost art of Command Line Parameters
Tags

 Last 50 Posts
 Back
Change Theme...
  • Users » 47469
  • Posts/Pages » 388
  • Comments » 105

PP



    No Child Pages.

Windows optimization tips



    No Child Pages.

Soft. Picks



    No Child Pages.

VS Fixes



    No Child Pages.

PC Build 1: “FASTLORD”



    No Child Pages.