Skip to content

Commit 4327271

Browse files
authored
#56: completion bash only (#187)
1 parent a3e3226 commit 4327271

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1755
-512
lines changed

cli/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
<artifactId>ide-cli</artifactId>
1313
<version>${revision}</version>
1414
<properties>
15-
<mainClass>com.devonfw.tools.ide.cli.Ide</mainClass>
16-
<imageName>ide</imageName>
15+
<mainClass>com.devonfw.tools.ide.cli.Ideasy</mainClass>
16+
<imageName>ideasy</imageName>
1717
<releaseName>${project.artifactId}-${os.detected.classifier}-${os.detected.arch}</releaseName>
1818
<java.version>17</java.version>
1919
<native.maven.plugin.version>0.9.28</native.maven.plugin.version>
@@ -52,7 +52,7 @@
5252
<artifactId>jackson-dataformat-xml</artifactId>
5353
<version>2.14.1</version>
5454
</dependency>
55-
<!-- Logging -->
55+
<!-- Logging (only for URL-Updaters) -->
5656
<dependency>
5757
<groupId>org.slf4j</groupId>
5858
<artifactId>slf4j-api</artifactId>

cli/src/main/java/com/devonfw/tools/ide/cli/CliArgument.java

Lines changed: 133 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.devonfw.tools.ide.cli;
22

3+
import java.util.Objects;
4+
35
/**
4-
* A single argument of a {@code main} method from a command-line-interface (CLI).
6+
* Represents an argument for a command-line-interface (CLI) and a chain to all its {@link #getNext(boolean)
7+
* successors}.
58
*
69
* @since 1.0.0
710
* @see #getNext(boolean)
@@ -14,27 +17,63 @@ public class CliArgument {
1417
*/
1518
public static final String END_OPTIONS = "--";
1619

17-
/** A dummy {@link CliArgument} to represent the end of the CLI arguments. */
18-
public static final CliArgument END = new CliArgument("«end»");
20+
/** A {@link CliArgument} to represent the end of the CLI arguments. */
21+
public static final CliArgument END = new CliArgument();
22+
23+
static final String NAME_START = "«start»";
1924

2025
private final String arg;
2126

2227
private String key;
2328

2429
private String value;
2530

26-
private CliArgument next;
31+
final CliArgument next;
32+
33+
private final boolean completion;
34+
35+
private CliArgument() {
36+
37+
super();
38+
this.arg = "«end»";
39+
this.next = null;
40+
this.completion = false;
41+
}
42+
43+
/**
44+
* The constructor.
45+
*
46+
* @param arg the {@link #get() argument}.
47+
* @param next the {@link #getNext() next}.
48+
*/
49+
protected CliArgument(String arg, CliArgument next) {
50+
51+
this(arg, next, false);
52+
}
2753

