Skip to content
Snippets Groups Projects
Commit f45edf31 authored by George Nachman's avatar George Nachman
Browse files

Add command history tool

parent d55fd096
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -11,6 +11,7 @@
extern NSString *const kCommandHistoryDidChangeNotificationName;
 
@class VT100RemoteHost;
@class VT100ScreenMark;
 
@interface CommandHistoryEntry : NSObject
 
Loading
Loading
@@ -26,13 +27,15 @@ extern NSString *const kCommandHistoryDidChangeNotificationName;
// NSNumber times since reference date
@property(nonatomic, readonly) NSMutableArray *useTimes;
 
- (VT100ScreenMark *)lastMark;
@end
 
@interface CommandHistory : NSObject
 
+ (instancetype)sharedInstance;
 
- (void)addCommand:(NSString *)command onHost:(VT100RemoteHost *)host;
- (void)addCommand:(NSString *)command onHost:(VT100RemoteHost *)host withMark:(VT100ScreenMark *)mark;
 
- (NSArray *)autocompleteSuggestionsWithPartialCommand:(NSString *)partialCommand
onHost:(VT100RemoteHost *)host;
Loading
Loading
Loading
Loading
@@ -27,6 +27,38 @@ static NSString *const kCommands = @"commands";
static const NSTimeInterval kMaxTimeToRememberCommands = 60 * 60 * 24 * 90;
static const int kMaxCommandsToSavePerHost = 200;
 
@interface CommandUse : NSObject
@property(nonatomic, assign) NSTimeInterval time;
@property(nonatomic, retain) VT100ScreenMark *mark;
+ (instancetype)commandUseFromSerializedValue:(NSArray *)serializedValue;
- (NSArray *)serializedValue;
@end
@implementation CommandUse
- (void)dealloc {
[_mark release];
[super dealloc];
}
- (NSArray *)serializedValue {
return @[ @(self.time) ];
}
+ (instancetype)commandUseFromSerializedValue:(id)serializedValue {
CommandUse *commandUse = [[[CommandUse alloc] init] autorelease];
if ([serializedValue isKindOfClass:[NSArray class]]) {
commandUse.time = [serializedValue[0] doubleValue];
} else if ([serializedValue isKindOfClass:[NSNumber class]]) {
commandUse.time = [serializedValue doubleValue];
}
return commandUse;
}
@end
@interface CommandHistory ()
@property(nonatomic, retain) NSMutableDictionary *hosts;
@end
Loading
Loading
@@ -52,7 +84,7 @@ static const int kMaxCommandsToSavePerHost = 200;
entry.command = dict[kCommand];
entry.uses = [dict[kUses] intValue];
entry.lastUsed = [dict[kLastUsed] doubleValue];
entry.useTimes = [[dict[kUseTimes] mutableCopy] autorelease];
[entry setSerializedUseTimes:dict[kUseTimes]];
return entry;
}
 
Loading
Loading
@@ -70,11 +102,25 @@ static const int kMaxCommandsToSavePerHost = 200;
[super dealloc];
}
 
- (NSArray *)serializableUseTimes {
NSMutableArray *result = [NSMutableArray array];
for (CommandUse *use in self.useTimes) {
[result addObject:[use serializedValue]];
}
return result;
}
- (void)setSerializedUseTimes:(NSArray *)array {
for (NSArray *value in array) {
[self.useTimes addObject:[CommandUse commandUseFromSerializedValue:value]];
}
}
- (NSDictionary *)dictionary {
return @{ kCommand: self.command,
kUses: @(self.uses),
kLastUsed: @(self.lastUsed),
kUseTimes: self.useTimes };
kUseTimes: [self serializableUseTimes] };
}
 
- (NSString *)description {
Loading
Loading
@@ -87,6 +133,11 @@ static const int kMaxCommandsToSavePerHost = 200;
self.matchLocation];
}
 
