Mandatory arguments are displayed in [], optional in <>, option argumnets are supported as well for manage.py command (for PY-11855)

This commit is contained in:
Ilya.Kazakevich
2015-03-20 16:54:00 +03:00
parent 4fbb4f5dac
commit b3bb56b2cb
6 changed files with 64 additions and 10 deletions
@@ -88,6 +88,7 @@ public final class Option {
// TODO: USe "known arguments info" to prevent copy/paste
/**
* @return if option accepts argument -- pair of [argument_quantity, argument]. Null otherwise.
* Unlike position argument, option argument is <a href="https://docs.python.org/2/library/optparse.html#terminology">always mandatory</a>
*/
@Nullable
public Pair<Integer, Argument> getArgumentAndQuantity() {
@@ -42,6 +42,17 @@ import java.awt.*;
*/
final class MissingArgumentDisplayer extends JPanel implements Listener {
/**
* Braces for mandatory args are [] according to GNU/POSIX recommendations
*/
@NotNull
private static final Pair<String, String> MANDATORY_ARG_BRACES = Pair.create("[", "]");
/**
* Braces for optional args are &lt;&gt; according to GNU/POSIX recommendations
*/
@NotNull
private static final Pair<String, String> OPTIONAL_ARG_BRACES = Pair.create("<", ">");
/**
* Number of places after end of line before argument place
*/
@@ -134,7 +145,23 @@ final class MissingArgumentDisplayer extends JPanel implements Listener {
final boolean required = nextArg.first;
final String argumentText = nextArg.second.getHelpText();
g.setColor((required ? JBColor.red : JBColor.gray));
g.drawString((StringUtil.isEmpty(argumentText) ? PyBundle.message("commandLine.missingArgument.defaultName") : argumentText), x, y);
final String textToShow = StringUtil.isEmpty(argumentText) ? PyBundle.message("commandLine.missingArgument.defaultName") : argumentText;
g.drawString(wrapBracesIfNeeded(required, textToShow), x, y);
}
/**
* Adds appropriate braces to argument help text if needed
* @param required is argument required
* @param textToShow arg help text
* @return text to show
*/
@NotNull
private static String wrapBracesIfNeeded(final boolean required, @NotNull final String textToShow) {
if (textToShow.startsWith(MANDATORY_ARG_BRACES.first) || textToShow.startsWith(OPTIONAL_ARG_BRACES.first)) {
return textToShow;
}
final Pair<String, String> braces = (required ? MANDATORY_ARG_BRACES : OPTIONAL_ARG_BRACES);
return String.format("%s%s%s", braces.first, textToShow, braces.second);
}
@@ -225,6 +225,13 @@ final class ValidationResultImpl extends CommandLineVisitor implements Validatio
@Nullable
@Override
public Pair<Boolean, Argument> getNextArg() {
if (myCurrentOptionAndArgsLeft != null && myCurrentOptionAndArgsLeft.second > 0) { // Next arg is option arg
final Pair<Integer, Argument> argumentAndQuantity = myCurrentOptionAndArgsLeft.first.getArgumentAndQuantity();
if (argumentAndQuantity != null) {
// Option argument is always mandatory: https://docs.python.org/2/library/optparse.html#terminology
return Pair.create(true, argumentAndQuantity.second);
}
}
return myCommand.getArgumentsInfo().getArgument(myCurrentPositionArgument);
}
}
@@ -871,5 +871,5 @@ commandLine.inspection.badOption=Bad or unknown option. make sure this option re
commandLine.inspection.badArgument=Argument can't have this value. use autocompletion to check list of possible values.
commandLine.inspection.excessArgument=Excess argument or argument is not possible here
# What to display if argument is available here, but no name provided
commandLine.missingArgument.defaultName=[arguments]
commandLine.missingArgument.defaultName=arguments
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.Pair;
import com.jetbrains.commandInterface.command.Argument;
import com.jetbrains.commandInterface.gnuCommandLine.psi.CommandLineFile;
import com.jetbrains.python.fixtures.PyTestCase;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
@@ -33,13 +34,15 @@ public final class CommandLineArgsTest extends PyTestCase {
*/
public void testArgsRequired() throws Exception {
CommandTestTools.initFileType();
final CommandLineFile file = CommandTestTools.createFileByText(myFixture, "command");
final ValidationResult validationResult = file.getValidationResult();
assert validationResult != null : "validation failed";
final Pair<Boolean, Argument> arg = validationResult.getNextArg();
Assert.assertNotNull("No argument returned, but should", arg);
Assert.assertTrue("Required argument is not marked as required", arg.first);
Assert.assertEquals("Wrong argument text", "positional_argument", arg.second.getHelpText());
validateNextArgument("command", "positional_argument");
}
/**
* Ensures option argument is returned if exists
*/
public void testOptionArgsRequired() throws Exception {
CommandTestTools.initFileType();
validateNextArgument("command positional_argument --available-option", "option argument");
}
/**
@@ -52,4 +55,20 @@ public final class CommandLineArgsTest extends PyTestCase {
assert validationResult != null : "validation failed";
Assert.assertNull("Argument returned while should not", validationResult.getNextArg());
}
/**
* Runs commands and checks argument is required after it
* @param commandText command text to run
* @param expectedArgumentText expected next argument help text
*/
private void validateNextArgument(@NotNull final String commandText, @NotNull final String expectedArgumentText) {
final CommandLineFile file = CommandTestTools.createFileByText(myFixture, commandText);
final ValidationResult validationResult = file.getValidationResult();
assert validationResult != null : "validation failed";
final Pair<Boolean, Argument> arg = validationResult.getNextArg();
Assert.assertNotNull("No argument returned, but should", arg);
Assert.assertTrue("Required argument is not marked as required", arg.first);
Assert.assertEquals("Wrong argument text", expectedArgumentText, arg.second.getHelpText());
}
}
@@ -58,7 +58,7 @@ final class CommandTestTools {
final List<Option> options = new ArrayList<Option>();
options.add(new Option(Pair.create(1, new Argument(Collections.singletonList("available_argument"))), "",
options.add(new Option(Pair.create(1, new Argument("option argument", Collections.singletonList("available_argument"))), "",
Collections.<String>emptyList(),
Collections.singletonList("--available-option")));