| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.ivy.util.cli; |
| |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.Map; |
| |
| import org.apache.ivy.util.StringUtils; |
| |
| public class CommandLineParser { |
| private static final int MIN_DESC_WIDTH = 40; |
| |
| private static final int MAX_SPEC_WIDTH = 30; |
| |
| private Map<String, Option> options = new LinkedHashMap<>(); |
| |
| private Map<String, List<Option>> categories = new LinkedHashMap<>(); |
| |
| public CommandLineParser() { |
| } |
| |
| public CommandLineParser addCategory(String category) { |
| categories.put(category, new ArrayList<Option>()); |
| return this; |
| } |
| |
| public CommandLineParser addOption(Option option) { |
| options.put(option.getName(), option); |
| if (!categories.isEmpty()) { |
| // LinkedHashMap hides its tail... |
| new LinkedList<>(categories.values()).getLast().add(option); |
| } |
| return this; |
| } |
| |
| public CommandLine parse(String[] args) throws ParseException { |
| CommandLine line = new CommandLine(); |
| |
| int index = args.length; |
| ListIterator<String> iterator = Arrays.asList(args).listIterator(); |
| while (iterator.hasNext()) { |
| String arg = iterator.next(); |
| if ("--".equals(arg)) { |
| // skip this argument and stop looping |
| index = iterator.nextIndex(); |
| break; |
| } |
| |
| if (!arg.startsWith("-")) { |
| index = iterator.previousIndex(); |
| break; |
| } |
| |
| Option option = options.get(arg.substring(1)); |
| if (option == null) { |
| throw new ParseException("Unrecognized option: " + arg); |
| } |
| line.addOptionValues(arg.substring(1), option.parse(iterator)); |
| } |
| |
| // left over args |
| String[] leftOverArgs = new String[args.length - index]; |
| System.arraycopy(args, index, leftOverArgs, 0, leftOverArgs.length); |
| line.setLeftOverArgs(leftOverArgs); |
| |
| return line; |
| } |
| |
| public void printHelp(PrintWriter pw, int width, String command, boolean showDeprecated) { |
| pw.println("usage: " + command); |
| // compute the largest option spec |
| int specWidth = 0; |
| for (Option option : options.values()) { |
| if (option.isDeprecated() && !showDeprecated) { |
| continue; |
| } |
| specWidth = Math.min(MAX_SPEC_WIDTH, Math.max(specWidth, option.getSpec().length())); |
| } |
| |
| // print options help |
| for (Map.Entry<String, List<Option>> entry : categories.entrySet()) { |
| pw.println("==== " + entry.getKey()); |
| for (Option option : entry.getValue()) { |
| if (option.isDeprecated() && !showDeprecated) { |
| continue; |
| } |
| // print option spec: option name + argument names |
| String spec = option.getSpec(); |
| pw.print(" " + spec); |
| int specLength = spec.length() + 1; |
| pw.print(StringUtils.repeat(" ", specWidth - specLength)); |
| |
| // print description |
| StringBuilder desc = new StringBuilder((option.isDeprecated() ? "DEPRECATED: " : "") |
| + option.getDescription()); |
| int count = Math.min(desc.length(), width - Math.max(specLength, specWidth)); |
| // see if we have enough space to start on the same line as the spec |
| if (count > MIN_DESC_WIDTH || desc.length() + specLength < width) { |
| pw.print(desc.substring(0, count)); |
| desc.delete(0, count); |
| } |
| pw.println(); |
| |
| // print remaining description |
| while (desc.length() > 0) { |
| pw.print(StringUtils.repeat(" ", specWidth)); |
| count = Math.min(desc.length(), width - specWidth); |
| pw.println(desc.substring(0, count)); |
| desc.delete(0, count); |
| } |
| } |
| pw.println(); |
| } |
| } |
| } |