- (VT100ScreenMark *)lastMark {
CommandUse *use = [self.useTimes lastObject];
return use.mark;
}
// Used to sort from highest to lowest score. So Ascending means self's score is higher
// than other's.
- (NSComparisonResult)compare:(CommandHistoryEntry *)other {
Loading
Loading
@@ -169,7 +220,9 @@ static const int kMaxCommandsToSavePerHost = 200;
 
#pragma mark - APIs
 
- (void)addCommand:(NSString *)command onHost:(VT100RemoteHost *)host {
- (void)addCommand:(NSString *)command
onHost:(VT100RemoteHost *)host
withMark:(VT100ScreenMark *)mark {
NSMutableArray *commands = [self commandsForHost:host];
CommandHistoryEntry *theEntry = nil;
for (CommandHistoryEntry *entry in commands) {
Loading
Loading
@@ -186,7 +239,11 @@ static const int kMaxCommandsToSavePerHost = 200;
}
theEntry.uses = theEntry.uses + 1;
theEntry.lastUsed = [NSDate timeIntervalSinceReferenceDate];
[theEntry.useTimes addObject:@(theEntry.lastUsed )];
CommandUse *commandUse = [[[CommandUse alloc] init] autorelease];
commandUse.time = theEntry.lastUsed;
commandUse.mark = mark;
[theEntry.useTimes addObject:commandUse];
if ([[PreferencePanel sharedInstance] savePasteHistory]) {
[NSKeyedArchiver archiveRootObject:[self dictionaryForEntries] toFile:_path];
}
Loading
Loading
@@ -224,11 +281,12 @@ static const int kMaxCommandsToSavePerHost = 200;
- (NSArray *)entryArrayByExpandingAllUsesInEntryArray:(NSArray *)array {
NSMutableArray *result = [NSMutableArray array];
for (CommandHistoryEntry *entry in array) {
for (NSNumber *useTime in entry.useTimes) {
for (CommandUse *commandUse in entry.useTimes) {
CommandHistoryEntry *singleUseEntry = [[entry copy] autorelease];
[singleUseEntry.useTimes removeAllObjects];
[singleUseEntry.useTimes addObject:useTime];
singleUseEntry.lastUsed = [useTime doubleValue];
[singleUseEntry.useTimes addObject:commandUse];
singleUseEntry.lastUsed = commandUse.time;
[result addObject:singleUseEntry];
}
}
Loading
Loading
Loading
Loading
@@ -376,6 +376,7 @@ typedef enum {
- (void)showHideNotes;
- (void)previousMarkOrNote;
- (void)nextMarkOrNote;
- (void)scrollToMark:(VT100ScreenMark *)mark;
 
- (VT100RemoteHost *)currentHost;
 
Loading
Loading
Loading
Loading
@@ -3554,6 +3554,12 @@ static long long timeInTenthsOfSeconds(struct timeval t)
}
}
 
- (void)scrollToMark:(VT100ScreenMark *)mark {
VT100GridRange range = [SCREEN lineNumberRangeOfInterval:mark.entry.interval];
[TEXTVIEW scrollLineNumberRangeIntoView:range];
[self highlightMarkOrNote:mark];
}
- (VT100RemoteHost *)currentHost {
return [SCREEN remoteHostOnLine:[SCREEN numberOfLines]];
}
Loading
Loading
@@ -5273,6 +5279,10 @@ static long long timeInTenthsOfSeconds(struct timeval t)
forTabViewItem:[[self ptytab] tabViewItem]];
}
 
- (void)screenCurrentHostDidChange:(VT100RemoteHost *)host {
[[[self tab] realParentWindow] sessionHostDidChange:self to:host];
}
- (BOOL)screenShouldSendReport {
return (SHELL != nil) && (![self isTmuxClient]);
}
Loading
Loading
@@ -5324,10 +5334,11 @@ static long long timeInTenthsOfSeconds(struct timeval t)
NSString *trimmedCommand =
[command stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (trimmedCommand.length) {
[[CommandHistory sharedInstance] addCommand:trimmedCommand
onHost:[SCREEN remoteHostOnLine:range.end.y]];
VT100ScreenMark *mark = [SCREEN markOnLine:range.start.y];
mark.command = command;
[[CommandHistory sharedInstance] addCommand:trimmedCommand
onHost:[SCREEN remoteHostOnLine:range.end.y]
withMark:mark];
}
commandRange_ = VT100GridCoordRangeMake(-1, -1, -1, -1);
}
Loading
Loading
Loading
Loading
@@ -6132,6 +6132,12 @@ NSString *kSessionsKVCKey = @"sessions";
[self.window.dockTile setShowsApplicationBadge:YES];
}
 
- (void)sessionHostDidChange:(PTYSession *)session to:(VT100RemoteHost *)host {
if ([[self currentSession] == session]) {
[toolbelt_]
}
}
#pragma mark - KeyValueCoding
 
- (int)columns
Loading
Loading
Loading
Loading
@@ -45,10 +45,10 @@ static const CGFloat kMargin = 4;
tableView_ = [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, contentSize.width, contentSize.height)];
NSTableColumn *col;
col = [[[NSTableColumn alloc] initWithIdentifier:@"contents"] autorelease];
col = [[[NSTableColumn alloc] initWithIdentifier:@"commands"] autorelease];
[col setEditable:NO];
[tableView_ addTableColumn:col];
[[col headerCell] setStringValue:@"Contents"];
[[col headerCell] setStringValue:@"Commands"];
NSFont *theFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
[[col dataCell] setFont:theFont];
[tableView_ setRowHeight:[[[[NSLayoutManager alloc] init] autorelease] defaultLineHeightForFont:theFont]];
Loading
Loading
@@ -129,6 +129,18 @@ static const CGFloat kMargin = 4;
}
}
 
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
NSInteger row = [tableView_ selectedRow];
if (row != -1) {
CommandHistoryEntry *entry = entries_[row];
if (entry.lastMark) {
ToolWrapper *wrapper = (ToolWrapper *)[[self superview] superview];
[[wrapper.term currentSession] scrollToMark:entry.lastMark];
}
}
}
- (void)commandHistoryDidChange:(id)sender
{
[entries_ autorelease];
Loading
Loading
Loading
Loading
@@ -10,6 +10,7 @@
#import "ToolWrapper.h"
#import "FutureMethods.h"
 
@class ToolCommandHistoryView;
@class ToolbeltSplitView;
@class PseudoTerminal;
 
Loading
Loading
@@ -40,4 +41,6 @@
 
- (void)setUseDarkDividers:(BOOL)useDarkDividers;
 
- (ToolCommandHistoryView *)commandHistoryView;
@end
Loading
Loading
@@ -287,4 +287,9 @@ static NSString *kToolbeltPrefKey = @"ToolbeltTools";
}
}
 
