-
Notifications
You must be signed in to change notification settings - Fork 12
/
helpers.js
114 lines (99 loc) · 3.58 KB
/
helpers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
'use babel'
/* @flow */
import FS from 'fs'
import Temp from 'tmp'
import promisify from 'sb-promisify'
import type { TextEditor, Range } from 'atom'
import type { TempDirectory } from './types'
export const writeFile = promisify(FS.writeFile)
export const unlinkFile = promisify(FS.unlink)
function escapeRegexp(string: string): string {
// Shamelessly stolen from https://github.com/atom/underscore-plus/blob/130913c179fe1d718a14034f4818adaf8da4db12/src/underscore-plus.coffee#L138
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
}
export function getWordRegexp(textEditor: TextEditor, bufferPosition: Range) {
const scopeDescriptor = textEditor.scopeDescriptorForBufferPosition(bufferPosition)
const nonWordCharacters = escapeRegexp(atom.config.get('editor.nonWordCharacters', {
scope: scopeDescriptor,
}))
return new RegExp(`^[\t ]*$|[^\\s${nonWordCharacters}]+`)
}
export function getTempDirectory(prefix: string): Promise<TempDirectory> {
return new Promise(function (resolve, reject) {
Temp.dir({ prefix }, function (error, directory, cleanup) {
if (error) {
reject(error)
} else resolve({ path: directory, cleanup })
})
})
}
export function fileExists(filePath: string): Promise<boolean> {
return new Promise(function (resolve) {
FS.access(filePath, FS.R_OK, function (error) {
resolve(error === null)
})
})
}
export function validateExec(command: string, args: Array<string>, options: Object) {
if (typeof command !== 'string') {
throw new Error('Invalid or no `command` provided')
} else if (!(args instanceof Array)) {
throw new Error('Invalid or no `args` provided')
} else if (typeof options !== 'object') {
throw new Error('Invalid or no `options` provided')
}
}
export function validateEditor(editor: TextEditor) {
let isEditor
if (typeof atom.workspace.isTextEditor === 'function') {
// Added in Atom v1.4.0
isEditor = atom.workspace.isTextEditor(editor)
} else {
isEditor = typeof editor.getText === 'function'
}
if (!isEditor) {
throw new Error('Invalid TextEditor provided')
}
}
export function validateFind(directory: string, name: string | Array<string>) {
if (typeof directory !== 'string') {
throw new Error('Invalid or no `directory` provided')
} else if (typeof name !== 'string' && !(name instanceof Array)) {
throw new Error('Invalid or no `name` provided')
}
}
const processMap: Map<string, Function> = new Map()
export function wrapExec(callback: Function): Function {
return function(filePath: string, parameters: Array<string>, options: Object = {}) {
let killed = false
const spawned = callback(filePath, parameters, Object.assign({ timeout: 10000 }, options))
let mirror = spawned
if (options.uniqueKey) {
if (typeof options.uniqueKey !== 'string') throw new Error('options.uniqueKey must be a string')
const oldValue = processMap.get(options.uniqueKey)
if (oldValue) {
oldValue()
}
processMap.set(options.uniqueKey, function() {
killed = true
spawned.kill()
})
mirror = mirror.then(function(value) {
if (killed) return null
return value
}, function(error) {
if (killed) return null
throw error
})
}
return mirror.catch(function(error) {
if (error.code === 'ENOENT') {
const newError = new Error(`Failed to spawn command \`${error.path}\`. Make sure \`${error.path}\` is installed and on your PATH`)
// $FlowIgnore: Custom property
newError.code = 'ENOENT'
throw newError
}
throw error
})
}
}