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
|
||||
###
|
||||
tempFile: (name = "atom-beautify-temp", contents) ->
|
||||
tempFile: (name = "atom-beautify-temp", contents = "") ->
|
||||
return new Promise((resolve, reject) ->
|
||||
# create temp file
|
||||
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
|
||||
fs.write(info.fd, contents) if contents?
|
||||
fs.close(info.fd, (err) ->
|
||||
return reject(err) if err
|
||||
resolve(info.path)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
###
|
||||
Read file
|
||||
|
@ -75,50 +77,102 @@ module.exports = class Beautifier
|
|||
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: (executable, args) ->
|
||||
console.log('run', arguments)
|
||||
# TODO: Get $PATH
|
||||
# Resolve executable
|
||||
Promise.resolve(executable)
|
||||
.then((exe) ->
|
||||
console.log('exe', exe)
|
||||
.then((exe) =>
|
||||
# Flatten args first
|
||||
args = _.flatten(args)
|
||||
console.log('flat args', args)
|
||||
# Resolve all args
|
||||
Promise.all(args)
|
||||
.then((args) ->
|
||||
return new Promise((resolve, reject) ->
|
||||
console.log('resolved args', args)
|
||||
# Remove null values
|
||||
.then((args) =>
|
||||
return new Promise((resolve, reject) =>
|
||||
# Remove undefined/null values
|
||||
args = _.without(args, undefined)
|
||||
args = _.without(args, null)
|
||||
console.log('args without undefined/null', args)
|
||||
# Get PATH and other environment variables
|
||||
@getShellEnvironment()
|
||||
.then((env) ->
|
||||
# Spawn command
|
||||
stdout = ""
|
||||
stderr = ""
|
||||
options = {
|
||||
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"
|
||||
env: env
|
||||
}
|
||||
}
|
||||
console.log('spawn', exe, args)
|
||||
# console.log('spawn', exe, args)
|
||||
cmd = spawn(exe, args, options)
|
||||
# add a 'data' event listener for the spawn instance
|
||||
cmd.stdout.on('data', (data) -> stdout += 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
|
||||
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 code isnt 0
|
||||
reject(stderr)
|
||||
else
|
||||
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) ->
|
||||
|
||||
beautify: (text, allOptions, grammar, filePath) ->
|
||||
# console.log(@)
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
|
||||
# Get language
|
||||
|
@ -112,15 +110,12 @@ module.exports = class Beautifiers
|
|||
return resolve(null)
|
||||
|
||||
# Options for Language
|
||||
console.log('allOptions', allOptions)
|
||||
options = @getOptions(language.namespace, allOptions) || {}
|
||||
# Support fallback for options
|
||||
if language.fallback?
|
||||
for fallback in language.fallback
|
||||
# Merge current options on top of fallback options
|
||||
console.log(fallback)
|
||||
options = _.merge(@getOptions(fallback, allOptions) || {}, options)
|
||||
console.log('options', options)
|
||||
|
||||
# Get Beautifiers
|
||||
# console.log(grammar, language)
|
||||
|
@ -136,7 +131,6 @@ module.exports = class Beautifiers
|
|||
|
||||
# Transform options, if applicable
|
||||
beautifierOptions = beautifier.options[language.name]
|
||||
console.log('beautifierOptions', beautifierOptions)
|
||||
if typeof beautifierOptions is "boolean"
|
||||
if beautifierOptions isnt true
|
||||
# Disable options
|
||||
|
@ -159,7 +153,6 @@ module.exports = class Beautifiers
|
|||
options = transformedOptions
|
||||
else
|
||||
console.warn("Unsupported Language options: ", beautifierOptions)
|
||||
console.log('beautify!', beautifier, language, options)
|
||||
beautifier.beautify(text, language.name, options)
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
|
|
Loading…
Reference in New Issue