Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions Hammerspoon/ConsoleWindow.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14113" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14113"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
Expand All @@ -15,48 +15,47 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Hammerspoon Console" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="console" animationBehavior="default" id="P23-aL-ez6">
<window title="Hammerspoon Console" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="console" animationBehavior="default" id="P23-aL-ez6">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="916" y="704" width="510" height="389"/>
<rect key="screenRect" x="0.0" y="0.0" width="3200" height="1778"/>
<rect key="screenRect" x="0.0" y="0.0" width="1710" height="1068"/>
<value key="minSize" type="size" width="340" height="200"/>
<view key="contentView" id="2jF-WS-ElT">
<rect key="frame" x="0.0" y="0.0" width="510" height="389"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gls-wS-aCi">
<rect key="frame" x="20" y="51" width="470" height="318"/>
<clipView key="contentView" id="vxQ-4d-mld">
<rect key="frame" x="1" y="1" width="468" height="316"/>
<scrollView horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="gls-wS-aCi">
<rect key="frame" x="20" y="47" width="470" height="322"/>
<clipView key="contentView" drawsBackground="NO" id="vxQ-4d-mld">
<rect key="frame" x="1" y="1" width="468" height="320"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView importsGraphics="NO" verticallyResizable="YES" usesFontPanel="YES" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="Jlb-eC-MmZ">
<rect key="frame" x="0.0" y="0.0" width="468" height="316"/>
<textView editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" findStyle="bar" allowsCharacterPickerTouchBarItem="NO" textCompletion="NO" id="Jlb-eC-MmZ">
<rect key="frame" x="0.0" y="0.0" width="468" height="320"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<size key="minSize" width="468" height="316"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="468" height="320"/>
<size key="maxSize" width="612" height="10000000"/>
<color key="insertionPointColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</textView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="bBB-1O-Jf0">
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="bBB-1O-Jf0">
<rect key="frame" x="-100" y="-100" width="87" height="18"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" horizontal="NO" id="Kjj-rY-Bja">
<rect key="frame" x="453" y="1" width="16" height="316"/>
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="Kjj-rY-Bja">
<rect key="frame" x="453" y="1" width="16" height="320"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="vJ5-eP-Q1d" customClass="HSGrowingTextField">
<rect key="frame" x="20" y="20" width="470" height="23"/>
<textField focusRingType="none" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="vJ5-eP-Q1d" customClass="HSGrowingTextField">
<rect key="frame" x="20" y="20" width="470" height="19"/>
<textFieldCell key="cell" selectable="YES" editable="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="CiF-1K-0Ju">
<font key="font" size="12" name="Menlo-Regular"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
Expand Down
44 changes: 32 additions & 12 deletions Hammerspoon/MJConsoleWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ @interface MJConsoleWindowController ()
@property (weak) IBOutlet NSTextField* inputField;
@property NSMutableArray* preshownStdouts;
@property NSDateFormatter *dateFormatter;
@property NSMutableArray *outputBuffer;
@property NSTimer *outputTimer;

@end

Expand All @@ -41,6 +43,34 @@ - (id) init {
[self.dateFormatter setLocale:enUSPOSIXLocale];
[self.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

self.outputBuffer = [[NSMutableArray alloc] initWithCapacity:1000];

// Strings that we want to add to the console window are batched up in self.outputBuffer and this timer drains them
self.outputTimer = [NSTimer timerWithTimeInterval:0.2 repeats:YES block:^(NSTimer * _Nonnull timer) {
if (self.outputBuffer.count > 0) {
@autoreleasepool {
NSTextStorage *storage = self.outputView.textStorage;
[storage beginEditing];

for (NSAttributedString *attrstr in self.outputBuffer) {
int curLength = (int)storage.length;
int maxLength = self.maxConsoleOutputHistory.intValue;
int addLength = (int)attrstr.length;

[storage appendAttributedString:attrstr];
if (curLength > maxLength && maxLength > 0) {
[storage deleteCharactersInRange:NSMakeRange(0, curLength - maxLength + addLength)];
}
}

[self.outputBuffer removeAllObjects];
[storage endEditing];
[self.outputView scrollToEndOfDocument:self];
}
}
}];
[[NSRunLoop mainRunLoop] addTimer:self.outputTimer forMode:NSRunLoopCommonModes];

[self initializeConsoleColorsAndFont] ;
}
return self;
Expand Down Expand Up @@ -141,18 +171,8 @@ - (void) appendString:(NSString*)str type:(MJReplLineType)type {
NSDictionary* attrs = @{NSFontAttributeName: self.consoleFont, NSForegroundColorAttributeName: color};
NSAttributedString* attrstr = [[NSAttributedString alloc] initWithString:str attributes:attrs];

dispatch_async(dispatch_get_main_queue(), ^{
NSTextStorage *storage = self.outputView.textStorage;
int curLength = (int)storage.length;
int maxLength = self.maxConsoleOutputHistory.intValue;
int addLength = (int)attrstr.length;

[storage appendAttributedString:attrstr];
if (curLength > maxLength && maxLength > 0) {
[storage deleteCharactersInRange:NSMakeRange(0, curLength - maxLength + addLength)];
}
[self.outputView scrollToEndOfDocument:self];
});
// We don't actually append the string immediately, it goes into a buffer that drains on a timer (see above)
[self.outputBuffer addObject:attrstr];
}

- (NSString*) run:(NSString*)command {
Expand Down
Loading