@@ -24,9 +24,11 @@ const {
2424 SafeStringIterator,
2525 StringPrototypeCodePointAt,
2626 StringPrototypeEndsWith,
27+ StringPrototypeIndexOf,
2728 StringPrototypeRepeat,
2829 StringPrototypeReplaceAll,
2930 StringPrototypeSlice,
31+ StringPrototypeSplit,
3032 StringPrototypeStartsWith,
3133 StringPrototypeTrim,
3234 Symbol,
@@ -100,7 +102,9 @@ const kDeleteWordLeft = Symbol('_deleteWordLeft');
100102const kDeleteWordRight = Symbol ( '_deleteWordRight' ) ;
101103const kGetDisplayPos = Symbol ( '_getDisplayPos' ) ;
102104const kHistoryNext = Symbol ( '_historyNext' ) ;
105+ const kMoveDownOrHistoryNext = Symbol ( '_moveDownOrHistoryNext' ) ;
103106const kHistoryPrev = Symbol ( '_historyPrev' ) ;
107+ const kMoveUpOrHistoryPrev = Symbol ( '_moveUpOrHistoryPrev' ) ;
104108const kInsertString = Symbol ( '_insertString' ) ;
105109const kLine = Symbol ( '_line' ) ;
106110const kLine_buffer = Symbol ( '_line_buffer' ) ;
@@ -929,6 +933,26 @@ class Interface extends InterfaceConstructor {
929933 this [ kRefreshLine ] ( ) ;
930934 }
931935
936+ [ kMoveDownOrHistoryNext ] ( ) {
937+ const { cols, rows } = this . getCursorPos ( ) ;
938+ const splitLine = StringPrototypeSplit ( this . line , '\n' ) ;
939+ // Go to the next history only if the cursor is in the first line of the multiline input.
940+ // Otherwise treat the "arrow down" as a movement to the next row.
941+ if ( splitLine . length > 1 && rows < splitLine . length - 1 ) {
942+ const currentLine = splitLine [ rows ] ;
943+ const nextLine = splitLine [ rows + 1 ] ;
944+ const amountToMove = ( cols > nextLine . length ) ?
945+ + cols + nextLine . length - 1 :
946+ + currentLine . length + 1 ;
947+ // Go to the same position on the next line, or the end of the next line
948+ // If the current position does not exist in the next line.
949+ this [ kMoveCursor ] ( amountToMove ) ;
950+ return ;
951+ }
952+
953+ this [ kHistoryNext ] ( ) ;
954+ }
955+
932956 // TODO(BridgeAR): Add underscores to the search part and a red background in
933957 // case no match is found. This should only be the visual part and not the
934958 // actual line content!
@@ -939,7 +963,9 @@ class Interface extends InterfaceConstructor {
939963 [ kHistoryNext ] ( ) {
940964 if ( this . historyIndex >= 0 ) {
941965 this [ kBeforeEdit ] ( this . line , this . cursor ) ;
942- const search = this [ kSubstringSearch ] || '' ;
966+ const isLineMultiline = StringPrototypeIndexOf ( this . line , '\n' ) !== - 1 ;
967+
968+ const search = isLineMultiline ? '' : this [ kSubstringSearch ] || '' ;
943969 let index = this . historyIndex - 1 ;
944970 while (
945971 index >= 0 &&
@@ -959,10 +985,31 @@ class Interface extends InterfaceConstructor {
959985 }
960986 }
961987
988+ [ kMoveUpOrHistoryPrev ] ( ) {
989+ const { cols, rows } = this . getCursorPos ( ) ;
990+ const splitLine = StringPrototypeSplit ( this . line , '\n' ) ;
991+ // Go to the previous history only if the cursor is in the first line of the multiline input.
992+ // Otherwise treat the "arrow up" as a movement to the previous row.
993+ if ( splitLine . length > 1 && rows > 0 ) {
994+ const previousLine = splitLine [ rows - 1 ] ;
995+ const amountToMove = ( cols > previousLine . length ) ?
996+ - cols - 1 :
997+ - previousLine . length - 1 ;
998+ // Go to the same position on the previous line, or the end of the previous line
999+ // If the current position does not exist in the previous line.
1000+ this [ kMoveCursor ] ( amountToMove ) ;
1001+ return ;
1002+ }
1003+
1004+ this [ kHistoryPrev ] ( ) ;
1005+ }
1006+
9621007 [ kHistoryPrev ] ( ) {
9631008 if ( this . historyIndex < this . history . length && this . history . length ) {
9641009 this [ kBeforeEdit ] ( this . line , this . cursor ) ;
965- const search = this [ kSubstringSearch ] || '' ;
1010+ const isLineMultiline = StringPrototypeIndexOf ( this . line , '\n' ) !== - 1 ;
1011+
1012+ const search = isLineMultiline ? '' : this [ kSubstringSearch ] || '' ;
9661013 let index = this . historyIndex + 1 ;
9671014 while (
9681015 index < this . history . length &&
@@ -1309,11 +1356,11 @@ class Interface extends InterfaceConstructor {
13091356 break ;
13101357
13111358 case 'up' :
1312- this [ kHistoryPrev ] ( ) ;
1359+ this [ kMoveUpOrHistoryPrev ] ( ) ;
13131360 break ;
13141361
13151362 case 'down' :
1316- this [ kHistoryNext ] ( ) ;
1363+ this [ kMoveDownOrHistoryNext ] ( ) ;
13171364 break ;
13181365
13191366 case 'tab' :
0 commit comments