All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codetaco.cli.input.CommandLineParser Maven / Gradle / Ivy

package com.codetaco.cli.input;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.codetaco.cli.type.ICmdLineArg;

/**
 * This parser takes a typical command line entry and creates tokens. A command
 * line is made up of key words and values. A key word is prefixed by a - or
 * two. Brackets or parenthesis may be used to create subparsers.
 *
 * @author Chris DeGreef [email protected]
 */
public class CommandLineParser extends AbstractInputParser implements IParserInput {
    static private StringBuilder convertToString(
      final File commandFile)
      throws FileNotFoundException,
      IOException {
        final FileReader fis = new FileReader(commandFile);
        try (final BufferedReader buf = new BufferedReader(fis)) {
            final StringBuilder str = new StringBuilder();
            String input = buf.readLine();
            while (input != null) {
                /*
                 * Allow comments if the first character on a line is #. It must
                 * be column 1.
                 */
                if (input.length() > 0 && input.charAt(0) != '#') {
                    str.append(input);
                    str.append(' ');
                }
                input = buf.readLine();
            }
            return str;
        }
    }

    /**
     * 

* getInstance. *

* * @param commandPrefix a char. * @param allowEmbeddedCommandPrefix a boolean. * @param args a {@link java.io.File} object. * @return a {@link com.codetaco.cli.input.IParserInput} object. * @throws java.io.IOException if any. */ static public IParserInput getInstance( final char commandPrefix, final boolean allowEmbeddedCommandPrefix, final File args) throws IOException { final CommandLineParser parser = new CommandLineParser(); parser.commandPrefix = commandPrefix; parser.allowEmbeddedCommandPrefix = allowEmbeddedCommandPrefix; parser.commandLine = convertToString(args).toString(); return parser; } /** *

* getInstance. *

* * @param commandPrefix a char. * @param allowEmbeddedCommandPrefix a boolean. * @param args a {@link java.lang.String} object. * @return a {@link com.codetaco.cli.input.IParserInput} object. */ static public IParserInput getInstance( final char commandPrefix, final boolean allowEmbeddedCommandPrefix, final String... args) { final CommandLineParser parser = new CommandLineParser(); parser.commandPrefix = commandPrefix; parser.allowEmbeddedCommandPrefix = allowEmbeddedCommandPrefix; final StringBuilder str = new StringBuilder(); for (int c = 0; c < args.length; c++) { str.append(args[c].replaceAll("\\\\", "\\\\\\\\")); str.append(" "); } parser.commandLine = str.toString(); return parser; } /** *

* getInstance. *

* * @param commandPrefix a char. * @param args a {@link java.io.File} object. * @return a {@link com.codetaco.cli.input.IParserInput} object. * @throws java.io.IOException if any. */ static public IParserInput getInstance( final char commandPrefix, final File args) throws IOException { return getInstance(commandPrefix, false, args); } /** *

* getInstance. *

* * @param commandPrefix a char. * @param args a {@link java.lang.String} object. * @return a {@link com.codetaco.cli.input.IParserInput} object. */ static public IParserInput getInstance( final char commandPrefix, final String... args) { return getInstance(commandPrefix, false, args); } /** *

* unparseTokens. *

* * @param args a {@link java.util.List} object. * @return a {@link java.lang.String} object. */ static public String unparseTokens( final List> args) { final StringBuilder out = new StringBuilder(); unparseTokens(args, out); return out.toString(); } /** *

* unparseTokens. *

* * @param args a {@link java.util.List} object. * @param out a {@link java.lang.StringBuilder} object. */ static public void unparseTokens( final List> args, final StringBuilder out) { final Iterator> aIter = args.iterator(); boolean first = true; while (aIter.hasNext()) { final ICmdLineArg arg = aIter.next(); if (arg.isParsed()) { if (!first) out.append(" "); first = false; arg.exportCommandLine(out); } } } protected String commandLine; char commandPrefix; boolean allowEmbeddedCommandPrefix; private CommandLineParser() { super(); allowEmbeddedCommandPrefix = true; } /** * {@inheritDoc} */ @Override public Token[] parseTokens() { char delim = ' '; final StringBuilder part = new StringBuilder(); boolean inToken = false; int startX = 0; final List tokens = new ArrayList<>(); char thisChar = ' '; char prevChar; for (int scanX = 0; scanX < commandLine.length(); scanX++) { prevChar = thisChar; thisChar = commandLine.charAt(scanX); char nextChar = ' '; /* * Look ahead one char if possible */ if (scanX < commandLine.length() - 2) nextChar = commandLine.charAt(scanX + 1); if (inToken) { if (delim != ' ' && thisChar == delim) { tokens.add(new Token(commandPrefix, part.toString(), startX, scanX + 1, true)); part.delete(0, part.length()); inToken = false; } else /* * As long as we are not in a quoted literal then we want * to split the token if any of these conditions are * true. */ if (delim == ' ' && (Character.isWhitespace(thisChar) || thisChar == '(' || thisChar == ')' || thisChar == '[' || thisChar == ']' || thisChar == ';' || thisChar == ',' || thisChar == '"' || thisChar == '\'' /* * = is whitespace unless it is followed by an * open paren, then it is an equation directive */ || (thisChar == '=' && nextChar != '(') /* * Make sure to allow double dashes at the * beginning of a token, the second one is * technically not an embedded dash. */ || (!allowEmbeddedCommandPrefix && thisChar == commandPrefix && prevChar != commandPrefix) /* * Even if we are allowing embedded * tokens we don't want to allow double * dashes within a token, only at the * beginning. A double dash will * indicate that a new token should be * started instead. */ || (allowEmbeddedCommandPrefix && thisChar == commandPrefix && nextChar == commandPrefix) /* * An embedded dash will cause a new * token if the current token started * with a single dash */ || (thisChar == commandPrefix && part.length() > 1 && part.charAt(0) == commandPrefix && part.charAt(1) != commandPrefix))) { boolean forceLiteral = false; /* * Single char commands can not be a number. This allows * negative numbers to be entered without escaping them or * surrounding them with delimiters. */ if (part.length() > 1) if (part.charAt(0) == commandPrefix && Character.isDigit(part.charAt(1))) forceLiteral = true; tokens.add(new Token(commandPrefix, part.toString(), startX, scanX, forceLiteral)); part.delete(0, part.length()); /* * rescan char */ --scanX; inToken = false; } else { if (thisChar == '\\') thisChar = commandLine.charAt(++scanX); part.append(thisChar); } } else { /* * Completely throw away whitespace characters unless quoted. * They served their purpose in that they caused a token to be * stopped. */ if (Character.isWhitespace(thisChar) || thisChar == ':' || thisChar == ';' || thisChar == ',' || (thisChar == '=' && nextChar != '(')) continue; if (thisChar == '(' || thisChar == ')' || thisChar == '[' || thisChar == ']') { tokens.add(new Token(commandPrefix, "" + thisChar, scanX, scanX + 1, false)); continue; } if (thisChar == '"' || thisChar == '\'') delim = thisChar; else { delim = ' '; part.append(thisChar); } inToken = true; startX = scanX; } } if (inToken) tokens.add(new Token(commandPrefix, part.toString(), startX, commandLine.length(), delim != ' ')); return tokens.toArray(new Token[tokens.size()]); } /** * {@inheritDoc} */ @Override public String substring(final int inclusiveStart, final int exclusiveEnd) { return commandLine.substring(inclusiveStart, exclusiveEnd); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy