/main.nu

http://github.com/Shadowfiend/pointy-haired-boss.tmbundle · Nushell · 117 lines · 113 code · 4 blank · 0 comment · 0 complexity · 4f39f9b0ad0a070291a689e7420d5d55 MD5 · raw file

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