Skip to content

Commit

Permalink
FORGE-764: multi-select ShellPrompt API
Browse files Browse the repository at this point in the history
  • Loading branch information
mbenson authored and gastaldi committed Jan 23, 2013
1 parent eec7047 commit 1109de2
Show file tree
Hide file tree
Showing 6 changed files with 672 additions and 3 deletions.
75 changes: 74 additions & 1 deletion shell-api/src/main/java/org/jboss/forge/shell/ShellPrompt.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
* Copyright 2012-2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
Expand All @@ -9,6 +9,7 @@

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jboss.forge.resources.FileResource;
import org.jboss.forge.shell.completer.CommandCompleter;
Expand Down Expand Up @@ -219,4 +220,76 @@ public interface ShellPrompt
*/
String promptSecret(String string, String defaultIfEmpty);

/**
* Prompt for user input, first printing the given message, followed by a keyed list of options. Loop until the user
* has selected all available options or signifies he is finished by entering an empty response, then return a set
* of all values selected.
*
* @param <T> The type of the objects to be selected
* @param message The prompt message to display
* @param options The set of selection options
* @return the selected options
*/
<T> Set<T> promptMultiSelect(String message, Set<T> options);

/**
* Prompt for user input, first printing the given message, followed by a keyed list of options, including a
* "wildcard" option to select all. Loop until the user has selected all available options or signifies he is
* finished by entering an empty response, then return a set of all values selected.
*
* @param <T> The type of the objects to be selected
* @param wildcard the shortcut response signifying "select all options", not {@code null}
* @param message The prompt message to display
* @param options The set of selection options
* @return the selected options
*/
<T> Set<T> promptMultiSelectWithWildcard(String wildcard, String message, Set<T> options);

/**
* Prompt for user input, first printing the given message, followed by a keyed list of options. Loop until the user
* signifies he is finished by entering an empty response, then return a set of all values selected.
*
* @param <T> The type of the objects to be selected
* @param message The prompt message to display
* @param options The array of unique selection options
* @return the selected options
*/
<T> Set<T> promptMultiSelect(String message, T... options);

/**
* Prompt for user input, first printing the given message, followed by a keyed list of options, including a
* "wildcard" option to select all. Loop until the user has selected all available options or signifies he is
* finished by entering an empty response, then return a set of all values selected.
*
* @param <T> The type of the objects to be selected
* @param wildcard the shortcut response signifying "select all options", not {@code null}
* @param message The prompt message to display
* @param options The array of unique selection options
* @return the selected options
*/
<T> Set<T> promptMultiSelectWithWildcard(String wildcard, String message, T... options);

/**
* Prompt for user input, first printing the given message, followed by a keyed list of options. Loop until the user
* signifies he is finished by entering an empty response, then return a set of all values selected.
*
* @param <T> The type of the objects to be selected
* @param message The prompt message to display
* @param options The map of selection options
* @return the selected options
*/
<T> Set<T> promptMultiSelect(String message, Map<String, T> options);

/**
* Prompt for user input, first printing the given message, followed by a keyed list of options, including a
* "wildcard" option to select all. Loop until the user has selected all available options or signifies he is
* finished by entering an empty response, then return a set of all values selected.
*
* @param <T> The type of the objects to be selected
* @param wildcard the shortcut response signifying "select all options", not {@code null}
* @param message The prompt message to display
* @param options The map of selection options
* @return the selected options
*/
<T> Set<T> promptMultiSelectWithWildcard(String wildcard, String message, Map<String, T> options);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.TreeSet;
Expand All @@ -25,8 +28,10 @@
import org.jboss.forge.shell.completer.CommandCompleter;
import org.jboss.forge.shell.completer.CompleterAdaptor;
import org.jboss.forge.shell.completer.EnumCompleter;
import org.jboss.forge.shell.console.jline.console.completer.AggregateCompleter;
import org.jboss.forge.shell.console.jline.console.completer.Completer;
import org.jboss.forge.shell.console.jline.console.completer.FileNameCompleter;
import org.jboss.forge.shell.console.jline.console.completer.StringsCompleter;
import org.jboss.forge.shell.util.BeanManagerUtils;
import org.jboss.forge.shell.util.Enums;
import org.jboss.forge.shell.util.Files;
Expand Down Expand Up @@ -624,4 +629,44 @@ public String promptSecret(final String message, final String defaultIfEmpty)
return secret;
}

}
@Override
public <T> Set<T> promptMultiSelect(String message, Set<T> options)
{
return promptMultiSelectWithWildcard(null, message, options);
}

