diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java index ebdf2ead..a15a7dbd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java @@ -67,8 +67,8 @@ public class InputView extends BoxView { String s = getInputText(); screen.writerBuilder().build().text(s, rect.x(), rect.y()); screen.setShowCursor(hasFocus()); - int sum = text.stream().limit(cursorIndex).mapToInt(text -> text.length()).sum(); - screen.setCursorPosition(new Position(rect.x() + sum, rect.y())); + int cPos = cursorPosition(); + screen.setCursorPosition(new Position(rect.x() + cPos, rect.y())); super.drawInternal(screen); } @@ -81,8 +81,12 @@ public class InputView extends BoxView { return text.stream().collect(Collectors.joining()); } + private int cursorPosition() { + return text.stream().limit(cursorIndex).mapToInt(text -> text.length()).sum(); + } + private void add(String data) { - text.add(data); + text.add(cursorIndex, data); moveCursor(1); } @@ -94,7 +98,9 @@ public class InputView extends BoxView { } private void delete() { - text.remove(cursorIndex); + if (cursorIndex < text.size()) { + text.remove(cursorIndex); + } } private void moveCursor(int index) { diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java index 8d61a44d..d156cffe 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java @@ -132,6 +132,10 @@ public class AbstractViewTests { return getField(object, field, String.class); } + protected static int getIntField(Object object, String field) { + return getField(object, field, int.class); + } + protected static Runnable getRunnableField(Object object, String field) { return getField(object, field, Runnable.class); } @@ -141,4 +145,13 @@ public class AbstractViewTests { return (T) ReflectionTestUtils.getField(object, field); } + protected static int callIntMethod(Object object, String method) { + return callMethod(int.class, object, method); + } + + @SuppressWarnings("unchecked") + protected static T callMethod(Class type, Object object, String method, Object... args) { + return (T) ReflectionTestUtils.invokeMethod(object, method, args); + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java index 4ad96695..97cdb99f 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java @@ -28,6 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat; class InputViewTests extends AbstractViewTests { private static final String CURSOR_INDEX_FIELD = "cursorIndex"; + private static final String CURSOR_POSITION_METHOD = "cursorPosition"; @Nested class Input { @@ -135,16 +136,49 @@ class InputViewTests extends AbstractViewTests { configure(view); } - int cursorIndex() { - return (Integer) ReflectionTestUtils.getField(view, CURSOR_INDEX_FIELD); - } - @Test void addEmojiAndBackspace() { handleKey(view, "😂"); - assertThat(cursorIndex()).isEqualTo(1); + assertThat(getIntField(view, CURSOR_INDEX_FIELD)).isEqualTo(1); handleKey(view, Key.Backspace); - assertThat(cursorIndex()).isEqualTo(0); + assertThat(getIntField(view, CURSOR_INDEX_FIELD)).isEqualTo(0); + } + + @Test + void deleteFromLastPosition() { + handleKey(view, Key.Delete); + assertThat(getIntField(view, CURSOR_INDEX_FIELD)).isEqualTo(0); + handleKey(view, Key.a); + assertThat(getIntField(view, CURSOR_INDEX_FIELD)).isEqualTo(1); + } + + } + + @Nested + class MoveAndMods { + + InputView view; + + @BeforeEach + void setup() { + view = new InputView(); + configure(view); + } + + @Test + void shouldAddToCursorPosition() { + assertThat(callIntMethod(view, CURSOR_POSITION_METHOD)).isEqualTo(0); + handleKey(view, Key.a); + assertThat(getIntField(view, CURSOR_INDEX_FIELD)).isEqualTo(1); + assertThat(view.getInputText()).isEqualTo("a"); + assertThat(callIntMethod(view, CURSOR_POSITION_METHOD)).isEqualTo(1); + + handleKey(view, Key.CursorLeft); + assertThat(getIntField(view, CURSOR_INDEX_FIELD)).isEqualTo(0); + + handleKey(view, Key.b); + assertThat(getIntField(view, CURSOR_INDEX_FIELD)).isEqualTo(1); + assertThat(view.getInputText()).isEqualTo("ba"); } }