Permalink
Browse files

Implement tail find

  • Loading branch information...
1 parent 013f253 commit f37ebb5a089a4353ebaf486148d5280fecc78134 @gnachman gnachman committed Oct 25, 2011
Showing with 174 additions and 7 deletions.
  1. +8 −0 Headers/iTerm/PTYSession.h
  2. +9 −0 Headers/iTerm/PTYTextView.h
  3. +5 −0 Headers/iTerm/VT100Screen.h
  4. +25 −4 LineBuffer.h
  5. +16 −0 LineBuffer.m
  6. +85 −0 PTYSession.m
  7. +15 −3 PTYTextView.m
  8. +11 −0 VT100Screen.m
@@ -32,6 +32,7 @@
#import "TextViewWrapper.h"
#import "FindViewController.h"
#import "ITAddressBookMgr.h"
+#import "LineBuffer.h"
#include <sys/time.h>
@@ -227,6 +228,9 @@ typedef enum {
// Does the terminal think this session is focused?
BOOL focused_;
+
+ FindContext tailFindContext_;
+ NSTimer *tailFindTimer_;
}
// Return the current pasteboard value as a string.
@@ -508,6 +512,7 @@ typedef enum {
- (void)launchCoprocessWithCommand:(NSString *)command;
- (void)setFocused:(BOOL)focused;
+- (BOOL)wantsContentChangedNotification;
@end
@@ -528,5 +533,8 @@ typedef enum {
- (NSString*)_lang;
- (NSString*)encodingName;
- (void)setDvrFrame;
+- (void)stopTailFind;
+- (void)beginTailFind;
+- (void)continueTailFind;
@end
@@ -31,6 +31,7 @@
#import "ScreenChar.h"
#import "PreferencePanel.h"
#import "Trouter.h"
+#import "LineBuffer.h"
#include <sys/time.h>
#define PRETTY_BOLD
@@ -298,6 +299,9 @@ typedef struct PTYFontInfo PTYFontInfo;
// Show a background indicator when in broadcast input mode
BOOL useBackgroundIndicator_;
+
+ // Find context just after initialization.
+ FindContext initialFindContext_;
}
+ (NSCursor *)textViewCursor;
@@ -531,6 +535,11 @@ typedef struct PTYFontInfo PTYFontInfo;
- (double)perceivedBrightness:(NSColor*)c;
- (void)drawOutlineInRect:(NSRect)rect topOnly:(BOOL)topOnly;
+// Add a search result for highlighting in yellow.
+- (void)addResultFromX:(int)resStartX absY:(long long)absStartY toX:(int)resEndX toAbsY:(long long)absEndY;
+
+- (FindContext *)initialFindContext;
+
@end
//
@@ -302,6 +302,7 @@ void StringToScreenChars(NSString *s,
- (BOOL)continueFindAllResults:(NSMutableArray*)results
inContext:(FindContext*)context;
- (void)cancelFindInContext:(FindContext*)context;
+- (void)setFindContextPositionToEnd:(FindContext *)context;
- (void) dumpDebugLog;
@@ -317,6 +318,10 @@ void StringToScreenChars(NSString *s,
// Accessor.
- (DVR*)dvr;
+// If this returns true then the textview will broadcast iTermTabContentsChanged
+// when a dirty char is found.
+- (BOOL)shouldSendContentsChangedNotification;
+
// Load a frame from a dvr decoder.
- (void)setFromFrame:(screen_char_t*)s len:(int)len info:(DVRFrameInfo)info;
View
@@ -50,13 +50,35 @@
}
@end
+#define FindOptCaseInsensitive (1 << 0)
+#define FindOptBackwards (1 << 1)
+#define FindOptRegex (1 << 2)
+#define FindMultipleResults (1 << 3)
typedef struct FindContext {
+ // Current absolute block number being searched.
int absBlockNum;
+
+ // The substring to search for.
NSString* substring;
+
+ // A bitwise OR of the options defined above.
int options;
+
+ // 1: search forward. -1: search backward.
int dir;
+
+ // The offset within a block to begin searching. -1 means the end of the
+ // block.
int offset;
+
+ // The offset within a block at which to stop searching. No results
+ // with an offset at or beyond this position will be returned.
int stopAt;
+
+ // Searching: a search is in progress and this context can be used to search.
+ // Matched: At least one result has been found. This context can be used to
+ // search again.
+ // NotFound: No results were found and the end of the buffer was reached.
enum { Searching, Matched, NotFound } status;
int matchLength;
NSMutableArray* results; // used for multiple results
@@ -245,10 +267,6 @@ typedef struct FindContext {
// Search for a substring. If found, return the position of the hit. Otherwise return -1. Use 0 for the start to indicate the beginning of the buffer or
// pass the result of a previous findSubstring result. The number of positions the result occupies will be set in *length (which would be different than the
// length of the substring in the presence of double-width characters.
-#define FindOptCaseInsensitive (1 << 0)
-#define FindOptBackwards (1 << 1)
-#define FindOptRegex (1 << 2)
-#define FindMultipleResults (1 << 3)
- (void)initFind:(NSString*)substring startingAt:(int)start options:(int)options withContext:(FindContext*)context;
- (void)releaseFind:(FindContext*)context;
- (void)findSubstring:(FindContext*)context stopAt:(int)stopAt;
@@ -270,4 +288,7 @@ typedef struct FindContext {
// Returns the position at the end of the buffer
- (int) lastPos;
+// Set the position of the find context to the end of the buffer.
+- (void)setFindContextPositionToEnd:(FindContext *)context;
+
@end
View
@@ -1555,5 +1555,21 @@ - (int) lastPos
return position;
}
+- (void)setFindContextPositionToEnd:(FindContext *)context
+{
+ if (![blocks count]) {
+ context->absBlockNum = 0;
+ context->offset = 0;
+ return;
+ }
+ context->absBlockNum = num_dropped_blocks + [blocks count] - 1;
+ if ([blocks count] > num_dropped_blocks) {
+ LineBlock* block = [blocks lastObject];
+ context->offset = [block rawSpaceUsed] - 1;
+ } else {
+ context->offset = 0;
+ }
+}
+
@end
View
@@ -116,12 +116,17 @@ - (id)init
selector:@selector(coprocessChanged)
name:@"kCoprocessStatusChangeNotification"
object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(sessionContentsChanged:)
+ name:@"iTermTabContentsChanged"
+ object:nil];
return self;
}
- (void)dealloc
{
+ [self stopTailFind]; // This frees the substring in the tail find context, if needed.
[triggerLine_ release];
[triggers_ release];
[pasteboard_ release];
@@ -2787,6 +2792,10 @@ - (void)updateDisplay
[updateTimer release];
updateTimer = nil;
}
+
+ if (tailFindTimer_ && [[[view findViewController] view] isHidden]) {
+ [self stopTailFind];
+ }
timerRunning_ = NO;
}
@@ -3164,6 +3173,16 @@ - (void)setFocused:(BOOL)focused
}
}
+- (BOOL)wantsContentChangedNotification
+{
+ // We want a content change notification if it's worth doing a tail find.
+ // That means the find window is open, we're not already doing a tail find,
+ // and a search was performed in the find window (vs select+cmd-e+cmd-f).
+ return !tailFindTimer_ &&
+ ![[[view findViewController] view] isHidden] &&
+ [TEXTVIEW initialFindContext]->substring != nil;
+}
+
@end
@implementation PTYSession (ScriptingSupport)
@@ -3373,4 +3392,70 @@ - (void)setDvrFrame
[[[self tab] realParentWindow] setWindowTitle];
}
+- (void)continueTailFind
+{
+ NSMutableArray *results = [NSMutableArray array];
+ BOOL more;
+ more = [SCREEN continueFindAllResults:results
+ inContext:&tailFindContext_];
+ for (SearchResult *r in results) {
+ [TEXTVIEW addResultFromX:r->startX
+ absY:r->absStartY
+ toX:r->endX
+ toAbsY:r->absEndY];
+ }
+ if ([results count]) {
+ [TEXTVIEW setNeedsDisplay:YES];
+ }
+ if (more) {
+ tailFindTimer_ = [NSTimer scheduledTimerWithTimeInterval:0.01
+ target:self
+ selector:@selector(continueTailFind)
+ userInfo:nil
+ repeats:NO];
+ } else {
+ tailFindTimer_ = nil;
+ }
+}
+
+- (void)beginTailFind
+{
+ FindContext *initialFindContext = [TEXTVIEW initialFindContext];
+ if (!initialFindContext->substring) {
+ return;
+ }
+ [SCREEN initFindString:initialFindContext->substring
+ forwardDirection:YES
+ ignoringCase:!!(initialFindContext->options & FindOptCaseInsensitive)
+ regex:!!(initialFindContext->options & FindOptRegex)
+ startingAtX:0
+ startingAtY:0
+ withOffset:0
+ inContext:&tailFindContext_
+ multipleResults:YES];
+
+ // Set the starting position to the block & offset that the backward search
+ // began at. Do a forward search from that location.
+ tailFindContext_.absBlockNum = initialFindContext->absBlockNum;
+ tailFindContext_.offset = initialFindContext->offset;
+
+ [self continueTailFind];
+}
+
+- (void)sessionContentsChanged:(NSNotification *)notification
+{
+ if (!tailFindTimer_) {
+ [self beginTailFind];
+ }
+}
+
+- (void)stopTailFind
+{
+ if (tailFindTimer_) {
+ [SCREEN cancelFindInContext:&tailFindContext_];
+ [tailFindTimer_ invalidate];
+ tailFindTimer_ = nil;
+ }
+}
+
@end
View
@@ -407,6 +407,7 @@ - (void)dealloc
[workingDirectoryAtLines release];
[trouter release];
+ [initialFindContext_.substring release];
[super dealloc];
}
@@ -4116,7 +4117,7 @@ - (void)growSelectionRight
}
// Add a match to resultMap_
-- (void)_addResultFromX:(int)resStartX absY:(long long)absStartY toX:(int)resEndX toAbsY:(long long)absEndY
+- (void)addResultFromX:(int)resStartX absY:(long long)absStartY toX:(int)resEndX toAbsY:(long long)absEndY
{
int width = [dataSource width];
for (long long y = absStartY; y <= absEndY; y++) {
@@ -4243,6 +4244,11 @@ - (BOOL)_selectNextResultForward:(BOOL)forward withOffset:(int)offset
return found;
}
+- (FindContext *)initialFindContext
+{
+ return &initialFindContext_;
+}
+
// continueFind is called by a timer in the client until it returns NO. It does
// two things:
// 1. If _findInProgress is true, search for more results in the dataSource and
@@ -4266,7 +4272,7 @@ - (BOOL)continueFind
// Add new results to map.
for (int i = nextOffset_; i < [findResults_ count]; i++) {
SearchResult* r = [findResults_ objectAtIndex:i];
- [self _addResultFromX:r->startX absY:r->absStartY toX:r->endX toAbsY:r->absEndY];
+ [self addResultFromX:r->startX absY:r->absStartY toX:r->endX toAbsY:r->absEndY];
redraw = YES;
}
nextOffset_ = [findResults_ count];
@@ -4330,6 +4336,12 @@ - (BOOL)findString:(NSString *)aString
withOffset:0
inContext:[dataSource findContext]
multipleResults:YES];
+
+ [initialFindContext_.substring release];
+ initialFindContext_ = *[dataSource findContext];
+ initialFindContext_.results = nil;
+ initialFindContext_.substring = [initialFindContext_.substring copy];
+
_findInProgress = YES;
// Reset every bit of state.
@@ -7411,7 +7423,7 @@ - (BOOL)updateDirtyRects
}
- if (foundDirty && [[iTermExpose sharedInstance] isVisible]) {
+ if (foundDirty && [dataSource shouldSendContentsChangedNotification]) {
changedSinceLastExpose_ = YES;
[[NSNotificationCenter defaultCenter] postNotificationName:@"iTermTabContentsChanged"
object:nil
View
@@ -52,6 +52,7 @@
#import "DVRBuffer.h"
#import "PTYTab.h"
#import "ITAddressBookMgr.h"
+#import "iTermExpose.h"
#define MAX_SCROLLBACK_LINES 1000000
#define DIRTY_MAGIC 0x76 // Used to ensure we don't go off end of dirty array
@@ -3477,6 +3478,11 @@ - (BOOL)continueFindResultAtStartX:(int*)startX
maxTime:0.1];
}
+- (void)setFindContextPositionToEnd:(FindContext *)context
+{
+ [linebuffer setFindContextPositionToEnd:context];
+}
+
- (void)saveToDvr
{
if (!dvr || ![[PreferencePanel sharedInstance] instantReplay]) {
@@ -3577,6 +3583,11 @@ - (DVR*)dvr
return dvr;
}
+- (BOOL)shouldSendContentsChangedNotification
+{
+ return [[iTermExpose sharedInstance] isVisible] ||
+ [SESSION wantsContentChangedNotification];
+}
@end

0 comments on commit f37ebb5

Please sign in to comment.