From 48e5de4506b52b20f336890676c7222fbf96f7ad Mon Sep 17 00:00:00 2001 From: Vladimir Rudnyh Date: Tue, 22 Dec 2015 07:25:19 +0300 Subject: [PATCH 1/3] Preserve multiline prompt on 'clear buffer' gnachman/iterm2#1330 --- iTerm2XCTests/VT100GridTest.m | 16 ++++++++-------- sources/VT100Grid.h | 2 +- sources/VT100Grid.m | 8 ++++---- sources/VT100Screen.m | 13 +++++++++++-- sources/iTermAdvancedSettingsModel.h | 1 + sources/iTermAdvancedSettingsModel.m | 1 + 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/iTerm2XCTests/VT100GridTest.m b/iTerm2XCTests/VT100GridTest.m index 327b376d90..36457246bc 100644 --- a/iTerm2XCTests/VT100GridTest.m +++ b/iTerm2XCTests/VT100GridTest.m @@ -1805,7 +1805,7 @@ - (void)testResetWithLineBufferLeavingBehindZero { [lineBuffer setMaxLines:1]; int dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:NO - preserveCursorLine:NO]; + preservePromptLines:0]; XCTAssert(dropped == 2); XCTAssert([[grid compactLineDump] isEqualToString: @"....\n" @@ -1826,7 +1826,7 @@ - (void)testResetWithLineBufferLeavingBehindZero { [lineBuffer setMaxLines:1]; dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:YES - preserveCursorLine:NO]; + preservePromptLines:0]; XCTAssert(dropped == 0); XCTAssert([[grid compactLineDump] isEqualToString: @"....\n" @@ -1841,7 +1841,7 @@ - (void)testResetWithLineBufferLeavingBehindZero { [lineBuffer setMaxLines:1]; dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:YES - preserveCursorLine:NO]; + preservePromptLines:0]; XCTAssert(dropped == 0); XCTAssert([[grid compactLineDump] isEqualToString: @"..\n" @@ -1861,7 +1861,7 @@ - (void)testResetWithLineBufferLeavingBehindCursorLine { [lineBuffer setMaxLines:1]; int dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:NO - preserveCursorLine:YES]; + preservePromptLines:1]; XCTAssert(dropped == 2); XCTAssert([[grid compactLineDump] isEqualToString: @"....\n" @@ -1887,7 +1887,7 @@ - (void)testResetWithLineBufferLeavingBehindCursorLine { [lineBuffer setMaxLines:1]; dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:NO - preserveCursorLine:YES]; + preservePromptLines:1]; XCTAssert(dropped == 1); XCTAssert([[grid compactLineDump] isEqualToString: @"efgh\n" @@ -1913,7 +1913,7 @@ - (void)testResetWithLineBufferLeavingBehindCursorLine { [lineBuffer setMaxLines:1]; dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:NO - preserveCursorLine:YES]; + preservePromptLines:1]; XCTAssert(dropped == 0); XCTAssert([[grid compactLineDump] isEqualToString: @"abcd\n" @@ -1935,7 +1935,7 @@ - (void)testResetWithLineBufferLeavingBehindCursorLine { [lineBuffer setMaxLines:1]; dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:YES - preserveCursorLine:YES]; + preservePromptLines:1]; XCTAssert(dropped == 0); XCTAssert([[grid compactLineDump] isEqualToString: @"....\n" @@ -1950,7 +1950,7 @@ - (void)testResetWithLineBufferLeavingBehindCursorLine { [lineBuffer setMaxLines:1]; dropped = [grid resetWithLineBuffer:lineBuffer unlimitedScrollback:YES - preserveCursorLine:YES]; + preservePromptLines:1]; XCTAssert(dropped == 0); XCTAssert([[grid compactLineDump] isEqualToString: @"..\n" diff --git a/sources/VT100Grid.h b/sources/VT100Grid.h index a8ef6134be..fd4732015c 100644 --- a/sources/VT100Grid.h +++ b/sources/VT100Grid.h @@ -128,7 +128,7 @@ // for |leave|. - (int)resetWithLineBuffer:(LineBuffer *)lineBuffer unlimitedScrollback:(BOOL)unlimitedScrollback - preserveCursorLine:(BOOL)preserveCursorLine; + preservePromptLines:(int)preservePromptLines; // Move the grid contents up, leaving only the whole wrapped line the cursor is on at the top. - (void)moveWrappedCursorLineToTopOfGrid; diff --git a/sources/VT100Grid.m b/sources/VT100Grid.m index a8836249f5..4c1f128121 100644 --- a/sources/VT100Grid.m +++ b/sources/VT100Grid.m @@ -388,12 +388,12 @@ - (int)scrollUpIntoLineBuffer:(LineBuffer *)lineBuffer - (int)resetWithLineBuffer:(LineBuffer *)lineBuffer unlimitedScrollback:(BOOL)unlimitedScrollback - preserveCursorLine:(BOOL)preserveCursorLine { + preservePromptLines:(int)preservePromptLines { self.scrollRegionRows = VT100GridRangeMake(0, size_.height); self.scrollRegionCols = VT100GridRangeMake(0, size_.width); int numLinesToScroll; - if (preserveCursorLine) { - numLinesToScroll = cursor_.y; + if (preservePromptLines > 0) { + numLinesToScroll = cursor_.y - preservePromptLines + 1; } else { numLinesToScroll = [self lineNumberOfLastNonEmptyLine] + 1; } @@ -405,7 +405,7 @@ - (int)resetWithLineBuffer:(LineBuffer *)lineBuffer } self.cursor = VT100GridCoordMake(0, 0); - [self setCharsFrom:VT100GridCoordMake(0, preserveCursorLine ? 1 : 0) + [self setCharsFrom:VT100GridCoordMake(0, preservePromptLines) to:VT100GridCoordMake(size_.width - 1, size_.height - 1) toChar:[self defaultChar]]; diff --git a/sources/VT100Screen.m b/sources/VT100Screen.m index 96a47f9a3b..fc494eef8b 100644 --- a/sources/VT100Screen.m +++ b/sources/VT100Screen.m @@ -848,13 +848,22 @@ - (void)clearBuffer { // This clears the screen, leaving the cursor's line at the top and preserves the cursor's x // coordinate. Scroll regions and the saved cursor position are reset. - (void)clearAndResetScreenPreservingCursorLine { + int numberOfLinesInPrompt = [iTermAdvancedSettingsModel numberOfLinesInPrompt]; + if (numberOfLinesInPrompt <= 0) { + DLog(@"iTerm advanced settings variable 'numberOfLinesInPrompt' is equal or less than than zero: %d",numberOfLinesInPrompt); + numberOfLinesInPrompt = 1; + } else if (numberOfLinesInPrompt > 3) { + DLog(@"iTerm advanced settings variable 'numberOfLinesInPrompt' is greater than 3: %d",numberOfLinesInPrompt); + } + [delegate_ screenTriggerableChangeDidOccur]; // This clears the screen. int x = currentGrid_.cursorX; [self incrementOverflowBy:[currentGrid_ resetWithLineBuffer:linebuffer_ unlimitedScrollback:unlimitedScrollback_ - preserveCursorLine:YES]]; + preservePromptLines:numberOfLinesInPrompt]]; currentGrid_.cursorX = x; + currentGrid_.cursorY = numberOfLinesInPrompt - 1; } - (void)clearScrollbackBuffer @@ -2586,7 +2595,7 @@ - (void)terminalResetPreservingPrompt:(BOOL)preservePrompt { } else { [self incrementOverflowBy:[currentGrid_ resetWithLineBuffer:linebuffer_ unlimitedScrollback:unlimitedScrollback_ - preserveCursorLine:NO]]; + preservePromptLines:0]]; } [self setInitialTabStops]; diff --git a/sources/iTermAdvancedSettingsModel.h b/sources/iTermAdvancedSettingsModel.h index 8a1ec32490..05615ebbd7 100644 --- a/sources/iTermAdvancedSettingsModel.h +++ b/sources/iTermAdvancedSettingsModel.h @@ -106,6 +106,7 @@ + (BOOL)useOpenDirectory; + (BOOL)disallowCopyEmptyString; + (BOOL)profilesWindowJoinsActiveSpace; ++ (int)numberOfLinesInPrompt; + (NSString *)badgeFont; + (BOOL)badgeFontIsBold; diff --git a/sources/iTermAdvancedSettingsModel.m b/sources/iTermAdvancedSettingsModel.m index 905c8bdd8b..fcf6a357cd 100644 --- a/sources/iTermAdvancedSettingsModel.m +++ b/sources/iTermAdvancedSettingsModel.m @@ -83,6 +83,7 @@ + (NSString *)name { \ DEFINE_INT(triggerRadius, 3, @"Terminal: Number of screen lines to match against trigger regular expressions.\nTrigger regular expressions are matched against the last logical line of text when a newline is received. A search is performed to find the start of the line. Since very long lines would cause performance problems, the search (and consequently the regular expression match, highlighting, and so on) is limited to this many screen lines."); DEFINE_BOOL(requireCmdForDraggingText, NO, @"Terminal: To drag images or selected text, you must hold ⌘. This prevents accidental drags."); DEFINE_BOOL(focusReportingEnabled, YES, @"Terminal: Apps may turn on Focus Reporting.\nFocus reporting causes iTerm2 to send an escape sequence when a session gains or loses focus. It can cause problems when an ssh session dies unexpectedly because it gets left on, so some users prefer to disable it."); +DEFINE_INT(numberOfLinesInPrompt, 1, @"Terminal: Number of lines in prompt.\n\"Clear Buffer\" command clears all output except prompt lines. If prompt consist of more than one line, all lines except last will be cleared. You could set this variable to prompt lines count to avoid this behavior."); #pragma mark Hotkey DEFINE_FLOAT(hotkeyTermAnimationDuration, 0.25, @"Hotkey: Duration in seconds of the hotkey window animation.\nWarning: reducing this value may cause problems if you have multiple displays."); From 8cf13fa28cb593ad9fa306a2dcd9cd0ba9002ceb Mon Sep 17 00:00:00 2001 From: Vladimir Rudnyh Date: Mon, 1 Feb 2016 14:46:06 +0300 Subject: [PATCH 2/3] Fix code review remarks --- sources/VT100Grid.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/VT100Grid.m b/sources/VT100Grid.m index 4c1f128121..169f8780a9 100644 --- a/sources/VT100Grid.m +++ b/sources/VT100Grid.m @@ -392,8 +392,8 @@ - (int)resetWithLineBuffer:(LineBuffer *)lineBuffer self.scrollRegionRows = VT100GridRangeMake(0, size_.height); self.scrollRegionCols = VT100GridRangeMake(0, size_.width); int numLinesToScroll; - if (preservePromptLines > 0) { - numLinesToScroll = cursor_.y - preservePromptLines + 1; + if (preservePromptLines > 0 && preservePromptLines < size_.height) { + numLinesToScroll = MAX(0, cursor_.y - preservePromptLines + 1); } else { numLinesToScroll = [self lineNumberOfLastNonEmptyLine] + 1; } From 358abd29585531dbd5bae0e9338e715879e45eee Mon Sep 17 00:00:00 2001 From: Vladimir Rudnyh Date: Mon, 1 Feb 2016 16:31:25 +0300 Subject: [PATCH 3/3] Add Shell Integration support in preserve multiline prompt on 'clear buffer' feature --- sources/VT100Screen.m | 14 +++++++++++--- sources/iTermAdvancedSettingsModel.m | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sources/VT100Screen.m b/sources/VT100Screen.m index fc494eef8b..2398b4a18a 100644 --- a/sources/VT100Screen.m +++ b/sources/VT100Screen.m @@ -848,12 +848,20 @@ - (void)clearBuffer { // This clears the screen, leaving the cursor's line at the top and preserves the cursor's x // coordinate. Scroll regions and the saved cursor position are reset. - (void)clearAndResetScreenPreservingCursorLine { - int numberOfLinesInPrompt = [iTermAdvancedSettingsModel numberOfLinesInPrompt]; + int numberOfLinesInPrompt; + if (_shellIntegrationInstalled) { + numberOfLinesInPrompt = currentGrid_.cursorY + [self numberOfScrollbackLines] + [self totalScrollbackOverflow] - _lastCommandOutputRange.end.y + 1; + DLog(@"numberOfLinesInPrompt calculated (based on shell integration): %d", numberOfLinesInPrompt); + } else { + numberOfLinesInPrompt = [iTermAdvancedSettingsModel numberOfLinesInPrompt]; + DLog(@"numberOfLinesInPrompt taken from advanced settings: %d", numberOfLinesInPrompt); + } + if (numberOfLinesInPrompt <= 0) { - DLog(@"iTerm advanced settings variable 'numberOfLinesInPrompt' is equal or less than than zero: %d",numberOfLinesInPrompt); + DLog(@"iTerm advanced settings variable 'numberOfLinesInPrompt' is equal or less than than zero: %d", numberOfLinesInPrompt); numberOfLinesInPrompt = 1; } else if (numberOfLinesInPrompt > 3) { - DLog(@"iTerm advanced settings variable 'numberOfLinesInPrompt' is greater than 3: %d",numberOfLinesInPrompt); + DLog(@"iTerm advanced settings variable 'numberOfLinesInPrompt' is greater than 3: %d", numberOfLinesInPrompt); } [delegate_ screenTriggerableChangeDidOccur]; diff --git a/sources/iTermAdvancedSettingsModel.m b/sources/iTermAdvancedSettingsModel.m index fcf6a357cd..cbbf14eeb3 100644 --- a/sources/iTermAdvancedSettingsModel.m +++ b/sources/iTermAdvancedSettingsModel.m @@ -83,7 +83,7 @@ + (NSString *)name { \ DEFINE_INT(triggerRadius, 3, @"Terminal: Number of screen lines to match against trigger regular expressions.\nTrigger regular expressions are matched against the last logical line of text when a newline is received. A search is performed to find the start of the line. Since very long lines would cause performance problems, the search (and consequently the regular expression match, highlighting, and so on) is limited to this many screen lines."); DEFINE_BOOL(requireCmdForDraggingText, NO, @"Terminal: To drag images or selected text, you must hold ⌘. This prevents accidental drags."); DEFINE_BOOL(focusReportingEnabled, YES, @"Terminal: Apps may turn on Focus Reporting.\nFocus reporting causes iTerm2 to send an escape sequence when a session gains or loses focus. It can cause problems when an ssh session dies unexpectedly because it gets left on, so some users prefer to disable it."); -DEFINE_INT(numberOfLinesInPrompt, 1, @"Terminal: Number of lines in prompt.\n\"Clear Buffer\" command clears all output except prompt lines. If prompt consist of more than one line, all lines except last will be cleared. You could set this variable to prompt lines count to avoid this behavior."); +DEFINE_INT(numberOfLinesInPrompt, 1, @"Terminal: Number of lines in prompt.\n\"Clear Buffer\" command clears all output except prompt lines. If prompt consist of more than one line, all lines except last will be cleared. You could set this variable to prompt lines count to avoid this behavior. This param is ignored if Shell Integration is installed."); #pragma mark Hotkey DEFINE_FLOAT(hotkeyTermAnimationDuration, 0.25, @"Hotkey: Duration in seconds of the hotkey window animation.\nWarning: reducing this value may cause problems if you have multiple displays.");