@Override
public <T> Set<T> promptMultiSelectWithWildcard(String wildcard, String message, Set<T> options)
{
final Map<String, T> optionMap = new LinkedHashMap<String, T>();
for (T t : options)
{
if (t == null)
{
throw new IllegalArgumentException("null values not allowed");
}
// use #name() for enums, which may not be the same as #toString()
optionMap.put(t.getClass().isEnum() ? ((Enum<?>) t).name() : t.toString(), t);
}
return promptMultiSelectWithWildcard(wildcard, message, optionMap);
}

@Override
public <T> Set<T> promptMultiSelect(String message, Map<String, T> options)
{
return promptMultiSelectWithWildcard(null, message, options);
}

@Override
public <T> Set<T> promptMultiSelect(String message, T... options)
{
return promptMultiSelect(message, new LinkedHashSet<T>(Arrays.asList(options)));
}

@Override
public <T> Set<T> promptMultiSelectWithWildcard(String wildcard, String message, T... options)
{
return promptMultiSelectWithWildcard(wildcard, message, new LinkedHashSet<T>(Arrays.asList(options)));
}

}
72 changes: 71 additions & 1 deletion shell/src/main/java/org/jboss/forge/shell/ShellImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
* Copyright 2012-2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
Expand All @@ -18,7 +18,12 @@
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

import javax.enterprise.context.ApplicationScoped;
Expand Down Expand Up @@ -1376,6 +1381,71 @@ public String promptSecret(String message)
}
}

@Override
public <T> Set<T> promptMultiSelectWithWildcard(String wildcard, String message, Map<String, T> options)
{
if ((options == null) || options.isEmpty())
{
throw new IllegalArgumentException(
"promptMultiSelect() Cannot ask user to select from a list of nothing. Ensure you have values in your options list.");
}
if (options.containsKey(""))
{
throw new IllegalArgumentException("empty labels not allowed");
}
if (options.containsKey(wildcard))
{
throw new IllegalArgumentException("wildcard label duplicated among option labels");
}
if (wildcard != null && wildcard.trim().isEmpty())
{
throw new IllegalArgumentException("blank/empty wildcard labels not allowed");
}
final Map<String, String> fullOptions = new LinkedHashMap<String, String>();
for (String key : options.keySet())
{
fullOptions.put(key, key);
}
if (wildcard != null)
{
fullOptions.put(wildcard, wildcard);
}
fullOptions.put("", null);

println(message);

final Set<T> result = new LinkedHashSet<T>();

StringBuilder prompt = new StringBuilder("select (");
if (wildcard != null)
{
prompt.append('"').append(wildcard).append('"').append(" = all values; ");
}
prompt.append("empty = done)");

while (true)
{
final String choice = promptChoice(prompt.toString(), fullOptions);
if (choice == null)
{
break;
}
if (choice.equals(wildcard))
{
result.addAll(options.values());
break;
}
result.add(options.get(choice));
fullOptions.remove(choice);
if (result.size() == options.size())
{
break;
}
}

return Collections.unmodifiableSet(result);
}

@Override
protected PromptTypeConverter getPromptTypeConverter()
{
Expand Down

0 comments on commit 1109de2

Please sign in to comment.