Closes #164. Auto-detect Shell environment variables
This commit is contained in:
parent
f7939e7d00
commit
240368fb09
|
@ -52,19 +52,21 @@ module.exports = class Beautifier
|
||||||
###
|
###
|
||||||
Create temporary file
|
Create temporary file
|
||||||
###
|
###
|
||||||
tempFile: (name = "atom-beautify-temp", contents) ->
|
tempFile: (name = "atom-beautify-temp", contents = "") ->
|
||||||
return new Promise((resolve, reject) ->
|
return new Promise((resolve, reject) ->
|
||||||
# create temp file
|
# create temp file
|
||||||
temp.open(name, (err, info) ->
|
temp.open(name, (err, info) ->
|
||||||
# console.log(name, info)
|
console.log(name, err, info)
|
||||||
|
return reject(err) if err
|
||||||
|
fs.write(info.fd, contents, (err) ->
|
||||||
return reject(err) if err
|
return reject(err) if err
|
||||||
fs.write(info.fd, contents) if contents?
|
|
||||||
fs.close(info.fd, (err) ->
|
fs.close(info.fd, (err) ->
|
||||||
return reject(err) if err
|
return reject(err) if err
|
||||||
resolve(info.path)
|
resolve(info.path)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
###
|
###
|
||||||
Read file
|
Read file
|
||||||
|
@ -75,50 +77,102 @@ module.exports = class Beautifier
|
||||||
return readFile(filePath, "utf8")
|
return readFile(filePath, "utf8")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
###
|
||||||
|
Get Shell Environment variables
|
||||||
|
|
||||||
|
Special thank you to @ioquatix
|
||||||
|
See https://github.com/ioquatix/script-runner/blob/v1.5.0/lib/script-runner.coffee#L45-L63
|
||||||
|
###
|
||||||
|
_envCache: null
|
||||||
|
_envCacheDate: null
|
||||||
|
_envCacheExpiry: 10000 # 10 seconds
|
||||||
|
getShellEnvironment: ->
|
||||||
|
return new @Promise((resolve, reject) =>
|
||||||
|
# Check Cache
|
||||||
|
if @_envCache? and @_envCacheDate?
|
||||||
|
# Check if Cache is old
|
||||||
|
if (new Date() - @_envCacheDate) < @_envCacheExpiry
|
||||||
|
# Still fresh
|
||||||
|
return resolve(@_envCache)
|
||||||
|
|
||||||
|
# Check if Windows
|
||||||
|
isWin = /^win/.test(process.platform)
|
||||||
|
if isWin
|
||||||
|
# Windows
|
||||||
|
# Use default
|
||||||
|
resolve(process.env)
|
||||||
|
else
|
||||||
|
# Mac & Linux
|
||||||
|
# I tried using ChildProcess.execFile but there is no way to set detached and
|
||||||
|
# this causes the child shell to lock up.
|
||||||
|
# This command runs an interactive login shell and
|
||||||
|
# executes the export command to get a list of environment variables.
|
||||||
|
# We then use these to run the script:
|
||||||
|
child = spawn process.env.SHELL, ['-ilc', 'env'],
|
||||||
|
# This is essential for interactive shells, otherwise it never finishes:
|
||||||
|
detached: true,
|
||||||
|
# We don't care about stdin, stderr can go out the usual way:
|
||||||
|
stdio: ['ignore', 'pipe', process.stderr]
|
||||||
|
# We buffer stdout:
|
||||||
|
buffer = ''
|
||||||
|
child.stdout.on 'data', (data) -> buffer += data
|
||||||
|
# When the process finishes, extract the environment variables and pass them to the callback:
|
||||||
|
child.on 'close', (code, signal) =>
|
||||||
|
if code isnt 0
|
||||||
|
return reject(new Error("Could not get Shell Environment. Exit code: "+code+", Signal: "+signal))
|
||||||
|
environment = {}
|
||||||
|
for definition in buffer.split('\n')
|
||||||
|
[key, value] = definition.split('=', 2)
|
||||||
|
environment[key] = value if key != ''
|
||||||
|
# Cache Environment
|
||||||
|
@_envCache = environment
|
||||||
|
@_envCacheDate = new Date()
|
||||||
|
resolve(environment)
|
||||||
|
)
|
||||||
|
|
||||||
###
|
###
|
||||||
Run command-line interface command
|
Run command-line interface command
|
||||||
###
|
###
|
||||||
run: (executable, args) ->
|
run: (executable, args) ->
|
||||||
console.log('run', arguments)
|
|
||||||
# TODO: Get $PATH
|
|
||||||
# Resolve executable
|
# Resolve executable
|
||||||
Promise.resolve(executable)
|
Promise.resolve(executable)
|
||||||
.then((exe) ->
|
.then((exe) =>
|
||||||
console.log('exe', exe)
|
|
||||||
# Flatten args first
|
# Flatten args first
|
||||||
args = _.flatten(args)
|
args = _.flatten(args)
|
||||||
console.log('flat args', args)
|
|
||||||
# Resolve all args
|
# Resolve all args
|
||||||
Promise.all(args)
|
Promise.all(args)
|
||||||
.then((args) ->
|
.then((args) =>
|
||||||
return new Promise((resolve, reject) ->
|
return new Promise((resolve, reject) =>
|
||||||
console.log('resolved args', args)
|
# Remove undefined/null values
|
||||||
# Remove null values
|
|
||||||
args = _.without(args, undefined)
|
args = _.without(args, undefined)
|
||||||
args = _.without(args, null)
|
args = _.without(args, null)
|
||||||
console.log('args without undefined/null', args)
|
# Get PATH and other environment variables
|
||||||
|
@getShellEnvironment()
|
||||||
|
.then((env) ->
|
||||||
# Spawn command
|
# Spawn command
|
||||||
stdout = ""
|
stdout = ""
|
||||||
stderr = ""
|
stderr = ""
|
||||||
options = {
|
options = {
|
||||||
env: {
|
env: env
|
||||||
PATH: "/Users/glavin/.rvm/gems/ruby-1.9.3-p551/bin:/Users/glavin/.rvm/gems/ruby-1.9.3-p551@global/bin:/Users/glavin/.rvm/rubies/ruby-1.9.3-p551/bin:/Users/glavin/.nvm/v0.10.32/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/texbin:/Developer/android-sdk-macosx/tools:/Developer/android-sdk-macosx/platform-tools:/Users/glavin/pear/bin:/Users/glavin/gocode/bin:/Users/glavin/.rvm/bin"
|
|
||||||
}
|
}
|
||||||
}
|
# console.log('spawn', exe, args)
|
||||||
console.log('spawn', exe, args)
|
|
||||||
cmd = spawn(exe, args, options)
|
cmd = spawn(exe, args, options)
|
||||||
# add a 'data' event listener for the spawn instance
|
# add a 'data' event listener for the spawn instance
|
||||||
cmd.stdout.on('data', (data) -> stdout += data )
|
cmd.stdout.on('data', (data) -> stdout += data )
|
||||||
cmd.stderr.on('data', (data) -> stderr += data )
|
cmd.stderr.on('data', (data) -> stderr += data )
|
||||||
# when the spawn child process exits, check if there were any errors and close the writeable stream
|
# when the spawn child process exits, check if there were any errors and close the writeable stream
|
||||||
cmd.on('exit', (code) ->
|
cmd.on('exit', (code) ->
|
||||||
console.log('spawn done', code, stderr, stdout)
|
# console.log('spawn done', code, stderr, stdout)
|
||||||
# If return code is not 0 then error occured
|
# If return code is not 0 then error occured
|
||||||
if code isnt 0
|
if code isnt 0
|
||||||
reject(stderr)
|
reject(stderr)
|
||||||
else
|
else
|
||||||
resolve(stdout)
|
resolve(stdout)
|
||||||
)
|
)
|
||||||
|
cmd.on('error', (err) ->
|
||||||
|
reject(err)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
###
|
|
||||||
Requires http://pear.php.net/package/PHP_Beautifier
|
|
||||||
###
|
|
||||||
"use strict"
|
|
||||||
fs = require("fs")
|
|
||||||
temp = require("temp").track()
|
|
||||||
exec = require("child_process").exec
|
|
||||||
module.exports = (getCmd, isStdout) ->
|
|
||||||
(text, options, callback) ->
|
|
||||||
|
|
||||||
# Create temp input file
|
|
||||||
temp.open "input", (err, info) ->
|
|
||||||
unless err
|
|
||||||
|
|
||||||
# Save current text to input file
|
|
||||||
fs.write info.fd, text or "", ->
|
|
||||||
fs.close info.fd, (err) ->
|
|
||||||
unless err
|
|
||||||
|
|
||||||
# Create temp output file
|
|
||||||
outputPath = temp.path()
|
|
||||||
deleteOutputFile = ->
|
|
||||||
temp.cleanup()
|
|
||||||
# Delete the output path
|
|
||||||
fs.unlink outputPath, (err) ->
|
|
||||||
# console.log "Deleting output file", err if err
|
|
||||||
return
|
|
||||||
return
|
|
||||||
|
|
||||||
# Process the command
|
|
||||||
processCmd = (cmd, optCallback) ->
|
|
||||||
if optCallback? and typeof optCallback is "function"
|
|
||||||
# console.log('Optional Callback found')
|
|
||||||
cb = callback # Save callback for later
|
|
||||||
callback = (output) -> # Wrap callback (cb) with optCallback
|
|
||||||
# console.log('Callback called!', output)
|
|
||||||
optCallback(output, cb)
|
|
||||||
|
|
||||||
if typeof cmd is "string"
|
|
||||||
|
|
||||||
config = env: process.env
|
|
||||||
isWin = /^win/.test(process.platform)
|
|
||||||
unless isWin
|
|
||||||
|
|
||||||
# We need the $PATH to be correct when executing the command.
|
|
||||||
# This should normalize the $PATH
|
|
||||||
# by calling the external files that would usually
|
|
||||||
# change the $PATH variable on user login.
|
|
||||||
$path = "[ -f ~/.bash_profile ] && source ~/.bash_profile > /dev/null 2>&1;"
|
|
||||||
$path += "[ -f ~/.bashrc ] && source ~/.bashrc > /dev/null 2>&1;"
|
|
||||||
|
|
||||||
# See http://stackoverflow.com/a/638980/2578205
|
|
||||||
# for checking if file exists in Bash
|
|
||||||
cmd = $path + cmd
|
|
||||||
|
|
||||||
# Execute and beautify!
|
|
||||||
exec cmd, config, (err, stdout, stderr) ->
|
|
||||||
|
|
||||||
# console.log(stderr);
|
|
||||||
unless err
|
|
||||||
|
|
||||||
# Beautification has completed
|
|
||||||
if isStdout
|
|
||||||
|
|
||||||
# Execute callback with resulting output text
|
|
||||||
callback stdout
|
|
||||||
deleteOutputFile()
|
|
||||||
else
|
|
||||||
|
|
||||||
# Read contents of output file
|
|
||||||
fs.readFile outputPath, "utf8", (err, newText) ->
|
|
||||||
|
|
||||||
# Execute callback with resulting output text
|
|
||||||
callback newText
|
|
||||||
deleteOutputFile()
|
|
||||||
return
|
|
||||||
|
|
||||||
else
|
|
||||||
console.error "Beautifcation Error: ", err
|
|
||||||
callback err
|
|
||||||
deleteOutputFile()
|
|
||||||
return
|
|
||||||
|
|
||||||
# Check if there's an error
|
|
||||||
else if cmd instanceof Error
|
|
||||||
return callback(cmd)
|
|
||||||
else
|
|
||||||
console.error "CLI Beautifier command not valid."
|
|
||||||
return callback(new Error("CLI Beautifier command not valid."+
|
|
||||||
" Invalid command '#{cmd}'."))
|
|
||||||
|
|
||||||
|
|
||||||
# Get the command
|
|
||||||
try
|
|
||||||
cmd = getCmd(info.path, outputPath, options, processCmd) # jshint ignore: line
|
|
||||||
catch e
|
|
||||||
return callback(e)
|
|
||||||
|
|
||||||
if typeof cmd is "string"
|
|
||||||
processCmd cmd
|
|
||||||
# Check if there's an error
|
|
||||||
else if cmd instanceof Error
|
|
||||||
return callback(cmd)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
return
|
|
|
@ -95,8 +95,6 @@ module.exports = class Beautifiers
|
||||||
# getBeautifiersForExtension: (extension) ->
|
# getBeautifiersForExtension: (extension) ->
|
||||||
|
|
||||||
beautify: (text, allOptions, grammar, filePath) ->
|
beautify: (text, allOptions, grammar, filePath) ->
|
||||||
# console.log(@)
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
|
|
||||||
# Get language
|
# Get language
|
||||||
|
@ -112,15 +110,12 @@ module.exports = class Beautifiers
|
||||||
return resolve(null)
|
return resolve(null)
|
||||||
|
|
||||||
# Options for Language
|
# Options for Language
|
||||||
console.log('allOptions', allOptions)
|
|
||||||
options = @getOptions(language.namespace, allOptions) || {}
|
options = @getOptions(language.namespace, allOptions) || {}
|
||||||
# Support fallback for options
|
# Support fallback for options
|
||||||
if language.fallback?
|
if language.fallback?
|
||||||
for fallback in language.fallback
|
for fallback in language.fallback
|
||||||
# Merge current options on top of fallback options
|
# Merge current options on top of fallback options
|
||||||
console.log(fallback)
|
|
||||||
options = _.merge(@getOptions(fallback, allOptions) || {}, options)
|
options = _.merge(@getOptions(fallback, allOptions) || {}, options)
|
||||||
console.log('options', options)
|
|
||||||
|
|
||||||
# Get Beautifiers
|
# Get Beautifiers
|
||||||
# console.log(grammar, language)
|
# console.log(grammar, language)
|
||||||
|
@ -136,7 +131,6 @@ module.exports = class Beautifiers
|
||||||
|
|
||||||
# Transform options, if applicable
|
# Transform options, if applicable
|
||||||
beautifierOptions = beautifier.options[language.name]
|
beautifierOptions = beautifier.options[language.name]
|
||||||
console.log('beautifierOptions', beautifierOptions)
|
|
||||||
if typeof beautifierOptions is "boolean"
|
if typeof beautifierOptions is "boolean"
|
||||||
if beautifierOptions isnt true
|
if beautifierOptions isnt true
|
||||||
# Disable options
|
# Disable options
|
||||||
|
@ -159,7 +153,6 @@ module.exports = class Beautifiers
|
||||||
options = transformedOptions
|
options = transformedOptions
|
||||||
else
|
else
|
||||||
console.warn("Unsupported Language options: ", beautifierOptions)
|
console.warn("Unsupported Language options: ", beautifierOptions)
|
||||||
console.log('beautify!', beautifier, language, options)
|
|
||||||
beautifier.beautify(text, language.name, options)
|
beautifier.beautify(text, language.name, options)
|
||||||
.then(resolve)
|
.then(resolve)
|
||||||
.catch(reject)
|
.catch(reject)
|
||||||
|
|
Loading…
Reference in New Issue