|
| 1 | +/* |
| 2 | + * decaffeinate suggestions: |
| 3 | + * DS101: Remove unnecessary use of Array.from |
| 4 | + * DS102: Remove unnecessary code created because of implicit returns |
| 5 | + * DS207: Consider shorter variations of null checks |
| 6 | + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md |
| 7 | + */ |
| 8 | +import { throttle } from 'underscore-plus'; |
| 9 | +import { Emitter } from 'atom'; |
| 10 | +import IPC from './ipc'; |
| 11 | + |
| 12 | +export default { |
| 13 | + |
| 14 | + // Connection logic injects a connection via `attach`. |
| 15 | + //# Required interface: |
| 16 | + // .message(json) |
| 17 | + //# Optional interface: |
| 18 | + // .stdin(data) |
| 19 | + // .interrupt() |
| 20 | + // .kill() |
| 21 | + |
| 22 | + // Messaging |
| 23 | + |
| 24 | + ipc: new IPC, |
| 25 | + |
| 26 | + handle(...a) { return this.ipc.handle(...Array.from(a || [])); }, |
| 27 | + input(m) { return this.ipc.input(m); }, |
| 28 | + readStream(s) { return this.ipc.readStream(s); }, |
| 29 | + import(...a) { return this.ipc.import(...Array.from(a || [])); }, |
| 30 | + |
| 31 | + activate() { |
| 32 | + |
| 33 | + this.emitter = new Emitter; |
| 34 | + |
| 35 | + this.bootMode = atom.config.get('julia-client.juliaOptions.bootMode'); |
| 36 | + |
| 37 | + this.ipc.writeMsg = msg => { |
| 38 | + if (this.isActive() && ((typeof this.conn.ready === 'function' ? this.conn.ready() : undefined) !== false)) { |
| 39 | + return this.conn.message(msg); |
| 40 | + } else { |
| 41 | + return this.ipc.queue.push(msg); |
| 42 | + } |
| 43 | + }; |
| 44 | + |
| 45 | + this.handle('error', options => { |
| 46 | + if (atom.config.get('julia-client.uiOptions.errorNotifications')) { |
| 47 | + atom.notifications.addError(options.msg, options); |
| 48 | + } |
| 49 | + console.error(options.detail); |
| 50 | + return atom.beep(); |
| 51 | + }); |
| 52 | + |
| 53 | + let plotpane = null; |
| 54 | + |
| 55 | + this.onAttached(() => { |
| 56 | + const args = atom.config.get('julia-client.juliaOptions.arguments'); |
| 57 | + this.import('connected')(); |
| 58 | + if (args.length > 0) { |
| 59 | + this.import('args')(args); |
| 60 | + } |
| 61 | + |
| 62 | + return plotpane = atom.config.observe('julia-client.uiOptions.usePlotPane', use => { |
| 63 | + return this.import('enableplotpane')(use); |
| 64 | + }); |
| 65 | + }); |
| 66 | + |
| 67 | + this.onDetached(() => { |
| 68 | + return (plotpane != null ? plotpane.dispose() : undefined); |
| 69 | + }); |
| 70 | + |
| 71 | + return this.onBoot(proc => { |
| 72 | + return this.remoteConfig = proc.config; |
| 73 | + }); |
| 74 | + }, |
| 75 | + |
| 76 | + setBootMode(bootMode) { |
| 77 | + this.bootMode = bootMode; |
| 78 | + }, |
| 79 | + |
| 80 | + editorPath(ed) { |
| 81 | + if ((ed == null)) { return ed; } |
| 82 | + if ((this.bootMode === 'Remote') && (this.remoteConfig != null)) { |
| 83 | + let path = ed.getPath(); |
| 84 | + if ((path == null)) { return path; } |
| 85 | + const ind = path.indexOf(this.remoteConfig.host); |
| 86 | + if (ind > -1) { |
| 87 | + path = path.slice(ind + this.remoteConfig.host.length, path.length); |
| 88 | + path = path.replace(/\\/g, '/'); |
| 89 | + return path; |
| 90 | + } else { |
| 91 | + return path; |
| 92 | + } |
| 93 | + } else { |
| 94 | + return ed.getPath(); |
| 95 | + } |
| 96 | + }, |
| 97 | + |
| 98 | + deactivate() { |
| 99 | + this.emitter.dispose(); |
| 100 | + if (this.isActive()) { return this.detach(); } |
| 101 | + }, |
| 102 | + |
| 103 | + // Basic handlers (communication through stderr) |
| 104 | + |
| 105 | + basicHandlers: {}, |
| 106 | + |
| 107 | + basicHandler(s) { |
| 108 | + let match; |
| 109 | + if (match = s.toString().match(/juno-msg-(.*)/)) { |
| 110 | + if (typeof this.basicHandlers[match[1]] === 'function') { |
| 111 | + this.basicHandlers[match[1]](); |
| 112 | + } |
| 113 | + return true; |
| 114 | + } |
| 115 | + }, |
| 116 | + |
| 117 | + handleBasic(msg, f) { return this.basicHandlers[msg] = f; }, |
| 118 | + |
| 119 | + // Connecting & Booting |
| 120 | + |
| 121 | + emitter: new Emitter, |
| 122 | + |
| 123 | + onAttached(cb) { return this.emitter.on('attached', cb); }, |
| 124 | + onDetached(cb) { return this.emitter.on('detached', cb); }, |
| 125 | + |
| 126 | + onceAttached(cb) { |
| 127 | + let f; |
| 128 | + return f = this.onAttached(function(...args) { |
| 129 | + f.dispose(); |
| 130 | + return cb.call(this, ...Array.from(args)); |
| 131 | + }); |
| 132 | + }, |
| 133 | + |
| 134 | + isActive() { return (this.conn != null); }, |
| 135 | + |
| 136 | + attach(conn) { |
| 137 | + this.conn = conn; |
| 138 | + if ((typeof this.conn.ready === 'function' ? this.conn.ready() : undefined) !== false) { this.flush(); } |
| 139 | + return this.emitter.emit('attached'); |
| 140 | + }, |
| 141 | + |
| 142 | + detach() { |
| 143 | + delete this.conn; |
| 144 | + this.ipc.reset(); |
| 145 | + return this.emitter.emit('detached'); |
| 146 | + }, |
| 147 | + |
| 148 | + flush() { return this.ipc.flush(); }, |
| 149 | + |
| 150 | + isWorking() { return this.ipc.isWorking(); }, |
| 151 | + onWorking(f) { return this.ipc.onWorking(f); }, |
| 152 | + onDone(f) { return this.ipc.onDone(f); }, |
| 153 | + onceDone(f) { return this.ipc.onceDone(f); }, |
| 154 | + |
| 155 | + // Management & UI |
| 156 | + |
| 157 | + onStdout(f) { return this.emitter.on('stdout', f); }, |
| 158 | + onStderr(f) { return this.emitter.on('stderr', f); }, |
| 159 | + onInfo(f) { return this.emitter.on('info', f); }, |
| 160 | + onBoot(f) { return this.emitter.on('boot', f); }, |
| 161 | + stdout(data) { return this.emitter.emit('stdout', data); }, |
| 162 | + stderr(data) { if (!this.basicHandler(data)) { return this.emitter.emit('stderr', data); } }, |
| 163 | + info(data) { return this.emitter.emit('info', data); }, |
| 164 | + |
| 165 | + clientCall(name, f, ...args) { |
| 166 | + if ((this.conn[f] == null)) { |
| 167 | + return atom.notifications.addError(`This client doesn't support ${name}.`); |
| 168 | + } else { |
| 169 | + return this.conn[f].call(this.conn, ...Array.from(args)); |
| 170 | + } |
| 171 | + }, |
| 172 | + |
| 173 | + stdin(data) { return this.clientCall('STDIN', 'stdin', data); }, |
| 174 | + |
| 175 | + interrupt() { |
| 176 | + if (this.isActive()) { |
| 177 | + return this.clientCall('interrupts', 'interrupt'); |
| 178 | + } |
| 179 | + }, |
| 180 | + |
| 181 | + disconnect() { |
| 182 | + if (this.isActive()) { |
| 183 | + return this.clientCall('disconnecting', 'disconnect'); |
| 184 | + } |
| 185 | + }, |
| 186 | + |
| 187 | + kill() { |
| 188 | + if (this.isActive()) { |
| 189 | + if (!this.isWorking()) { |
| 190 | + return this.import('exit')().catch(function() {}); |
| 191 | + } else { |
| 192 | + return this.clientCall('kill', 'kill'); |
| 193 | + } |
| 194 | + } else { |
| 195 | + return this.ipc.reset(); |
| 196 | + } |
| 197 | + }, |
| 198 | + |
| 199 | + clargs() { |
| 200 | + const {precompiled, optimisationLevel, deprecationWarnings} = |
| 201 | + atom.config.get('julia-client.juliaOptions'); |
| 202 | + let as = []; |
| 203 | + as.push(`--depwarn=${deprecationWarnings ? 'yes' : 'no'}`); |
| 204 | + if (optimisationLevel !== 2) { as.push(`-O${optimisationLevel}`); } |
| 205 | + as.push("--color=yes"); |
| 206 | + as.push("-i"); |
| 207 | + const startupArgs = atom.config.get('julia-client.juliaOptions.startupArguments'); |
| 208 | + if (startupArgs.length > 0) { |
| 209 | + as = as.concat(startupArgs); |
| 210 | + } |
| 211 | + as = as.map(arg => arg.trim()); |
| 212 | + as = as.filter(arg => arg.length > 0); |
| 213 | + return as; |
| 214 | + }, |
| 215 | + |
| 216 | + connectedError(action = 'do that') { |
| 217 | + if (this.isActive()) { |
| 218 | + atom.notifications.addError(`Can't ${action} with a Julia client running.`, |
| 219 | + {description: "Stop the current client with `Packages -> Juno -> Stop Julia`."}); |
| 220 | + return true; |
| 221 | + } else { |
| 222 | + return false; |
| 223 | + } |
| 224 | + }, |
| 225 | + |
| 226 | + notConnectedError(action = 'do that') { |
| 227 | + if (!this.isActive()) { |
| 228 | + atom.notifications.addError(`Can't ${action} without a Julia client running.`, |
| 229 | + {description: "Start a client with `Packages -> Juno -> Start Julia`."}); |
| 230 | + return true; |
| 231 | + } else { |
| 232 | + return false; |
| 233 | + } |
| 234 | + }, |
| 235 | + |
| 236 | + require(a, f) { |
| 237 | + if (f == null) { [a, f] = Array.from([null, a]); } |
| 238 | + return this.notConnectedError(a) || f(); |
| 239 | + }, |
| 240 | + |
| 241 | + disrequire(a, f) { |
| 242 | + if (f == null) { [a, f] = Array.from([null, a]); } |
| 243 | + return this.connectedError(a) || f(); |
| 244 | + }, |
| 245 | + |
| 246 | + withCurrent(f) { |
| 247 | + const current = this.conn; |
| 248 | + return (...a) => { |
| 249 | + if (current !== this.conn) { return; } |
| 250 | + return f(...Array.from(a || [])); |
| 251 | + }; |
| 252 | + } |
| 253 | +}; |
0 commit comments