2854
/**
2955
* The constructor.
3056
*
3157
* @param arg the {@link #get() argument}.
58+
* @param next the {@link #getNext() next}.
59+
* @param completion the {@link #isCompletion() completion flag}.
3260
*/
33-
protected CliArgument(String arg) {
61+
protected CliArgument(String arg, CliArgument next, boolean completion) {
3462

3563
super();
64+
Objects.requireNonNull(arg);
65+
Objects.requireNonNull(next);
3666
this.arg = arg;
37-
this.next = END;
67+
this.next = next;
68+
this.completion = completion;
69+
}
70+
71+
/**
72+
* @return {@code true} if this is the argument to complete (should be the last one), {@code false} otherwise.
73+
*/
74+
public boolean isCompletion() {
75+
76+
return this.completion;
3877
}
3978

4079
/**
@@ -61,6 +100,22 @@ public boolean isLongOption() {
61100
return this.arg.startsWith("--");
62101
}
63102

103+
/**
104+
* @return {@code true} if this is a short option (e.g. "-b"), {@code false} otherwise.
105+
*/
106+
public boolean isShortOption() {
107+
108+
return (this.arg.length() >= 2) && (this.arg.charAt(0) == '-') && (this.arg.charAt(1) != '-');
109+
}
110+
111+
/**
112+
* @return {@code true} if this is a combined short option (e.g. "-bd"), {@code false} otherwise.
113+
*/
114+
public boolean isCombinedShortOption() {
115+
116+
return (this.arg.length() > 2) && (this.arg.charAt(0) == '-') && (this.arg.charAt(1) != '-');
117+
}
118+
64119
/**
65120
* @return {@code true} if {@link #END_OPTIONS}, {@code false} otherwise.
66121
*/
@@ -70,37 +125,67 @@ public boolean isEndOptions() {
70125
}
71126

72127
/**
73-
* @return {@code true} if this is the {@link #END}, {@code false} otherwise.
128+
* @return {@code true} if this is the {@link #END} of the arguments, {@code false} otherwise.
74129
*/
75130
public boolean isEnd() {
76131

77-
return (this == END);
132+
return (this.next == null);
133+
}
134+
135+
/**
136+
* @return {@code true} if this is the start of the arguments, {@code false} otherwise.
137+
*/
138+
public boolean isStart() {
139+
140+
return (this.arg == NAME_START); // not using equals on purpose
141+
}
142+
143+
/**
144+
* @param successors the number of {@link #getNext() successors} expected.
145+
* @return {@code true} if at least the given number of {@link #getNext() successors} are available, {@code false}
146+
* otherwise.
147+
*/
148+
public boolean hasMoreSuccessorsThan(int successors) {
149+
150+
if (successors <= 0) {
151+
return true;
152+
}
153+
CliArgument current = this;
154+
while (current != END) {
155+
successors--;
156+
if (successors == 0) {
157+
return true;
158+
}
159+
current = current.next;
160+
}
161+
return false;
162+
}
163+
164+
/**
165+
* @return the next {@link CliArgument} or {@code null} if this is the {@link #isEnd() end}.
166+
* @see #getNext(boolean)
167+
*/
168+
public CliArgument getNext() {
169+
170+
return this.next;
78171
}
79172

80173
/**
81174
* @param splitShortOpts - if {@code true} then combined short options will be split (so instead of "-fbd" you will
82175
* get "-f", "-b", "-d").
83-
* @return the next {@link CliArgument} or {@code null} if this is the last argument.
176+
* @return the next {@link CliArgument} or {@code null} if this is the {@link #isEnd() end}.
84177
*/
85178
public CliArgument getNext(boolean splitShortOpts) {
86179

87-
if (splitShortOpts && (this.next != null)) {
180+
if (splitShortOpts && (this.next != null) && !this.next.completion) {
88181
String option = this.next.arg;
89182
int len = option.length();
90183
if ((len > 2) && (option.charAt(0) == '-') && (option.charAt(1) != '-')) {
91-
CliArgument first = null;
92-
CliArgument current = null;
93-
for (int i = 1; i < len; i++) {
94-
CliArgument shortOpt = new CliArgument("-" + option.charAt(i));
95-
shortOpt.next = this.next.next;
96-
if (current == null) {
97-
first = shortOpt;
98-
} else {
99-
current.next = shortOpt;
100-
}
101-
current = shortOpt;
184+
CliArgument current = this.next.next;
185+
for (int i = len - 1; i > 0; i--) {
186+
current = new CliArgument("-" + option.charAt(i), current);
102187
}
103-
return first;
188+
return current;
104189
}
105190
}
106191
return this.next;
@@ -151,6 +236,9 @@ public String getArgs() {
151236
}
152237
StringBuilder sb = new StringBuilder();
153238
CliArgument current = this;
239+
if (current.isStart()) {
240+
current = current.next;
241+
}
154242
String prefix = "\"";
155243
while (!current.isEnd()) {
156244
sb.append(prefix);
@@ -162,55 +250,49 @@ public String getArgs() {
162250
return sb.toString();
163251
}
164252

253+
private CliArgument createStart() {
254+
255+
assert (!isStart());
256+
return new CliArgument(NAME_START, this);
257+
}
258+
165259
@Override
166260
public String toString() {
167261

168262
return this.arg;
169263
}
170264

171265
/**
172-
* @param args the command-line arguments from {@code main} method.
266+
* @param args the command-line arguments (e.g. from {@code main} method).
173267
* @return the first {@link CliArgument} of the parsed arguments or {@code null} if for empty arguments.
174268
*/
175269
public static CliArgument of(String... args) {
176270

177-
return of(true, args);
271+
return of(false, args);
178272
}
179273

180274
/**
181-
* @param splitShortOpt - to {@link #getNext(boolean) split combined short options} for the first argument.
182-
* @param args the command-line arguments from {@code main} method.
275+
* @param args the command-line arguments (e.g. from {@code main} method).
183276
* @return the first {@link CliArgument} of the parsed arguments or {@code null} if for empty arguments.
184277
*/
185-
public static CliArgument of(boolean splitShortOpt, String... args) {
278+
public static CliArgument ofCompletion(String... args) {
279+
280+
return of(true, args);
281+
}
186282

187-
CliArgument first = CliArgument.END;
188-
CliArgument current = null;
189-
for (int argsIndex = 0; argsIndex < args.length; argsIndex++) {
283+
private static CliArgument of(boolean completion, String... args) {
284+
285+
CliArgument current = CliArgument.END;
286+
int last = args.length - 1;
287+
for (int argsIndex = last; argsIndex >= 0; argsIndex--) {
190288
String arg = args[argsIndex];
191-
CliArgument argument = new CliArgument(arg);
192-
if (current == null) {
193-
first = argument;
194-
current = argument;
195-
if (splitShortOpt) {
196-
CliArgument start = new CliArgument("");
197-
start.next = argument;
198-
first = start.getNext(true);
199-
current = first;
200-
while (!current.next.isEnd()) {
201-
current = current.next;
202-
}
203-
}
204-
} else {
205-
if (current.isEnd()) {
206-
// should never happen, but if a bug leads us here it is severe
207-
throw new IllegalStateException("Internal error!");
208-
}
209-
current.next = argument;
210-
current = argument;
289+
boolean completionArg = false;
290+
if (argsIndex == last) {
291+
completionArg = completion;
211292
}
293+
current = new CliArgument(arg, current, completionArg);
212294
}
213-
return first;
295+
return current.createStart();
214296
}
215297

216298
/**

0 commit comments

Comments
 (0)