PageRenderTime 45ms CodeModel.GetById 11ms app.highlight 2ms RepoModel.GetById 29ms app.codeStats 0ms

/main.nu

http://github.com/Shadowfiend/pointy-haired-boss.tmbundle
Unknown | 117 lines | 93 code | 24 blank | 0 comment | 0 complexity | 4f39f9b0ad0a070291a689e7420d5d55 MD5 | raw file
  1(import Cocoa)
  2
  3; Filters ANSI escape codes from the given string. Probably nowhere near foolproof.
  4(function filter-escape-codes (string)
  5  (/[\003\032]/
  6    replaceWithString:""
  7             inString:(/\c[(\[|\(|\))[;?0-9]*[0-9A-Za-z]/
  8                        replaceWithString:""
  9                                 inString:string)))
 10
 11; A PHBTask is used to fire up an NSTask and feed its standard error
 12; and output to a vico buffer.  Standard input can be written to using
 13; writeString:, and subclasses can preprocess output
 14; (preprocessOutput:isError:) or just play with it without modifying the
 15; resulting output (handleOutput:isError:).
 16(class PHBTask is NSObject
 17  (ivar (id) task
 18        (id) buffer-name
 19        (id) buffer-text
 20        (id) std-out
 21        (id) std-err
 22        (id) std-in)
 23
 24  (+ phbTaskWithBufferName:(id)name launchPath:(id)launchPath isShellScript:(BOOL)runInShell is
 25    (((PHBTask) alloc) initWithBufferName:name launchPath:launchPath isShellScript:runInShell))
 26
 27  (- initWithBufferName:(id)name launchPath:(id)launchPath isShellScript:(BOOL)runInShell is
 28    (self initWithBufferName:name launchPath:launchPath arguments:'() isShellScript:runInShell))
 29
 30  (- initWithBufferName:(id)name launchPath:(id)launchPath arguments:(id)argumentList isShellScript:(BOOL)runInShell is
 31    (self initWithBufferName:name launchPath:launchPath arguments:argumentList workingDirectory:((current-window baseURL) path) isShellScript:runInShell))
 32
 33  (- initWithBufferName:(id)name launchPath:(id)launchPath arguments:(id)argumentList workingDirectory:(id)workingDirectory isShellScript:(BOOL)runInShell is
 34    (super init)
 35
 36    (set @buffer-name name)
 37
 38    (set @task ((NSTask alloc) init))
 39    (let ((std-out-pipe (NSPipe pipe))
 40          (std-err-pipe (NSPipe pipe))
 41          (std-in-pipe (NSPipe pipe))
 42          (current-window (current-window)))
 43      (set @std-out (std-out-pipe fileHandleForReading))
 44      (set @std-err (std-err-pipe fileHandleForReading))
 45      (set @std-in (std-in-pipe fileHandleForWriting))
 46
 47      (if runInShell
 48        (then
 49          (@task setLaunchPath:"/bin/bash")
 50          (@task setArguments:(NSArray arrayWithList:(cons launchPath argumentList))))
 51        (else
 52          (@task setLaunchPath:launchPath)))
 53
 54      (@task setCurrentDirectoryPath:workingDirectory)
 55      (@task setStandardInput:std-in-pipe)
 56      (@task setStandardOutput:std-out-pipe)
 57      (@task setStandardError:std-err-pipe)
 58      
 59      ((NSNotificationCenter defaultCenter)
 60        addObserver:self
 61           selector:"outputReceived:"
 62               name:NSFileHandleReadCompletionNotification
 63             object:nil))
 64    self)
 65
 66  (- start is
 67    ((current-text) input:(+ "<esc>:tabnew " @buffer-name "<CR>"))
 68    (set @buffer-text (current-text))
 69    (@buffer-text input:"<esc>gT")
 70
 71    (@std-out readInBackgroundAndNotify)
 72    (@std-err readInBackgroundAndNotify)
 73    (@task launch))
 74
 75  (- exit is
 76    (@buffer-text input:"<esc>:bd<CR>")
 77    (@task terminate))
 78
 79  (- forceExit is
 80    (system (+ "kill -9 " (@task processIdentifier))))
 81
 82  (- writeString:(id)aString is
 83    (@std-in writeData:(aString dataUsingEncoding:NSUTF8StringEncoding)))
 84
 85  (- filterEscapeCodes:(id)aString is
 86    (filter-escape-codes aString))
 87
 88  ; For overriding by child classes that want to parse incoming output or whatever.
 89  (- handleOutput:(id)output isError:(BOOL)isError is)
 90
 91  ; Does any preprocessing of output before emitting it to the buffer. By default,
 92  ; filters escape codes.
 93  (- preprocessOutput:(id)output isError:(BOOL)isError is
 94    (filter-escape-codes output))
 95
 96  (- appendOutput:(id)output is
 97    (let (text-storage (@buffer-text textStorage))
 98      (let (line-range (text-storage rangeOfLine:(text-storage lineCount)))
 99        (let (line-end (+ (head line-range) (head (tail line-range))))
100          (@buffer-text insertString:output atLocation:line-end)))))
101
102  (- outputReceived:(id) notification is
103    (if (or (eq (notification object) @std-out) (eq (notification object) @std-err))
104      (let ((isError (eq (notification object) @std-err))
105          (data ((notification userInfo) objectForKey:NSFileHandleNotificationDataItem)))
106        (let (string-data ((NSString alloc) initWithData:data encoding:NSUTF8StringEncoding))
107          (self handleOutput:string-data isError:isError)
108          (self appendOutput:(self preprocessOutput:string-data isError:isError)))
109
110        ; 0-length data means we are at EOF.
111        (unless (<= (data length) 0)
112          ((notification object) readInBackgroundAndNotify)))))
113          
114  (- dealloc is
115    (@task terminate)
116    ((NSNotificationCenter) defaultCenter) removeObserver:self))
117