From c66a378d4820af20e59361deff15c2e74d38e8f7 Mon Sep 17 00:00:00 2001 From: Felix Ding Date: Tue, 17 Sep 2024 13:27:26 -0700 Subject: [PATCH] Toggle suggestions (#13) * Enables users to toggle between suggestions * Disables suggestion toggling when user has typed ahead * Removes println for incrementing and decrementing * Fixes formatting * Makes adjustment for various checkstyle items --- plugin/plugin.xml | 30 +++++++++ .../AbstractQToggleSuggestionsHandler.java | 61 +++++++++++++++++++ .../QToggleSuggestionsBackwardHandler.java | 15 +++++ .../QToggleSuggestionsForwardHandler.java | 15 +++++ .../util/QInlineVerifyKeyListener.java | 3 +- .../amazonq/util/QInvocationSession.java | 24 ++++++++ .../amazonq/util/QSuggestionsContext.java | 11 ++++ 7 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQToggleSuggestionsHandler.java create mode 100644 plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsBackwardHandler.java create mode 100644 plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsForwardHandler.java diff --git a/plugin/plugin.xml b/plugin/plugin.xml index b70b918d..f5737278 100644 --- a/plugin/plugin.xml +++ b/plugin/plugin.xml @@ -97,6 +97,16 @@ name="Reject Suggestions" id="software.aws.toolkits.eclipse.amazonq.commands.rejectSuggestions"> + + + + @@ -112,6 +122,14 @@ class="software.aws.toolkits.eclipse.amazonq.handlers.QRejectSuggestionsHandler" commandId="software.aws.toolkits.eclipse.amazonq.commands.rejectSuggestions"> + + + + @@ -133,6 +151,18 @@ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="ESC"> + + + + diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQToggleSuggestionsHandler.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQToggleSuggestionsHandler.java new file mode 100644 index 00000000..6b85577f --- /dev/null +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/AbstractQToggleSuggestionsHandler.java @@ -0,0 +1,61 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +package software.aws.toolkits.eclipse.amazonq.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; + +import software.aws.toolkits.eclipse.amazonq.util.QInvocationSession; + +public abstract class AbstractQToggleSuggestionsHandler extends AbstractHandler { + public enum Direction { + FORWARD, BACKWARD + } + + private Direction direction = Direction.FORWARD; + + @Override + public final boolean isEnabled() { + QInvocationSession qInvocationSessionInstance = QInvocationSession.getInstance(); + return qInvocationSessionInstance != null && !qInvocationSessionInstance.hasBeenTypedahead() + && qInvocationSessionInstance.isPreviewingSuggestions(); + } + + /** + * Executes the command when the user triggers the handler. + *

+ * Subclasses overriding this method should ensure that the following conditions are met: + *

+ * + * + * @param event The execution event that triggered the handler. + * @return The result of the execution, or null if there is no result. + * + * @implSpec + * Implementations should call {@code super.execute(event)} at the end to delegate the actual movement. + */ + @Override + public Object execute(final ExecutionEvent event) { + QInvocationSession qInvocationSessionInstance = QInvocationSession.getInstance(); + + switch (direction) { + case FORWARD: + qInvocationSessionInstance.incrementCurentSuggestionIndex(); + break; + case BACKWARD: + qInvocationSessionInstance.decrementCurrentSuggestionIndex(); + break; + default: + qInvocationSessionInstance.incrementCurentSuggestionIndex(); + } + + return null; + } + + protected final void setCommandDirection(final Direction direction) { + this.direction = direction; + } +} diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsBackwardHandler.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsBackwardHandler.java new file mode 100644 index 00000000..a284c78b --- /dev/null +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsBackwardHandler.java @@ -0,0 +1,15 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +package software.aws.toolkits.eclipse.amazonq.handlers; + +import org.eclipse.core.commands.ExecutionEvent; + +public class QToggleSuggestionsBackwardHandler extends AbstractQToggleSuggestionsHandler { + // Actual command handler logic consolidated in parent class + @Override + public final Object execute(final ExecutionEvent event) { + super.setCommandDirection(Direction.BACKWARD); + + return super.execute(event); + } +} diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsForwardHandler.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsForwardHandler.java new file mode 100644 index 00000000..3a992205 --- /dev/null +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/handlers/QToggleSuggestionsForwardHandler.java @@ -0,0 +1,15 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +package software.aws.toolkits.eclipse.amazonq.handlers; + +import org.eclipse.core.commands.ExecutionEvent; + +public class QToggleSuggestionsForwardHandler extends AbstractQToggleSuggestionsHandler { + // Actual command handler logic consolidated in parent class + @Override + public final Object execute(final ExecutionEvent event) { + super.setCommandDirection(Direction.FORWARD); + + return super.execute(event); + } +} diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInlineVerifyKeyListener.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInlineVerifyKeyListener.java index 77e84779..5f5484e8 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInlineVerifyKeyListener.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInlineVerifyKeyListener.java @@ -46,6 +46,8 @@ public void verifyKey(final VerifyEvent event) { // Here we conduct typeahead logic String currentSuggestion = qInvocationSessionInstance.getCurrentSuggestion().trim(); int currentOffset = widget.getCaretOffset(); + qInvocationSessionInstance + .setHasBeenTypedahead(currentOffset - qInvocationSessionInstance.getInvocationOffset() > 0); IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode("org.eclipse.jdt.ui"); // This needs to be defaulted to true. This key is only present in the // preference store if it is set to false. @@ -162,7 +164,6 @@ public void verifyKey(final VerifyEvent event) { break; } } - leadingWhitespaceSkipped += newWs; qInvocationSessionInstance.setLeadingWhitespaceSkipped(leadingWhitespaceSkipped); } diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInvocationSession.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInvocationSession.java index 4270fdea..9de065f3 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInvocationSession.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QInvocationSession.java @@ -46,6 +46,7 @@ public final class QInvocationSession extends QResource { private Stack closingBrackets = new Stack<>(); private boolean isLastKeyNewLine = false; private int[] headOffsetAtLine = new int[500]; + private boolean hasBeenTypedahead = false; // Private constructor to prevent instantiation private QInvocationSession() { @@ -307,6 +308,28 @@ public String getCurrentSuggestion() { return details.get(index).getSuggestion(); } + public void decrementCurrentSuggestionIndex() { + if (suggestionsContext != null) { + suggestionsContext.decrementIndex(); + getViewer().getTextWidget().redraw(); + } + } + + public void incrementCurentSuggestionIndex() { + if (suggestionsContext != null) { + suggestionsContext.incrementIndex(); + getViewer().getTextWidget().redraw(); + } + } + + public void setHasBeenTypedahead(final boolean hasBeenTypedahead) { + this.hasBeenTypedahead = hasBeenTypedahead; + } + + public boolean hasBeenTypedahead() { + return hasBeenTypedahead; + } + // Additional methods for the session can be added here @Override public void dispose() { @@ -319,6 +342,7 @@ public void dispose() { leadingWhitespaceSkipped = 0; isLastKeyNewLine = false; caretMovementReason = CaretMovementReason.UNEXAMINED; + hasBeenTypedahead = false; QInvocationSession.getInstance().getViewer().getTextWidget().redraw(); widget.removePaintListener(paintListener); widget.removeCaretListener(caretListener); diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QSuggestionsContext.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QSuggestionsContext.java index fc4f0f6e..6b4e1527 100644 --- a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QSuggestionsContext.java +++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/QSuggestionsContext.java @@ -25,5 +25,16 @@ public final void setCurrentIndex(final int index) { this.currentIndex = index; } + public final void incrementIndex() { + currentIndex = (currentIndex + 1) % details.size(); + } + + public final void decrementIndex() { + if (currentIndex - 1 < 0) { + currentIndex = details.size() - 1; + } else { + currentIndex--; + } + } }