- (ToolCommandHistoryView *)commandHistoryView {
ToolWrapper *wrapper = [tools_ objectForKey:theName];
// TODO FINISH THIS
}
@end
Loading
Loading
@@ -197,5 +197,6 @@ extern int kVT100ScreenMinRows;
- (void)setWorkingDirectory:(NSString *)workingDirectory onLine:(int)line;
- (NSString *)workingDirectoryOnLine:(int)line;
- (VT100RemoteHost *)remoteHostOnLine:(int)line;
- (VT100ScreenMark *)lastCommandMark; // last mark representing a command
 
@end
Loading
Loading
@@ -2623,6 +2623,7 @@ static const double kInterBellQuietPeriod = 0.1;
 
- (void)terminalSetRemoteHost:(NSString *)remoteHost {
NSRange atRange = [remoteHost rangeOfString:@"@"];
VT100RemoteHost *currentHost = [self remoteHostOnLine:[self numberOfLines]];
NSString *user = nil;
NSString *host = nil;
if (atRange.length == 1) {
Loading
Loading
@@ -2641,6 +2642,11 @@ static const double kInterBellQuietPeriod = 0.1;
}
int cursorLine = [self numberOfLines] - [self height] + currentGrid_.cursorY;
[self setRemoteHost:host user:user onLine:cursorLine];
if (![host isEqual:currentHost]) {
[delegate_ screenCurrentHostDidChange:host];
}
// TODO: If remote host has changed, pass a message up to the ToolCommandHistoryView to reload its state.
}
 
- (void)terminalClearScreen {
Loading
Loading
@@ -2921,7 +2927,7 @@ static const double kInterBellQuietPeriod = 0.1;
// TODO
}
 
- (void)terminalReturnCodeOfLastCommandWas:(int)returnCode {
- (VT100ScreenMark *)lastCommandMark {
NSEnumerator *enumerator = [intervalTree_ reverseLimitEnumerator];
NSArray *objects = [enumerator nextObject];
int numChecked = 0;
Loading
Loading
@@ -2930,15 +2936,23 @@ static const double kInterBellQuietPeriod = 0.1;
if ([obj isKindOfClass:[VT100ScreenMark class]]) {
VT100ScreenMark *mark = (VT100ScreenMark *)obj;
if (mark.command) {
mark.code = returnCode;
[delegate_ screenNeedsRedraw];
return;
return mark;
}
}
++numChecked;
}
objects = [enumerator nextObject];
}
return nil;
}
- (void)terminalReturnCodeOfLastCommandWas:(int)returnCode {
VT100ScreenMark *mark = [self lastCommandMark];
if (mark) {
mark.code = returnCode;
[delegate_ screenNeedsRedraw];
}
}
 
- (void)terminalFinalTermCommand:(NSArray *)argv {
Loading
Loading
#import <Cocoa/Cocoa.h>
#import "PTYTextViewDataSource.h"
 
@class VT100RemoteHost;
@protocol VT100ScreenDelegate <NSObject>
 
// Screen contents have become dirty and should be redrawn right away.
Loading
Loading
@@ -203,6 +205,8 @@
- (void)screenSetTabColorGreenComponentTo:(CGFloat)color;
- (void)screenSetTabColorBlueComponentTo:(CGFloat)color;
 
- (void)screenCurrentHostDidChange:(VT100RemoteHost *)host;
// Ok to write to shell?
- (BOOL)screenShouldSendReport;
 
Loading
Loading
Loading
Loading
@@ -318,4 +318,6 @@ typedef enum {
// Indicates if this the hotkey window.
- (BOOL)isHotKeyWindow;
 
- (void)sessionHostDidChange:(PTYSession *)session to:(VT100RemoteHost *)host;
@end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment