• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 9907372175

12 Jul 2024 11:49AM UTC coverage: 61.142% (-0.02%) from 61.162%
9907372175

push

github

hohwille
fixed tests

1997 of 3595 branches covered (55.55%)

Branch coverage included in aggregate %.

5296 of 8333 relevant lines covered (63.55%)

2.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.13
cli/src/main/java/com/devonfw/tools/ide/commandlet/ShellCommandlet.java
1
package com.devonfw.tools.ide.commandlet;
2

3
import java.io.IOException;
4
import java.util.Iterator;
5

6
import org.fusesource.jansi.AnsiConsole;
7
import org.jline.reader.EndOfFileException;
8
import org.jline.reader.LineReader;
9
import org.jline.reader.LineReaderBuilder;
10
import org.jline.reader.MaskingCallback;
11
import org.jline.reader.Parser;
12
import org.jline.reader.UserInterruptException;
13
import org.jline.reader.impl.DefaultParser;
14
import org.jline.terminal.Terminal;
15
import org.jline.terminal.TerminalBuilder;
16
import org.jline.widget.AutosuggestionWidgets;
17

18
import com.devonfw.tools.ide.cli.CliArgument;
19
import com.devonfw.tools.ide.cli.CliArguments;
20
import com.devonfw.tools.ide.completion.IdeCompleter;
21
import com.devonfw.tools.ide.context.AbstractIdeContext;
22
import com.devonfw.tools.ide.context.IdeContext;
23
import com.devonfw.tools.ide.property.BooleanProperty;
24
import com.devonfw.tools.ide.property.KeywordProperty;
25
import com.devonfw.tools.ide.property.Property;
26

27
/**
28
 * {@link Commandlet} for internal interactive shell with build-in auto-completion and help.
29
 */
