1 /* |
|
2 * CDDL HEADER START |
|
3 * |
|
4 * The contents of this file are subject to the terms of the |
|
5 * Common Development and Distribution License (the "License"). |
|
6 * You may not use this file except in compliance with the License. |
|
7 * |
|
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 * or http://www.opensolaris.org/os/licensing. |
|
10 * See the License for the specific language governing permissions |
|
11 * and limitations under the License. |
|
12 * |
|
13 * When distributing Covered Code, include this CDDL HEADER in each |
|
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 * If applicable, add the following below this CDDL HEADER, with the |
|
16 * fields enclosed by brackets "[]" replaced with your own identifying |
|
17 * information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 * |
|
19 * CDDL HEADER END |
|
20 */ |
|
21 |
|
22 /* |
|
23 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. |
|
24 */ |
|
25 |
|
26 package com.oracle.solaris.vp.util.cli; |
|
27 |
|
28 import java.util.*; |
|
29 import com.oracle.solaris.vp.util.misc.TextUtil; |
|
30 import com.oracle.solaris.vp.util.misc.finder.Finder; |
|
31 |
|
32 public class HelpFormatter { |
|
33 // |
|
34 // Instance data |
|
35 // |
|
36 |
|
37 private String description; |
|
38 private UsageFormatter formatter; |
|
39 private String optionsLabel = Finder.getString("command.help.options"); |
|
40 |
|
41 // |
|
42 // Constructors |
|
43 // |
|
44 |
|
45 public HelpFormatter(String description, UsageFormatter formatter) { |
|
46 this.description = description; |
|
47 this.formatter = formatter; |
|
48 } |
|
49 |
|
50 // |
|
51 // HelpFormatter methods |
|
52 // |
|
53 |
|
54 public String getDescription() { |
|
55 return description; |
|
56 } |
|
57 |
|
58 public UsageFormatter getUsageFormatter() { |
|
59 return formatter; |
|
60 } |
|
61 |
|
62 public void setOptionsLabel(String optionsLabel) { |
|
63 this.optionsLabel = optionsLabel; |
|
64 } |
|
65 |
|
66 public String getOptionsLabel() { |
|
67 return optionsLabel; |
|
68 } |
|
69 |
|
70 public String getHelp() { |
|
71 UsageFormatter usage = getUsageFormatter(); |
|
72 OptionElement[] options = getOptionElements(); |
|
73 OptionFormatter formatter = usage.getOptionFormatter(); |
|
74 |
|
75 StringBuilder buffer = new StringBuilder(); |
|
76 int width = usage.getWidth(); |
|
77 |
|
78 buffer.append(usage.getUsage()). |
|
79 append("\n\n"). |
|
80 append(TextUtil.format(getDescription(), width, "", "", false)); |
|
81 |
|
82 if (options.length > 0) { |
|
83 int indentlen = usage.getIndent(); |
|
84 String indent2 = String.format("%" + indentlen + "s", ""); |
|
85 |
|
86 String optionsLabel = getOptionsLabel(); |
|
87 if (optionsLabel != null) { |
|
88 buffer.append("\n\n").append(getOptionsLabel()); |
|
89 } |
|
90 |
|
91 for (OptionElement option : options) { |
|
92 String synopsis = formatter.getFormatted(option, true); |
|
93 buffer.append("\n\n"); |
|
94 |
|
95 String indent1; |
|
96 String description = option.getDescription(); |
|
97 |
|
98 // Can synopsis and description be on the same line? |
|
99 if (synopsis.length() + 1 <= indentlen) { |
|
100 description = String.format("%-" + indentlen + "s%s", |
|
101 synopsis, description); |
|
102 indent1 = ""; |
|
103 } else { |
|
104 buffer.append(synopsis); |
|
105 if (!description.isEmpty()) { |
|
106 buffer.append("\n"); |
|
107 } |
|
108 indent1 = indent2; |
|
109 } |
|
110 |
|
111 buffer.append(TextUtil.format(description, width, indent1, |
|
112 indent2, false)); |
|
113 } |
|
114 } |
|
115 |
|
116 return buffer.toString(); |
|
117 } |
|
118 |
|
119 // |
|
120 // Private methods |
|
121 // |
|
122 |
|
123 private OptionElement[] getOptionElements() { |
|
124 // Recursively retrieve all OptionElements |
|
125 HashMap<String, OptionElement> map = |
|
126 new HashMap<String, OptionElement>(); |
|
127 getOptionElements(getUsageFormatter().getOption(), map); |
|
128 |
|
129 ArrayList<OptionElement> elements = new ArrayList<OptionElement>(); |
|
130 elements.addAll(map.values()); |
|
131 |
|
132 Collections.sort(elements, |
|
133 new Comparator<OptionElement>() { |
|
134 public int compare(OptionElement a, OptionElement b) { |
|
135 String aName = a.getName(); |
|
136 String bName = b.getName(); |
|
137 |
|
138 int result = aName.toLowerCase().compareTo( |
|
139 bName.toLowerCase()); |
|
140 |
|
141 if (result == 0) { |
|
142 // Lowercase before uppercase |
|
143 result = bName.compareTo(aName); |
|
144 } |
|
145 |
|
146 return result; |
|
147 } |
|
148 }); |
|
149 |
|
150 return elements.toArray(new OptionElement[elements.size()]); |
|
151 } |
|
152 |
|
153 private void getOptionElements( |
|
154 Option option, HashMap<String, OptionElement> map) { |
|
155 |
|
156 if (option.isDocumented()) { |
|
157 if (option instanceof OptionElement) { |
|
158 OptionElement element = (OptionElement)option; |
|
159 String key = element.getName() + element.getArgName(); |
|
160 map.put(key, element); |
|
161 } else |
|
162 |
|
163 if (option instanceof OptionGroup) { |
|
164 for (Option o : ((OptionGroup)option).getOptions()) { |
|
165 getOptionElements(o, map); |
|
166 } |
|
167 } |
|
168 } |
|
169 } |
|
170 } |
|