"""MacGregor. """ import pickle, os.path import objc from PyObjCTools import NibClassBuilder, AppHelper from Foundation import * from AppKit import * import SelectedObjectsFilteringController NibClassBuilder.extractClasses("MacGregorDocument") NibClassBuilder.extractClasses("MainMenu") class DragTargetTableView(NibClassBuilder.AutoBaseClass): def draggingApplies(self, sender, pboard=None): sourceDragMask = sender.draggingSourceOperationMask() if pboard is None: pboard = sender.draggingPasteboard() if pboard.types().containsObject_(NSFilenamesPboardType): return sourceDragMask & NSDragOperationCopy return False def draggingEntered_(self, sender): if self.draggingApplies(sender): return NSDragOperationCopy return NSDragOperationNone def performDragOperation_(self, sender): pboard = sender.draggingPasteboard() if self.draggingApplies(sender, pboard): files = list(pboard.propertyListForType_(NSFilenamesPboardType)) self.document.filesAdded_(files) return True return False # def concludeDragOperation_(self, sender): # pass class MacGregorAppDelegate(NibClassBuilder.AutoBaseClass): def getKeyWindow(self): return NSApplication.sharedApplication().keyWindow().delegate() def toggleDrawer_(self, sender): self.getKeyWindow().infoDrawer.toggle_(sender) def removeItem_(self, sender): self.getKeyWindow().removeItem_(sender) class MacGregorDocument(NibClassBuilder.AutoBaseClass): files = objc.ivar('files') results = objc.ivar('results') def init(self): self = super(MacGregorDocument, self).init() self.files = NSMutableArray.array() self.results = NSMutableArray.array() return self def filesAdded_(self, files): self.filesController.addObjects_( [dict( fileName=os.path.split(x)[1], filePath=os.path.split(x)[0], fullPath=x) for x in files]) def awakeFromNib(self): self.dropTarget.registerForDraggedTypes_([NSFilenamesPboardType]) self.fileList.setDoubleAction_("openFile:") self.resultsList.setDoubleAction_("openFile:") self.infoDrawer.setLeadingOffset_(10.0) self.infoDrawer.setTrailingOffset_(10.0) self.infoDrawer.toggle_(self) self.cached_fileListInspector_frame = self.fileListInspector.frame() self.cached_resultsListInspector_frame = self.resultsListInspector.frame() self.inspectorMapping = { self.fileList: (self.fileListInspector, self.cached_fileListInspector_frame), self.resultsList: (self.resultsListInspector, self.cached_resultsListInspector_frame)} self.selectionChanged_(self.fileList) def windowNibName(self): return "MacGregorDocument" def readFromFile_ofType_(self, path, tp): docu = open(path) pick = pickle.Unpickler(docu) self.files = [ dict( fileName=os.path.split(x)[1], filePath=os.path.split(x)[0], fullPath=x) for x in pick.load()] docu.close() return True def writeToFile_ofType_(self, path, tp): docu = open(path, 'w') pick = pickle.Pickler(docu) pick.dump([x['fullPath'] for x in self.files]) docu.close() return True def windowControllerDidLoadNib_(self, controller): pass currentTask = None currentFileHandle = None def performSearch_(self, sender): self.setValue_forKey_([], 'results') if self.currentTask is not None: print "KILLING TASK" self.currentData = '' self.currentTask.terminate() self.currentFileHandle.closeFile() self.currentTask = None self.currentFileHandle = None if not len(self.searchBox.stringValue()): return taskArgs = ['-r', '-n', '-I', self.searchBox.stringValue()] taskArgs.extend([x['fullPath'] for x in self.files]) grepper = NSTask.alloc().init() output = NSPipe.pipe() grepper.setStandardOutput_(output) grepper.setLaunchPath_(u'/usr/bin/grep') grepper.setArguments_(taskArgs) print "LAUNCHING NEW PROCESS", grepper grepper.launch() self.arrayOfFoundItems = [] self.currentTask = grepper fl = output.fileHandleForReading() center = NSNotificationCenter.defaultCenter() center.addObserver_selector_name_object_( self, self.taskDidDie_, NSTaskDidTerminateNotification, grepper) center.addObserver_selector_name_object_( self, self.dataAvailableFromChild_, NSFileHandleReadCompletionNotification, fl) fl.readInBackgroundAndNotify() self.currentFileHandle = fl def taskDidDie_(self, notification): self.addFoundItems() print "TASK DID DIE", notification.object() currentData = '' def dataAvailableFromChild_(self, notification): notificationHandle = notification.object() if notificationHandle is not self.currentFileHandle: #print "WRONG TASK; IGNORING" return data = notification.userInfo()[NSFileHandleNotificationDataItem].bytes() if not data: ## EOF was reached; child is dead self.currentTask = None self.currentFileHandle = None return self.currentData += str(data) self.currentFileHandle.readInBackgroundAndNotify() #print "HAVE DATA", self.currentData while '\n' in self.currentData: line, self.currentData = self.currentData.split('\n', 1) if not line.strip(): #print "SKIPPING BLANK LINE" continue if line.count(':') < 2: #print "SKIPPING BIZARRE LINE", line continue (x, y, z) = line.strip().split(':', 2) result = dict( filePath=os.path.split(x)[0], fileName=os.path.split(x)[1], fullPath=x, lineNumber=y, excerpt=z) self.arrayOfFoundItems.append(result) if len(self.arrayOfFoundItems) > 10: self.addFoundItems() def addFoundItems(self): self.resultsController.addObjects_(self.arrayOfFoundItems) self.arrayOfFoundItems = [] def openFile_(self, sender): workspace = NSWorkspace.sharedWorkspace() if sender is self.fileList: full_path = self.files[sender.selectedRow()]['fullPath'] elif sender is self.resultsList: full_path = self.results[sender.selectedRow()]['fullPath'] return workspace.openFile_(full_path) def selectionChanged_(self, sender): newView, newFrame = self.inspectorMapping[sender] newSize = (0, newFrame.size.height) self.infoDrawer.setMinContentSize_(newSize) self.infoDrawer.setMaxContentSize_(newSize) self.infoDrawer.setContentSize_(newSize) self.infoDrawer.setContentView_(newView) self.infoDrawer.open_(sender) # def removeItem_(self, sender): # self.willChangeValueForKey_(u"files") # obj = self.files[self.fileList.selectedRow()] # self.files = filter(lambda x: x != obj, self.files) # self.didChangeValueForKey_(u"files") if __name__ == "__main__": AppHelper.runEventLoop()