diff --git a/build.gradle.kts b/build.gradle.kts index bd593c21..fba61275 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } group = "com.darvil" -version = "0.2.0" +version = "0.2.1" description = "Command line argument parser" dependencies { diff --git a/src/main/java/lanat/Argument.java b/src/main/java/lanat/Argument.java index 99a9e5af..9f157e5c 100644 --- a/src/main/java/lanat/Argument.java +++ b/src/main/java/lanat/Argument.java @@ -406,11 +406,12 @@ public void setRepresentationColor(@NotNull Color color) { /* no, | is not a typo. We don't want the OR operator to short-circuit, we want all of them to be evaluated * because the methods have side effects (they add errors to the parser) */ - TInner returnValue = (finalValue == null | !this.finishParsing$checkExclusivity() | !this.finishParsing$checkUsageCount()) + TInner returnValue = (finalValue == null | !this.finishParsing$checkGroupRestrictions() | !this.finishParsing$checkUsageCount()) ? defaultValue : finalValue; - if (this.parentGroup != null) this.parentGroup.setArgUsed(); + if (this.parentGroup != null && this.getUsageCount() >= 1) + this.parentGroup.setArgUsed(); // if the argument type has a value defined (even if it wasn't used), use that. Otherwise, use the default value return returnValue; @@ -442,20 +443,19 @@ public void setRepresentationColor(@NotNull Color color) { } /** - * Checks if the argument is part of an exclusive group, and if so, checks if there is any violation of exclusivity + * Checks if the argument is part of a restricted group, and if so, checks if there is any violation of restrictions * in the group hierarchy. - * - * @return {@code true} if there is no violation of exclusivity in the group hierarchy. + * @return {@code true} if there is no violation of restrictions in the group hierarchy. */ - private boolean finishParsing$checkExclusivity() { - // check if the parent group of this argument is exclusive, and if so, check if any other argument in it has been used + private boolean finishParsing$checkGroupRestrictions() { + // check if the parent group of this argument is restricted, and if so, check if any other argument in it has been used if (this.parentGroup == null || this.getUsageCount() == 0) return true; - ArgumentGroup exclusivityResult = this.parentGroup.checkExclusivity(null); - if (exclusivityResult == null) return true; + ArgumentGroup restrictionViolator = this.parentGroup.getRestrictionViolator(null); + if (restrictionViolator == null) return true; - this.parentCommand.getParser().addError(new ParseErrors.MultipleArgsInExclusiveGroupUsedError( - this.argType.getLastTokensIndicesPair(), exclusivityResult + this.parentCommand.getParser().addError(new ParseErrors.MultipleArgsInRestrictedGroupUsedError( + this.argType.getLastTokensIndicesPair(), restrictionViolator )); return false; } diff --git a/src/main/java/lanat/ArgumentGroup.java b/src/main/java/lanat/ArgumentGroup.java index 7faded90..8343600d 100644 --- a/src/main/java/lanat/ArgumentGroup.java +++ b/src/main/java/lanat/ArgumentGroup.java @@ -13,17 +13,17 @@ /** *

Argument Group

*

- * Represents a group of arguments. This is used to group arguments together, and to set exclusivity between them. - * When a group is exclusive, it means that only one argument in it can be used at a time. + * Represents a group of arguments. This is used to group arguments together, and to set a restriction between them. + * When a group is restricted, it means that only one argument in it can be used at a time. *

* Groups can also be used to simply indicate arguments that are related to each other, and to set a description * to this relation. This is useful for the help message representation. *

- * Groups can be nested, meaning that a group can contain other groups. This is useful for setting exclusivity between + * Groups can be nested, meaning that a group can contain other groups. This is useful for setting restrictions between * arguments that are in different groups. For example, given the following group tree: *

  *            +-----------------------+
- *            |  Group 1 (exclusive)  |
+ *            |  Group 1 (restricted)  |
  *            |-----------------------|
  *            | Argument 1            |
  *            +-----------------------+
@@ -31,7 +31,7 @@
  *          +---------------------------+
  *          |                           |
  *  +---------------+      +-------------------------+
- *  |    Group 2    |      |   Group 3 (exclusive)   |
+ *  |    Group 2    |      |   Group 3 (restricted)   |
  *  |---------------|      |-------------------------|
  *  | Argument 2.1  |      | Argument 3.1            |
  *  | Argument 2.2  |      | Argument 3.2            |
@@ -40,14 +40,14 @@
  * 
@@ -85,11 +85,11 @@ public class ArgumentGroup
 	 * them.
 	 */
 	private final @NotNull List<@NotNull ArgumentGroup> subGroups = new ArrayList<>();
-	private boolean isExclusive = false;
+	private boolean isRestricted = false;
 
 	/**
 	 * When set to {@code true}, indicates that one argument in this group has been used. This is used when later
-	 * checking for exclusivity in the groups tree at {@link ArgumentGroup#checkExclusivity(ArgumentGroup)}
+	 * checking for restrictions in the groups tree at {@link ArgumentGroup#getRestrictionViolator(ArgumentGroup)}
 	 */
 	private boolean argumentUsed = false;
 
@@ -184,42 +184,42 @@ public Command getParentCommand() {
 	}
 
 	/**
-	 * Sets this group to be exclusive, meaning that only one argument in it can be used at a time.
-	 * @see ArgumentGroup#isExclusive()
+	 * Sets this group to be restricted, meaning that only one argument in it can be used at a time.
+	 * @see ArgumentGroup#isRestricted()
 	 */
-	public void setExclusive(boolean isExclusive) {
-		this.isExclusive = isExclusive;
+	public void setRestricted(boolean isRestricted) {
+		this.isRestricted = isRestricted;
 	}
 
 	/**
-	 * Returns {@code true} if this group is exclusive.
-	 * @return {@code true} if this group is exclusive.
-	 * @see ArgumentGroup#setExclusive(boolean)
+	 * Returns {@code true} if this group is restricted.
+	 * @return {@code true} if this group is restricted.
+	 * @see ArgumentGroup#setRestricted(boolean)
 	 */
-	public boolean isExclusive() {
-		return this.isExclusive;
+	public boolean isRestricted() {
+		return this.isRestricted;
 	}
 
 	/**
-	 * Checks if there is any violation of exclusivity in this group's tree, from this group to the root. This is done
+	 * Checks if there is any violation of restrictions in this group's tree, from this group to the root. This is done
 	 * by checking if this or any of the group's siblings have been used (except for the childCallee, which is the group
 	 * that called this method). If none of them have been used, the parent group is checked, and so on.
 	 *
 	 * @param childCallee The group that called this method. This is used to avoid checking the group that called this
-	 * 	method, because it is the one that is being checked for exclusivity. This can be {@code null} if this is
+	 * 	method, because it is the one that is being checked for restriction. This can be {@code null} if this is
 	 * 	the first call to this method.
 	 * @return The group that caused the violation, or {@code null} if there is no violation.
 	 */
-	@Nullable ArgumentGroup checkExclusivity(@Nullable ArgumentGroup childCallee) {
+	@Nullable ArgumentGroup getRestrictionViolator(@Nullable ArgumentGroup childCallee) {
 		if (
-			this.isExclusive && (
+			this.isRestricted && (
 				this.argumentUsed || this.subGroups.stream().filter(g -> g != childCallee).anyMatch(g -> g.argumentUsed)
 			)
 		)
 			return this;
 
 		if (this.parentGroup != null)
-			return this.parentGroup.checkExclusivity(this);
+			return this.parentGroup.getRestrictionViolator(this);
 
 		return null;
 	}
@@ -234,7 +234,7 @@ public boolean isEmpty() {
 
 
 	/**
-	 * Marks that an argument in this group has been used. This is used to later check for exclusivity.
+	 * Marks that an argument in this group has been used. This is used to later check for restrictions.
 	 * This also marks the parent group as used, and so on until reaching the root of the groups tree, thus marking the
 	 * path of the used argument.
 	 */
diff --git a/src/main/java/lanat/helpRepresentation/ArgumentGroupRepr.java b/src/main/java/lanat/helpRepresentation/ArgumentGroupRepr.java
index 6d965afd..d25c8d3d 100644
--- a/src/main/java/lanat/helpRepresentation/ArgumentGroupRepr.java
+++ b/src/main/java/lanat/helpRepresentation/ArgumentGroupRepr.java
@@ -32,7 +32,7 @@ private ArgumentGroupRepr() {}
 			return null;
 
 		final var name = new TextFormatter(group.getName() + ':').addFormat(FormatOption.BOLD);
-		if (group.isExclusive())
+		if (group.isRestricted())
 			name.addFormat(FormatOption.UNDERLINE);
 
 		return '\n' + name.toString() + '\n' + HelpFormatter.indent(description, group);
@@ -62,7 +62,7 @@ private ArgumentGroupRepr() {}
 		if (description == null && argumentDescriptions.isEmpty())
 			return "";
 
-		if (group.isExclusive())
+		if (group.isRestricted())
 			name.addFormat(FormatOption.UNDERLINE);
 
 		if (description != null)
@@ -92,8 +92,8 @@ public static String getRepresentation(@NotNull ArgumentGroup group) {
 		// its empty, nothing to append
 		if (group.isEmpty()) return "";
 
-		// if this group isn't exclusive, we just want to append the arguments, basically
-		if (group.isExclusive())
+		// if this group isn't restricted, we just want to append the arguments, basically
+		if (group.isRestricted())
 			buff.append('(');
 
 		final var arguments = Argument.sortByPriority(group.getArguments());
@@ -103,7 +103,7 @@ public static String getRepresentation(@NotNull ArgumentGroup group) {
 			buff.append(ArgumentRepr.getRepresentation(arg));
 			if (i < arguments.size() - 1) {
 				buff.append(' ');
-				if (group.isExclusive())
+				if (group.isRestricted())
 					buff.append('|').append(' ');
 			}
 		}
@@ -112,7 +112,7 @@ public static String getRepresentation(@NotNull ArgumentGroup group) {
 
 		if (!arguments.isEmpty() && !groups.isEmpty()) {
 			buff.append(' ');
-			if (group.isExclusive())
+			if (group.isRestricted())
 				buff.append("| ");
 		}
 
@@ -121,12 +121,12 @@ public static String getRepresentation(@NotNull ArgumentGroup group) {
 			buff.append(ArgumentGroupRepr.getRepresentation(grp)); // append the group's representation recursively
 			if (i < groups.size() - 1) {
 				buff.append(' ');
-				if (grp.isExclusive())
+				if (grp.isRestricted())
 					buff.append('|').append(' ');
 			}
 		}
 
-		if (group.isExclusive())
+		if (group.isRestricted())
 			buff.append(')');
 
 		return buff.toString();
diff --git a/src/main/java/lanat/parsing/errors/ParseErrors.java b/src/main/java/lanat/parsing/errors/ParseErrors.java
index d93329e5..adfaa0e6 100644
--- a/src/main/java/lanat/parsing/errors/ParseErrors.java
+++ b/src/main/java/lanat/parsing/errors/ParseErrors.java
@@ -152,11 +152,11 @@ public void handle(@NotNull ErrorFormattingContext fmt, @NotNull ParseErrorConte
 	}
 
 	/**
-	 * Error that occurs when multiple arguments in an exclusive group are used.
+	 * Error that occurs when multiple arguments in a restricted group are used.
 	 * @param indicesPair The indices of the tokens that caused the error. (start, end)
-	 * @param group The exclusive group that contains the arguments.
+	 * @param group The restricted group that contains the arguments.
 	 */
-	public record MultipleArgsInExclusiveGroupUsedError(
+	public record MultipleArgsInRestrictedGroupUsedError(
 		@NotNull Pair indicesPair,
 		@NotNull ArgumentGroup group
 	) implements Error.ParseError
@@ -164,7 +164,7 @@ public record MultipleArgsInExclusiveGroupUsedError(
 		@Override
 		public void handle(@NotNull ErrorFormattingContext fmt, @NotNull ParseErrorContext ctx) {
 			fmt
-				.withContent("Multiple arguments in exclusive group '" + this.group.getName() + "' used.")
+				.withContent("Multiple arguments in restricted group '" + this.group.getName() + "' used.")
 				.highlight(this.indicesPair.first(), this.indicesPair.second(), false);
 		}
 	}
diff --git a/src/test/java/lanat/test/UnitTests.java b/src/test/java/lanat/test/UnitTests.java
index 0c1a1297..1da4470f 100644
--- a/src/test/java/lanat/test/UnitTests.java
+++ b/src/test/java/lanat/test/UnitTests.java
@@ -82,8 +82,8 @@ protected TestingParser setParser() {
 			this.addCommand(new Command("subCommand2") {{
 				this.setErrorCode(0b1000);
 
-				this.addGroup(new ArgumentGroup("exclusive-group") {{
-					this.setExclusive(true);
+				this.addGroup(new ArgumentGroup("restricted-group") {{
+					this.setRestricted(true);
 					this.addArgument(Argument.createOfBoolType("extra"));
 					this.addArgument(Argument.create(new IntegerArgumentType(), 'c').positional());
 				}});
diff --git a/src/test/java/lanat/test/exampleTests/CommandTemplateExample.java b/src/test/java/lanat/test/exampleTests/CommandTemplateExample.java
index 0e9b275e..980f6dc5 100644
--- a/src/test/java/lanat/test/exampleTests/CommandTemplateExample.java
+++ b/src/test/java/lanat/test/exampleTests/CommandTemplateExample.java
@@ -61,7 +61,7 @@ protected boolean checkFile(@NotNull File file) {
 	@InitDef
 	public static void afterInit(@NotNull Command cmd) {
 		cmd.addGroup(new ArgumentGroup("test-group") {{
-			this.setExclusive(true);
+			this.setRestricted(true);
 			this.addArgument(cmd.getArgument("string"));
 			this.addArgument(cmd.getArgument("number"));
 		}});
diff --git a/src/test/java/lanat/test/units/TestArgumentGroups.java b/src/test/java/lanat/test/units/TestArgumentGroups.java
index 5b9b8ad8..8002fbb4 100644
--- a/src/test/java/lanat/test/units/TestArgumentGroups.java
+++ b/src/test/java/lanat/test/units/TestArgumentGroups.java
@@ -15,7 +15,7 @@ protected TestingParser setParser() {
 		final var parser = super.setParser();
 
 		parser.addGroup(new ArgumentGroup("group") {{
-			this.setExclusive(true);
+			this.setRestricted(true);
 			this.addArgument(Argument.createOfBoolType("group-arg"));
 			this.addArgument(Argument.createOfBoolType("group-arg2"));
 		}});
@@ -24,8 +24,8 @@ protected TestingParser setParser() {
 	}
 
 	@Test
-	@DisplayName("Test exclusive group")
-	public void testExclusiveGroup() {
+	@DisplayName("Test restricted group")
+	public void testRestrictedGroup() {
 		var parsedArgs = this.parser.parseGetValues("--group-arg --group-arg2");
 		assertEquals(Boolean.TRUE, parsedArgs.get("group-arg").orElse(null));
 		assertEquals(Boolean.FALSE, parsedArgs.get("group-arg2").orElse(null)); // group-arg2 should not be present
diff --git a/src/test/java/lanat/test/units/TestTerminalOutput.java b/src/test/java/lanat/test/units/TestTerminalOutput.java
index e76e0af3..85289b8b 100644
--- a/src/test/java/lanat/test/units/TestTerminalOutput.java
+++ b/src/test/java/lanat/test/units/TestTerminalOutput.java
@@ -119,12 +119,12 @@ public void testIncorrectUsageCount() {
 	}
 
 	@Test
-	@DisplayName("Test group exclusivity error")
-	public void testGroupExclusivityError() {
+	@DisplayName("Test group restriction error")
+	public void testGroupRestrictionError() {
 		this.assertErrorOutput("foo subCommand2 --extra --c 5", """
 			ERROR
 			Testing foo subCommand2 --extra -> --c 5 <-
-			Multiple arguments in exclusive group 'exclusive-group' used.""");
+			Multiple arguments in restricted group 'restricted-group' used.""");
 	}
 
 	@Test