@@ -24,6 +24,7 @@ const {
2424 StringPrototypeCodePointAt,
2525 StringPrototypeEndsWith,
2626 StringPrototypeIncludes,
27+ StringPrototypeLastIndexOf,
2728 StringPrototypeRepeat,
2829 StringPrototypeReplaceAll,
2930 StringPrototypeSlice,
@@ -1091,21 +1092,20 @@ class Interface extends InterfaceConstructor {
10911092 this [ kRefreshLine ] ( ) ;
10921093 }
10931094
1094- [ kMultilineMove ] ( direction , splitLines , { rows , cols } ) {
1095- const curr = splitLines [ rows ] ;
1095+ [ kMultilineMove ] ( direction , splitLines , { logicalRows , logicalCols } ) {
1096+ const curr = splitLines [ logicalRows ] ;
10961097 const down = direction === 1 ;
1097- const adj = splitLines [ rows + direction ] ;
1098- const promptLen = kMultilinePrompt . description . length ;
1098+ const adj = splitLines [ logicalRows + direction ] ;
10991099 let amountToMove ;
1100- // Clamp distance to end of current + prompt + next/prev line + newline
1100+ // Clamp distance to end of current + next/prev line + newline
11011101 const clamp = down ?
1102- curr . length - cols + promptLen + adj . length + 1 :
1103- - cols + 1 ;
1104- const shouldClamp = cols > adj . length + 1 ;
1102+ curr . length - logicalCols + adj . length + 1 :
1103+ - logicalCols - 1 ;
1104+ const shouldClamp = logicalCols > adj . length ;
11051105
11061106 if ( shouldClamp ) {
11071107 if ( this [ kPreviousCursorCols ] === - 1 ) {
1108- this [ kPreviousCursorCols ] = cols ;
1108+ this [ kPreviousCursorCols ] = logicalCols ;
11091109 }
11101110 amountToMove = clamp ;
11111111 } else {
@@ -1116,7 +1116,7 @@ class Interface extends InterfaceConstructor {
11161116 }
11171117 if ( this [ kPreviousCursorCols ] !== - 1 ) {
11181118 if ( this [ kPreviousCursorCols ] <= adj . length ) {
1119- amountToMove += this [ kPreviousCursorCols ] - cols ;
1119+ amountToMove += this [ kPreviousCursorCols ] - logicalCols ;
11201120 this [ kPreviousCursorCols ] = - 1 ;
11211121 } else {
11221122 amountToMove = clamp ;
@@ -1128,10 +1128,10 @@ class Interface extends InterfaceConstructor {
11281128 }
11291129
11301130 [ kMoveDownOrHistoryNext ] ( ) {
1131- const cursorPos = this . getCursorPos ( ) ;
1131+ const logicalCursorPos = this . getLogicalCursorPos ( ) ;
11321132 const splitLines = StringPrototypeSplit ( this . line , '\n' ) ;
1133- if ( this [ kIsMultiline ] && cursorPos . rows < splitLines . length - 1 ) {
1134- this [ kMultilineMove ] ( 1 , splitLines , cursorPos ) ;
1133+ if ( this [ kIsMultiline ] && logicalCursorPos . logicalRows < splitLines . length - 1 ) {
1134+ this [ kMultilineMove ] ( 1 , splitLines , logicalCursorPos ) ;
11351135 return ;
11361136 }
11371137 this [ kPreviousCursorCols ] = - 1 ;
@@ -1155,10 +1155,10 @@ class Interface extends InterfaceConstructor {
11551155 }
11561156
11571157 [ kMoveUpOrHistoryPrev ] ( ) {
1158- const cursorPos = this . getCursorPos ( ) ;
1159- if ( this [ kIsMultiline ] && cursorPos . rows > 0 ) {
1158+ const logicalCursorPos = this . getLogicalCursorPos ( ) ;
1159+ if ( this [ kIsMultiline ] && logicalCursorPos . logicalRows > 0 ) {
11601160 const splitLines = StringPrototypeSplit ( this . line , '\n' ) ;
1161- this [ kMultilineMove ] ( - 1 , splitLines , cursorPos ) ;
1161+ this [ kMultilineMove ] ( - 1 , splitLines , logicalCursorPos ) ;
11621162 return ;
11631163 }
11641164 this [ kPreviousCursorCols ] = - 1 ;
@@ -1226,6 +1226,22 @@ class Interface extends InterfaceConstructor {
12261226 return this [ kGetDisplayPos ] ( strBeforeCursor ) ;
12271227 }
12281228
1229+ /**
1230+ * Returns the logical position of the cursor within the input string
1231+ * excluding prompt and terminal formatting.
1232+ * @returns {{
1233+ * logicalCols: number;
1234+ * logicalRows: number;
1235+ * }}
1236+ */
1237+ getLogicalCursorPos ( ) {
1238+ const logicalCols = this . cursor - ( StringPrototypeLastIndexOf ( this . line , '\n' , this . cursor - 1 ) + 1 ) ;
1239+ const strlineBeforeCursor = StringPrototypeSlice ( this . line , 0 , this . cursor ) ;
1240+ const logicalRows = StringPrototypeSplit ( strlineBeforeCursor , '\n' ) . length - 1
1241+
1242+ return { logicalCols, logicalRows } ;
1243+ }
1244+
12291245 // This function moves cursor dx places to the right
12301246 // (-dx for left) and refreshes the line if it is needed.
12311247 [ kMoveCursor ] ( dx ) {
0 commit comments