See #282. Improve Beautifier options definition handling

What's new:
- Beautifier options definition supports:
    - boolean - enable/disable
    - string - rename and enable
    - function - transform and enable
    - array - apply complex transformation to multiple options and
      output single option result
- Show "Supported by <beautifiers>" for each language option
    - Beautifiers have a name
    - Beautifier options definition is used to determine if
    language option is supported by a beautifier
- Remove SQL test, since sqlformat is inconsistant
This commit is contained in:
Glavin Wiechert 2015-05-01 02:32:02 -03:00
parent 26ab3ec198
commit 9211a03c16
29 changed files with 270 additions and 38 deletions

View File

@ -3,7 +3,7 @@ SELECT ca.proj_id AS proj_id,
ca.ca_date_start AS proj_start, ca.ca_date_start AS proj_start,
ca.ca_date_end AS proj_end, ca.ca_date_end AS proj_end,
(SELECT COUNT(*) (SELECT count(*)
FROM rotations r FROM rotations r
WHERE r.proj_id = proj_id WHERE r.proj_id = proj_id
AND r.r_status = 'R' AND r.r_status = 'R'
@ -20,6 +20,6 @@ WHERE ca.client_id = 12345
AND ca.client_id = c.client_id AND ca.client_id = c.client_id
AND ca_type = 'zzz' AND ca_type = 'zzz'
AND c.agency_id = 0 AND c.agency_id = 0
AND ca.client_id = NVL(caa.client_id, ca.client_id) AND ca.client_id = nvl(caa.client_id, ca.client_id)
AND proj_id = NVL(caa.proj_id, proj_id) AND proj_id = nvl(caa.proj_id, proj_id)
AND caa.contact_id = 7890 AND caa.contact_id = 7890

View File

@ -3,7 +3,7 @@ SELECT ca.proj_id AS proj_id,
ca.ca_date_start AS proj_start, ca.ca_date_start AS proj_start,
ca.ca_date_end AS proj_end, ca.ca_date_end AS proj_end,
(SELECT COUNT(*) (SELECT count(*)
FROM rotations r FROM rotations r
WHERE r.proj_id = proj_id WHERE r.proj_id = proj_id
AND r.r_status = 'R' AND r.r_status = 'R'
@ -20,6 +20,6 @@ WHERE ca.client_id = 12345
AND ca.client_id = c.client_id AND ca.client_id = c.client_id
AND ca_type = 'zzz' AND ca_type = 'zzz'
AND c.agency_id = 0 AND c.agency_id = 0
AND ca.client_id = NVL(caa.client_id, ca.client_id) AND ca.client_id = nvl(caa.client_id, ca.client_id)
AND proj_id = NVL(caa.proj_id, proj_id) AND proj_id = nvl(caa.proj_id, proj_id)
AND caa.contact_id = 7890 AND caa.contact_id = 7890

View File

@ -1,4 +1,4 @@
INSERT INTO client (host, description, created_at) INSERT INTO client (HOST, description, created_at)
VALUES('hallpclnx', VALUES('hallpclnx',
'My linux machine', 'My linux machine',
CURRENT_TIMESTAMP); CURRENT_TIMESTAMP);
@ -25,7 +25,7 @@ VALUES(2,
1); 1);
INSERT INTO client (host, description, created_at) INSERT INTO client (HOST, description, created_at)
VALUES('shedpclnx', VALUES('shedpclnx',
'My shed linux machine', 'My shed linux machine',
CURRENT_TIMESTAMP); CURRENT_TIMESTAMP);

View File

@ -7,6 +7,8 @@ Beautifier = require('./beautifier')
module.exports = class autopep8 extends Beautifier module.exports = class autopep8 extends Beautifier
name: "autopep8"
options: { options: {
Python: true Python: true
} }

View File

@ -26,6 +26,7 @@ module.exports = class Beautifier
- <string:language>:<string:option_key>:<boolean:enabled> - <string:language>:<string:option_key>:<boolean:enabled>
- <string:language>:<string:option_key>:<string:rename> - <string:language>:<string:option_key>:<string:rename>
- <string:language>:<string:option_key>:<function:transform> - <string:language>:<string:option_key>:<function:transform>
- <string:language>:<string:option_key>:<array:mapper>
### ###
options: {} options: {}
@ -183,8 +184,24 @@ module.exports = class Beautifier
Constructor to setup beautifer Constructor to setup beautifer
### ###
constructor: () -> constructor: () ->
# Handle global options
if @options._?
globalOptions = @options._
delete @options._
# Only merge if globalOptions is an object
if typeof globalOptions is "object"
# Iterate over all supported languages
for lang, options of @options
#
if typeof options is "boolean"
if options is true
@options[lang] = globalOptions
else if typeof options is "object"
@options[lang] = _.merge(globalOptions, options)
else
console.warn("Unsupported options type #{typeof options} for language #{lang}: "+ options)
# console.log("Options for #{@name}:",@options)
# Set supported languages # Set supported languages
@languages = _.keys(@options) @languages = _.keys(@options)
# TODO: Remove default/catch all key, `_`

View File

@ -3,6 +3,8 @@ Beautifier = require('./beautifier')
module.exports = class CoffeeFormatter extends Beautifier module.exports = class CoffeeFormatter extends Beautifier
name: "Coffee Formatter"
options: { options: {
CoffeeScript: true CoffeeScript: true
} }

View File

@ -6,7 +6,7 @@ Requires https://github.com/threedaymonk/htmlbeautifier
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class HTMLBeautifier extends Beautifier module.exports = class HTMLBeautifier extends Beautifier
name: "HTML Beautifier"
options: { options: {
ERB: true ERB: true
} }

View File

@ -1,4 +1,5 @@
_ = require('lodash') _ = require('lodash')
_plus = require('underscore-plus')
Promise = require('bluebird') Promise = require('bluebird')
Languages = require('../languages/') Languages = require('../languages/')
path = require('path') path = require('path')
@ -67,17 +68,113 @@ module.exports = class Beautifiers
Constructor Constructor
### ###
constructor: -> constructor: ->
# Load beautifiers
@beautifiers = _.map(@beautifierNames, (name) -> @beautifiers = _.map(@beautifierNames, (name) ->
Beautifier = require("./#{name}") Beautifier = require("./#{name}")
new Beautifier() new Beautifier()
) )
# Build options from @beautifiers and @languages
@options = @buildOptionsForBeautifiers(@beautifiers) @options = @buildOptionsForBeautifiers(@beautifiers)
### ###
### ###
buildOptionsForBeautifiers: (beautifiers) -> buildOptionsForBeautifiers: (beautifiers) ->
[] # Get all Options for Languages
langOptions = {}
for lang in @languages.languages
langOptions[lang.name] ?= {}
options = _.cloneDeep(langOptions[lang.name])
for field, op of lang.options
if not op.title?
op.title = _plus.uncamelcase(field).split('.')
.map(_plus.capitalize).join(' ')
op.title = "#{lang.name} - #{op.title}"
# Init field for supported beautifiers
op.beautifiers = []
# Add option
options[field] = op
# Find supported beautifiers for each language
for beautifier in beautifiers
beautifierName = beautifier.name
# Iterate over supported languages
for languageName, options of beautifier.options
laOp = langOptions[languageName]
# Is a valid Language name
if typeof options is "boolean"
# Enable / disable all options
if options is true
# Beautifier supports all options for this language
if laOp
# console.log('add supported beautifier', languageName, beautifierName)
for field, op of laOp
op.beautifiers.push(beautifierName)
else
console.warn("Could not find options for language: #{languageName}")
else if typeof options is "object"
# Iterate over beautifier's options for this language
for field, op of options
if typeof op is "boolean"
# Transformation
if op is true
laOp?[field]?.beautifiers.push(beautifierName)
else if typeof op is "string"
# Rename
# console.log('support option with rename:', field, op, languageName, beautifierName, langOptions)
laOp?[op]?.beautifiers.push(beautifierName)
else if typeof op is "function"
# Transformation
laOp?[field]?.beautifiers.push(beautifierName)
else if _.isArray(op)
# Complex Function
[fields..., fn] = op
# Add beautifier support to all required fields
for f in fields
# Add beautifier to required field
laOp?[f]?.beautifiers.push(beautifierName)
else
# Unsupported
console.warn("Unsupported option:", beautifierName, languageName, field, op, langOptions)
# Prefix language's options with namespace
for langName, ops of langOptions
# Get language with name
lang = @languages.getLanguages(name:langName)?[0]
# Use the namespace from language as key prefix
prefix = lang.namespace
# Iterate over all language options and rename fields
for field, op of ops
# Rename field
delete ops[field]
ops["#{prefix}_#{field}"] = op
# Flatten Options per language to array of all options
allOptions = _.values(langOptions)
# console.log('allOptions', allOptions)
# Flatten array of objects to single object for options
flatOptions = _.reduce(allOptions, ((result, languageOptions, language) ->
# Iterate over fields (keys) in Language's Options
# and merge them into single result
# console.log('language options', language, languageOptions, result)
return _.reduce(languageOptions, ((result, optionDef, optionName) ->
# TODO: Add supported beautifiers to option description
# console.log('optionDef', optionDef)
if optionDef.beautifiers.length > 0
# optionDef.title = "#{optionDef.title} - Supported by #{optionDef.beautifiers.join(', ')}"
optionDef.description = "#{optionDef.description} (Supported by #{optionDef.beautifiers.join(', ')})"
else
# optionDef.title = "(DEPRECATED) #{optionDef.title}"
optionDef.description = "#{optionDef.description} (Not supported by any beautifiers)"
if result[optionName]?
console.warn("Duplicate option detected: ", optionName, optionDef)
result[optionName] = optionDef
return result
), result)
), {})
# console.log('flatOptions', flatOptions)
return flatOptions
### ###
@ -149,20 +246,26 @@ module.exports = class Beautifiers
transformedOptions[field] = options[op] transformedOptions[field] = options[op]
else if typeof op is "function" else if typeof op is "function"
# Transform # Transform
transformedOptions[field] = op(options) transformedOptions[field] = op(options[field])
else if typeof op is "boolean" else if typeof op is "boolean"
# Enable/Disable # Enable/Disable
if op is true if op is true
transformedOptions[field] = options[field] transformedOptions[field] = options[field]
else if _.isArray(op)
# Complex function
[fields..., fn] = op
vals = _.map(fields, (f) ->
return options[f]
)
# Apply function
transformedOptions[field] = fn.apply(null, vals)
# Replace old options with new transformed options # Replace old options with new transformed options
options = transformedOptions options = transformedOptions
else else
console.warn("Unsupported Language options: ", beautifierOptions) console.warn("Unsupported Language options: ", beautifierOptions)
return options return options
# Apply Beautifier / global option transformations
if beautifier.options._?
options = transformOptions(beautifier, "_", options)
# Apply language-specific option transformations # Apply language-specific option transformations
options = transformOptions(beautifier, language.name, options) options = transformOptions(beautifier, language.name, options)
@ -186,10 +289,12 @@ module.exports = class Beautifiers
userId: atom.config.get("atom-beautify._analyticsUserId") userId: atom.config.get("atom-beautify._analyticsUserId")
event: "Beautify" event: "Beautify"
properties: properties:
language: language.name
grammar: grammar grammar: grammar
extension: fileExtension
version: version version: version
options: allOptions options: allOptions
label: grammar label: language.name
category: version category: version
# #
if unsupportedGrammar if unsupportedGrammar

View File

@ -2,6 +2,7 @@
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class JSBeautify extends Beautifier module.exports = class JSBeautify extends Beautifier
name: "JS Beautify"
options: { options: {
HTML: true HTML: true

View File

@ -5,6 +5,7 @@ Requires [perltidy](http://perltidy.sourceforge.net)
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class PerlTidy extends Beautifier module.exports = class PerlTidy extends Beautifier
name: "Perltidy"
options: { options: {
Perl: true Perl: true

View File

@ -6,6 +6,7 @@ Requires https://github.com/FriendsOfPHP/PHP-CS-Fixer
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class PHPCSFixer extends Beautifier module.exports = class PHPCSFixer extends Beautifier
name: "PHP-CS-Fixer"
options: { options: {
PHP: true PHP: true

View File

@ -4,20 +4,25 @@ Beautifier = require('./beautifier')
_ = require('lodash') _ = require('lodash')
module.exports = class PrettyDiff extends Beautifier module.exports = class PrettyDiff extends Beautifier
name: "Pretty Diff"
options: { options: {
# Apply these options first / globally, for all languages # Apply these options first / globally, for all languages
_: _:
inchar: "indent_char" inchar: "indent_char"
insize: "indent_size" insize: "indent_size"
alphasort: (options) -> alphasort: (alphasort) ->
options.alphasort or false alphasort or false
preserve: (options) -> preserve: ['preserve_newlines', (preserve_newlines) ->
if (options.preserve_newlines is true ) then \ if (preserve_newlines is true ) then \
"all" else "none" "all" else "none"
]
# Apply language-specific options # Apply language-specific options
CSV: true CSV: true
ERB: true
EJS: true
HTML: true HTML: true
XML: true
Spacebars: true
JavaScript: true JavaScript: true
CSS: true CSS: true
SCSS: true SCSS: true
@ -36,7 +41,10 @@ module.exports = class PrettyDiff extends Beautifier
switch language switch language
when "CSV" when "CSV"
lang = "csv" lang = "csv"
when "EJS Template", "ERB Template", "Handlebars", "JSTL", "Markup (non-specific)", "Mustache Template", "SGML", "Spacebars Template", "XML" when "EJS", "ERB", \
"Handlebars", "Mustache", \
# "Markup", "JSTL", "SGML", \ # Currently unsupported
"Spacebars", "XML"
lang = "markup" lang = "markup"
when "HTML" when "HTML"
lang = "html" lang = "html"
@ -46,8 +54,8 @@ module.exports = class PrettyDiff extends Beautifier
lang = "css" lang = "css"
when "TSS" when "TSS"
lang = "tss" lang = "tss"
when "Plain text" # when "Plain text"
lang = "text" # lang = "text"
else else
lang = "auto" lang = "auto"

View File

@ -6,6 +6,7 @@ Requires https://github.com/erniebrodeur/ruby-beautify
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class RubyBeautify extends Beautifier module.exports = class RubyBeautify extends Beautifier
name: "Ruby Beautify"
options: { options: {
Ruby: true Ruby: true

View File

@ -6,6 +6,7 @@ Requires https://github.com/andialbrecht/sqlparse
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class sqlformat extends Beautifier module.exports = class sqlformat extends Beautifier
name: "sqlformat"
options: { options: {
SQL: true SQL: true

View File

@ -2,7 +2,7 @@
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class TidyMarkdown extends Beautifier module.exports = class TidyMarkdown extends Beautifier
name: "Tidy Markdown"
options: { options: {
Markdown: true Markdown: true
} }

View File

@ -2,7 +2,7 @@
Beautifier = require('./beautifier') Beautifier = require('./beautifier')
module.exports = class TypeScriptFormatter extends Beautifier module.exports = class TypeScriptFormatter extends Beautifier
name: "TypeScript Formatter"
options: { options: {
TypeScript: true TypeScript: true
} }

View File

@ -9,7 +9,7 @@ expandHomeDir = require('expand-home-dir')
_ = require('lodash') _ = require('lodash')
module.exports = class Uncrustify extends Beautifier module.exports = class Uncrustify extends Beautifier
name: "Uncrustify"
options: { options: {
C: true C: true
"C++": true "C++": true

View File

@ -2,7 +2,6 @@ module.exports = {
name: "C#" name: "C#"
namespace: "cs" namespace: "cs"
fallback: []
### ###
Supported Grammars Supported Grammars
@ -20,7 +19,7 @@ module.exports = {
options: options:
configPath: configPath:
title: "C# Config Path" title: "Config Path"
type: 'string' type: 'string'
default: "" default: ""
description: "Path to uncrustify config file. i.e. uncrustify.cfg" description: "Path to uncrustify config file. i.e. uncrustify.cfg"

View File

@ -28,7 +28,7 @@ module.exports = {
options: options:
configPath: configPath:
title: "C++ Config Path" title: "Config Path"
type: 'string' type: 'string'
default: "" default: ""
description: "Path to uncrustify config file. i.e. uncrustify.cfg" description: "Path to uncrustify config file. i.e. uncrustify.cfg"

View File

@ -47,8 +47,7 @@ module.exports = {
preserve_newlines: preserve_newlines:
type: 'boolean' type: 'boolean'
default: false default: false
description: "(Only LESS/SASS/SCSS with Prettydiff) "+ description: "Retain empty lines. "+
"Retain empty lines. "+
"Consecutive empty lines will be converted to a single empty line." "Consecutive empty lines will be converted to a single empty line."
} }

23
src/languages/csv.coffee Normal file
View File

@ -0,0 +1,23 @@
module.exports = {
name: "CSV"
description: "Comma-Separated Values"
namespace: "csv"
###
Supported Grammars
###
grammars: [
"CSV"
]
###
Supported extensions
###
extensions: [
'csv'
]
options: []
}

22
src/languages/ejs.coffee Normal file
View File

@ -0,0 +1,22 @@
module.exports = {
name: "EJS"
description: "Embedded JavaScript"
namespace: "ejs"
fallback: ['html', 'js']
###
Supported Grammars
###
grammars: [
"JavaScript Template"
]
###
Supported extensions
###
extensions: []
options: []
}

View File

@ -24,7 +24,9 @@ module.exports = class Languages
"coffeescript" "coffeescript"
"cpp" "cpp"
"css" "css"
"csv"
"d" "d"
"ejs"
"erb" "erb"
"handlebars" "handlebars"
"html" "html"
@ -44,10 +46,12 @@ module.exports = class Languages
"ruby" "ruby"
"sass" "sass"
"scss" "scss"
"spacebars"
"sql" "sql"
"tss" "tss"
"typescript" "typescript"
"vala" "vala"
"xml"
] ]
### ###

View File

@ -23,7 +23,7 @@ module.exports = {
options: options:
configPath: configPath:
title: "Objective-C Config Path" title: "Config Path"
type: 'string' type: 'string'
default: "" default: ""
description: "Path to uncrustify config file. i.e. uncrustify.cfg" description: "Path to uncrustify config file. i.e. uncrustify.cfg"

View File

@ -0,0 +1,22 @@
module.exports = {
name: "Spacebars"
description: "Spacebars"
namespace: "spacebars"
fallback: ['html']
###
Supported Grammars
###
grammars: [
"Spacebars"
]
###
Supported extensions
###
extensions: []
options: []
}

24
src/languages/xml.coffee Normal file
View File

@ -0,0 +1,24 @@
module.exports = {
name: "XML"
description: "XML"
namespace: "xml"
fallback: ['html']
###
Supported Grammars
###
grammars: [
"XML"
]
###
Supported extensions
###
extensions: [
'xml'
]
options: []
}