30
public final class ShellCommandlet extends Commandlet {
31

32
  private static final int AUTOCOMPLETER_MAX_RESULTS = 50;
33

34
  private static final int RC_EXIT = 987654321;
35

36
  /**
37
   * The constructor.
38
   *
39
   * @param context the {@link IdeContext}.
40
   */
41
  public ShellCommandlet(IdeContext context) {
42

43
    super(context);
3✔
44
    addKeyword(getName());
4✔
45
  }
1✔
46

47
  @Override
48
  public String getName() {
49

50
    return "shell";
2✔
51
  }
52

53
  @Override
54
  public boolean isIdeHomeRequired() {
55

56
    return false;
×
57
  }
58

59
  @Override
60
  public void run() {
61

62
    try {
63
      // TODO: add BuiltIns here, see: https://github.com/devonfw/IDEasy/issues/168
64

65
      Parser parser = new DefaultParser();
×
66
      try (Terminal terminal = TerminalBuilder.builder().build()) {
×
67

68
        // initialize our own completer here
69
        IdeCompleter completer = new IdeCompleter((AbstractIdeContext) this.context);
×
70

71
        LineReader reader = LineReaderBuilder.builder().terminal(terminal).completer(completer).parser(parser)
×
72
            .variable(LineReader.LIST_MAX, AUTOCOMPLETER_MAX_RESULTS).build();
×
73

74
        // Create autosuggestion widgets
75
        AutosuggestionWidgets autosuggestionWidgets = new AutosuggestionWidgets(reader);
×
76
        // Enable autosuggestions
77
        autosuggestionWidgets.enable();
×
78

79
        // TODO: implement TailTipWidgets, see: https://github.com/devonfw/IDEasy/issues/169
80

81
        String prompt = "ide> ";
×
82
        String rightPrompt = null;
×
83
        String line;
84

85
        AnsiConsole.systemInstall();
×
86
        while (true) {
87
          try {
88
            line = reader.readLine(prompt, rightPrompt, (MaskingCallback) null, null);
×
89
            reader.getHistory().add(line);
×
90
            int rc = runCommand(line);
×
91
            if (rc == RC_EXIT) {
×
92
              return;
×
93
            }
94
          } catch (UserInterruptException e) {
×
95
            // Ignore CTRL+C
96
            return;
×
97
          } catch (EndOfFileException e) {
×
98
            // CTRL+D
99
            return;
×
100
          } finally {
101
            AnsiConsole.systemUninstall();
×
102
          }
×
103
        }
104

105
      } catch (IOException e) {
×
106
        throw new RuntimeException(e);
×
107
      }
108
    } catch (Exception e) {
×
109
      throw new RuntimeException("Unexpected error during interactive auto-completion", e);
×
110
    }
111
  }
112

113
  /**
114
   * Converts String of arguments to array and runs the command
115
   *
116
   * @param args String of arguments
117
   * @return status code
118
   */
119
  private int runCommand(String args) {
120

121
    if ("exit".equals(args) || "quit".equals(args)) {
×
122
      return RC_EXIT;
×
123
    }
124
    String[] arguments = args.split(" ", 0);
×
125
    CliArguments cliArgs = new CliArguments(arguments);
×
126
    cliArgs.next();
×
127
    return ((AbstractIdeContext) this.context).run(cliArgs);
×
128
  }
129

130
  /**
131
   * @param argument the current {@link CliArgument} (position) to match.
132
   * @param commandlet the potential {@link Commandlet} to match.
133
   * @return {@code true} if the given {@link Commandlet} matches to the given {@link CliArgument}(s) and those have been applied (set in the {@link Commandlet}
134
   * and {@link Commandlet#validate() validated}), {@code false} otherwise (the {@link Commandlet} did not match and we have to try a different candidate).
135
   */
136
  private boolean apply(CliArgument argument, Commandlet commandlet) {
137

138
    this.context.trace("Trying to match arguments to commandlet {}", commandlet.getName());
×
139
    CliArgument currentArgument = argument;
×
140
    Iterator<Property<?>> valueIterator = commandlet.getValues().iterator();
×
141
    Property<?> currentProperty = null;
×
142
    boolean endOpts = false;
×
143
    while (!currentArgument.isEnd()) {
×
144
      if (currentArgument.isEndOptions()) {
×
145
        endOpts = true;
×
146
      } else {
147
        String arg = currentArgument.get();
×
148
        this.context.trace("Trying to match argument '{}'", currentArgument);
×
149
        if ((currentProperty != null) && (currentProperty.isExpectValue())) {
×
150
          currentProperty.setValueAsString(arg, this.context);
×
151
          if (!currentProperty.isMultiValued()) {
×
152
            currentProperty = null;
×
153
          }
154
        } else {
155
          Property<?> property = null;
×
156
          if (!endOpts) {
×
157
            property = commandlet.getOption(currentArgument.getKey());
×
158
          }
159
          if (property == null) {
×
160
            if (!valueIterator.hasNext()) {
×
161
              this.context.trace("No option or next value found");
×
162
              return false;
×
163
            }
164
            currentProperty = valueIterator.next();
×
165
            this.context.trace("Next value candidate is {}", currentProperty);
×
166
            if (currentProperty instanceof KeywordProperty keyword) {
×
167
              if (keyword.matches(arg)) {
×
168
                keyword.setValue(Boolean.TRUE);
×
169
                this.context.trace("Keyword matched");
×
170
              } else {
171
                this.context.trace("Missing keyword");
×
172
                return false;
×
173
              }
174
            } else {
175
              boolean success = currentProperty.assignValueAsString(arg, this.context, commandlet);
×
176
              if (!success && currentProperty.isRequired()) {
×
177
                return false;
×
178
              }
179
            }
180
            if ((currentProperty != null) && !currentProperty.isMultiValued()) {
×
181
              currentProperty = null;
×
182
            }
183
          } else {
184
            this.context.trace("Found option by name");
×
185
            String value = currentArgument.getValue();
×
186
            if (value != null) {
×
187
              property.setValueAsString(value, this.context);
×
188
            } else if (property instanceof BooleanProperty) {
×
189
              ((BooleanProperty) property).setValue(Boolean.TRUE);
×
190
            } else {
191
              currentProperty = property;
×
192
              if (property.isEndOptions()) {
×
193
                endOpts = true;
×
194
              }
195
              throw new UnsupportedOperationException("not implemented");
×
196
            }
197
          }
198
        }
199
      }
200
      currentArgument = currentArgument.getNext(!endOpts);
×
201
    }
202
    return commandlet.validate();
×
203
  }
204
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc