From 9211a03c16309777183c2fa3a375b1aa7dcddc66 Mon Sep 17 00:00:00 2001 From: Glavin Wiechert Date: Fri, 1 May 2015 02:32:02 -0300 Subject: [PATCH] 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 " 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 --- .../nested-jsbeautifyrc/sql/expected/test.sql | 6 +- .../sql/original/{test.sql => _test.sql} | 0 .../simple-jsbeautifyrc/sql/expected/test.sql | 6 +- .../sql/expected/test2.sql | 4 +- .../sql/original/{test.sql => _test.sql} | 0 .../sql/original/{test2.sql => _test2.sql} | 0 src/beautifiers/autopep8.coffee | 2 + src/beautifiers/beautifier.coffee | 19 ++- src/beautifiers/coffee-formatter.coffee | 2 + src/beautifiers/htmlbeautifier.coffee | 2 +- src/beautifiers/index.coffee | 117 +++++++++++++++++- src/beautifiers/js-beautify.coffee | 3 +- src/beautifiers/perltidy.coffee | 3 +- src/beautifiers/php-cs-fixer.coffee | 3 +- src/beautifiers/prettydiff.coffee | 24 ++-- src/beautifiers/ruby-beautify.coffee | 3 +- src/beautifiers/sqlformat.coffee | 3 +- src/beautifiers/tidy-markdown.coffee | 2 +- src/beautifiers/typescript-formatter.coffee | 2 +- src/beautifiers/uncrustify/index.coffee | 2 +- src/languages/c-sharp.coffee | 3 +- src/languages/cpp.coffee | 2 +- src/languages/css.coffee | 3 +- src/languages/csv.coffee | 23 ++++ src/languages/ejs.coffee | 22 ++++ src/languages/index.coffee | 4 + src/languages/objective-c.coffee | 2 +- src/languages/spacebars.coffee | 22 ++++ src/languages/xml.coffee | 24 ++++ 29 files changed, 270 insertions(+), 38 deletions(-) rename examples/nested-jsbeautifyrc/sql/original/{test.sql => _test.sql} (100%) rename examples/simple-jsbeautifyrc/sql/original/{test.sql => _test.sql} (100%) rename examples/simple-jsbeautifyrc/sql/original/{test2.sql => _test2.sql} (100%) create mode 100644 src/languages/csv.coffee create mode 100644 src/languages/ejs.coffee create mode 100644 src/languages/spacebars.coffee create mode 100644 src/languages/xml.coffee diff --git a/examples/nested-jsbeautifyrc/sql/expected/test.sql b/examples/nested-jsbeautifyrc/sql/expected/test.sql index 9a4aab3..2925130 100644 --- a/examples/nested-jsbeautifyrc/sql/expected/test.sql +++ b/examples/nested-jsbeautifyrc/sql/expected/test.sql @@ -3,7 +3,7 @@ SELECT ca.proj_id AS proj_id, ca.ca_date_start AS proj_start, ca.ca_date_end AS proj_end, - (SELECT COUNT(*) + (SELECT count(*) FROM rotations r WHERE r.proj_id = proj_id AND r.r_status = 'R' @@ -20,6 +20,6 @@ WHERE ca.client_id = 12345 AND ca.client_id = c.client_id AND ca_type = 'zzz' AND c.agency_id = 0 - AND ca.client_id = NVL(caa.client_id, ca.client_id) - AND proj_id = NVL(caa.proj_id, proj_id) + AND ca.client_id = nvl(caa.client_id, ca.client_id) + AND proj_id = nvl(caa.proj_id, proj_id) AND caa.contact_id = 7890 \ No newline at end of file diff --git a/examples/nested-jsbeautifyrc/sql/original/test.sql b/examples/nested-jsbeautifyrc/sql/original/_test.sql similarity index 100% rename from examples/nested-jsbeautifyrc/sql/original/test.sql rename to examples/nested-jsbeautifyrc/sql/original/_test.sql diff --git a/examples/simple-jsbeautifyrc/sql/expected/test.sql b/examples/simple-jsbeautifyrc/sql/expected/test.sql index 9a4aab3..2925130 100644 --- a/examples/simple-jsbeautifyrc/sql/expected/test.sql +++ b/examples/simple-jsbeautifyrc/sql/expected/test.sql @@ -3,7 +3,7 @@ SELECT ca.proj_id AS proj_id, ca.ca_date_start AS proj_start, ca.ca_date_end AS proj_end, - (SELECT COUNT(*) + (SELECT count(*) FROM rotations r WHERE r.proj_id = proj_id AND r.r_status = 'R' @@ -20,6 +20,6 @@ WHERE ca.client_id = 12345 AND ca.client_id = c.client_id AND ca_type = 'zzz' AND c.agency_id = 0 - AND ca.client_id = NVL(caa.client_id, ca.client_id) - AND proj_id = NVL(caa.proj_id, proj_id) + AND ca.client_id = nvl(caa.client_id, ca.client_id) + AND proj_id = nvl(caa.proj_id, proj_id) AND caa.contact_id = 7890 \ No newline at end of file diff --git a/examples/simple-jsbeautifyrc/sql/expected/test2.sql b/examples/simple-jsbeautifyrc/sql/expected/test2.sql index 284de85..871f4f1 100644 --- a/examples/simple-jsbeautifyrc/sql/expected/test2.sql +++ b/examples/simple-jsbeautifyrc/sql/expected/test2.sql @@ -1,4 +1,4 @@ -INSERT INTO client (host, description, created_at) +INSERT INTO client (HOST, description, created_at) VALUES('hallpclnx', 'My linux machine', CURRENT_TIMESTAMP); @@ -25,7 +25,7 @@ VALUES(2, 1); -INSERT INTO client (host, description, created_at) +INSERT INTO client (HOST, description, created_at) VALUES('shedpclnx', 'My shed linux machine', CURRENT_TIMESTAMP); diff --git a/examples/simple-jsbeautifyrc/sql/original/test.sql b/examples/simple-jsbeautifyrc/sql/original/_test.sql similarity index 100% rename from examples/simple-jsbeautifyrc/sql/original/test.sql rename to examples/simple-jsbeautifyrc/sql/original/_test.sql diff --git a/examples/simple-jsbeautifyrc/sql/original/test2.sql b/examples/simple-jsbeautifyrc/sql/original/_test2.sql similarity index 100% rename from examples/simple-jsbeautifyrc/sql/original/test2.sql rename to examples/simple-jsbeautifyrc/sql/original/_test2.sql diff --git a/src/beautifiers/autopep8.coffee b/src/beautifiers/autopep8.coffee index 76bc3de..cac0292 100644 --- a/src/beautifiers/autopep8.coffee +++ b/src/beautifiers/autopep8.coffee @@ -7,6 +7,8 @@ Beautifier = require('./beautifier') module.exports = class autopep8 extends Beautifier + name: "autopep8" + options: { Python: true } diff --git a/src/beautifiers/beautifier.coffee b/src/beautifiers/beautifier.coffee index 36df178..c84a212 100644 --- a/src/beautifiers/beautifier.coffee +++ b/src/beautifiers/beautifier.coffee @@ -26,6 +26,7 @@ module.exports = class Beautifier - :: - :: - :: + - :: ### options: {} @@ -183,8 +184,24 @@ module.exports = class Beautifier Constructor to setup beautifer ### 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 @languages = _.keys(@options) - # TODO: Remove default/catch all key, `_` diff --git a/src/beautifiers/coffee-formatter.coffee b/src/beautifiers/coffee-formatter.coffee index eb8c615..aec4048 100644 --- a/src/beautifiers/coffee-formatter.coffee +++ b/src/beautifiers/coffee-formatter.coffee @@ -3,6 +3,8 @@ Beautifier = require('./beautifier') module.exports = class CoffeeFormatter extends Beautifier + name: "Coffee Formatter" + options: { CoffeeScript: true } diff --git a/src/beautifiers/htmlbeautifier.coffee b/src/beautifiers/htmlbeautifier.coffee index 6c439c4..8cdc10d 100644 --- a/src/beautifiers/htmlbeautifier.coffee +++ b/src/beautifiers/htmlbeautifier.coffee @@ -6,7 +6,7 @@ Requires https://github.com/threedaymonk/htmlbeautifier Beautifier = require('./beautifier') module.exports = class HTMLBeautifier extends Beautifier - + name: "HTML Beautifier" options: { ERB: true } diff --git a/src/beautifiers/index.coffee b/src/beautifiers/index.coffee index 42b8db0..31191d2 100644 --- a/src/beautifiers/index.coffee +++ b/src/beautifiers/index.coffee @@ -1,4 +1,5 @@ _ = require('lodash') +_plus = require('underscore-plus') Promise = require('bluebird') Languages = require('../languages/') path = require('path') @@ -67,17 +68,113 @@ module.exports = class Beautifiers Constructor ### constructor: -> + # Load beautifiers @beautifiers = _.map(@beautifierNames, (name) -> Beautifier = require("./#{name}") new Beautifier() ) + # Build options from @beautifiers and @languages @options = @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] else if typeof op is "function" # Transform - transformedOptions[field] = op(options) + transformedOptions[field] = op(options[field]) else if typeof op is "boolean" # Enable/Disable if op is true 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 options = transformedOptions else console.warn("Unsupported Language options: ", beautifierOptions) return options - # Apply Beautifier / global option transformations - if beautifier.options._? - options = transformOptions(beautifier, "_", options) # Apply language-specific option transformations options = transformOptions(beautifier, language.name, options) @@ -186,10 +289,12 @@ module.exports = class Beautifiers userId: atom.config.get("atom-beautify._analyticsUserId") event: "Beautify" properties: + language: language.name grammar: grammar + extension: fileExtension version: version options: allOptions - label: grammar + label: language.name category: version # if unsupportedGrammar diff --git a/src/beautifiers/js-beautify.coffee b/src/beautifiers/js-beautify.coffee index cd81d31..19e2109 100644 --- a/src/beautifiers/js-beautify.coffee +++ b/src/beautifiers/js-beautify.coffee @@ -2,7 +2,8 @@ Beautifier = require('./beautifier') module.exports = class JSBeautify extends Beautifier - + name: "JS Beautify" + options: { HTML: true Handlebars: true diff --git a/src/beautifiers/perltidy.coffee b/src/beautifiers/perltidy.coffee index 5c62f5f..53427bc 100644 --- a/src/beautifiers/perltidy.coffee +++ b/src/beautifiers/perltidy.coffee @@ -5,7 +5,8 @@ Requires [perltidy](http://perltidy.sourceforge.net) Beautifier = require('./beautifier') module.exports = class PerlTidy extends Beautifier - + name: "Perltidy" + options: { Perl: true } diff --git a/src/beautifiers/php-cs-fixer.coffee b/src/beautifiers/php-cs-fixer.coffee index c602036..b9d04d7 100644 --- a/src/beautifiers/php-cs-fixer.coffee +++ b/src/beautifiers/php-cs-fixer.coffee @@ -6,7 +6,8 @@ Requires https://github.com/FriendsOfPHP/PHP-CS-Fixer Beautifier = require('./beautifier') module.exports = class PHPCSFixer extends Beautifier - + name: "PHP-CS-Fixer" + options: { PHP: true } diff --git a/src/beautifiers/prettydiff.coffee b/src/beautifiers/prettydiff.coffee index 7d911d4..74dae6e 100644 --- a/src/beautifiers/prettydiff.coffee +++ b/src/beautifiers/prettydiff.coffee @@ -4,20 +4,25 @@ Beautifier = require('./beautifier') _ = require('lodash') module.exports = class PrettyDiff extends Beautifier - + name: "Pretty Diff" options: { # Apply these options first / globally, for all languages _: inchar: "indent_char" insize: "indent_size" - alphasort: (options) -> - options.alphasort or false - preserve: (options) -> - if (options.preserve_newlines is true ) then \ + alphasort: (alphasort) -> + alphasort or false + preserve: ['preserve_newlines', (preserve_newlines) -> + if (preserve_newlines is true ) then \ "all" else "none" + ] # Apply language-specific options CSV: true + ERB: true + EJS: true HTML: true + XML: true + Spacebars: true JavaScript: true CSS: true SCSS: true @@ -36,7 +41,10 @@ module.exports = class PrettyDiff extends Beautifier switch language when "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" when "HTML" lang = "html" @@ -46,8 +54,8 @@ module.exports = class PrettyDiff extends Beautifier lang = "css" when "TSS" lang = "tss" - when "Plain text" - lang = "text" + # when "Plain text" + # lang = "text" else lang = "auto" diff --git a/src/beautifiers/ruby-beautify.coffee b/src/beautifiers/ruby-beautify.coffee index 78e1758..4427faa 100644 --- a/src/beautifiers/ruby-beautify.coffee +++ b/src/beautifiers/ruby-beautify.coffee @@ -6,7 +6,8 @@ Requires https://github.com/erniebrodeur/ruby-beautify Beautifier = require('./beautifier') module.exports = class RubyBeautify extends Beautifier - + name: "Ruby Beautify" + options: { Ruby: true } diff --git a/src/beautifiers/sqlformat.coffee b/src/beautifiers/sqlformat.coffee index d0da0a9..fae276b 100644 --- a/src/beautifiers/sqlformat.coffee +++ b/src/beautifiers/sqlformat.coffee @@ -6,7 +6,8 @@ Requires https://github.com/andialbrecht/sqlparse Beautifier = require('./beautifier') module.exports = class sqlformat extends Beautifier - + name: "sqlformat" + options: { SQL: true } diff --git a/src/beautifiers/tidy-markdown.coffee b/src/beautifiers/tidy-markdown.coffee index 0b73662..90188f5 100644 --- a/src/beautifiers/tidy-markdown.coffee +++ b/src/beautifiers/tidy-markdown.coffee @@ -2,7 +2,7 @@ Beautifier = require('./beautifier') module.exports = class TidyMarkdown extends Beautifier - + name: "Tidy Markdown" options: { Markdown: true } diff --git a/src/beautifiers/typescript-formatter.coffee b/src/beautifiers/typescript-formatter.coffee index 0c3de15..c8d62ae 100644 --- a/src/beautifiers/typescript-formatter.coffee +++ b/src/beautifiers/typescript-formatter.coffee @@ -2,7 +2,7 @@ Beautifier = require('./beautifier') module.exports = class TypeScriptFormatter extends Beautifier - + name: "TypeScript Formatter" options: { TypeScript: true } diff --git a/src/beautifiers/uncrustify/index.coffee b/src/beautifiers/uncrustify/index.coffee index 93d541c..afbe785 100644 --- a/src/beautifiers/uncrustify/index.coffee +++ b/src/beautifiers/uncrustify/index.coffee @@ -9,7 +9,7 @@ expandHomeDir = require('expand-home-dir') _ = require('lodash') module.exports = class Uncrustify extends Beautifier - + name: "Uncrustify" options: { C: true "C++": true diff --git a/src/languages/c-sharp.coffee b/src/languages/c-sharp.coffee index c266c7a..b947412 100644 --- a/src/languages/c-sharp.coffee +++ b/src/languages/c-sharp.coffee @@ -2,7 +2,6 @@ module.exports = { name: "C#" namespace: "cs" - fallback: [] ### Supported Grammars @@ -20,7 +19,7 @@ module.exports = { options: configPath: - title: "C# Config Path" + title: "Config Path" type: 'string' default: "" description: "Path to uncrustify config file. i.e. uncrustify.cfg" diff --git a/src/languages/cpp.coffee b/src/languages/cpp.coffee index 5e742a1..80a4709 100644 --- a/src/languages/cpp.coffee +++ b/src/languages/cpp.coffee @@ -28,7 +28,7 @@ module.exports = { options: configPath: - title: "C++ Config Path" + title: "Config Path" type: 'string' default: "" description: "Path to uncrustify config file. i.e. uncrustify.cfg" diff --git a/src/languages/css.coffee b/src/languages/css.coffee index 1cee7c6..5157264 100644 --- a/src/languages/css.coffee +++ b/src/languages/css.coffee @@ -47,8 +47,7 @@ module.exports = { preserve_newlines: type: 'boolean' default: false - description: "(Only LESS/SASS/SCSS with Prettydiff) "+ - "Retain empty lines. "+ + description: "Retain empty lines. "+ "Consecutive empty lines will be converted to a single empty line." } \ No newline at end of file diff --git a/src/languages/csv.coffee b/src/languages/csv.coffee new file mode 100644 index 0000000..a05dac3 --- /dev/null +++ b/src/languages/csv.coffee @@ -0,0 +1,23 @@ +module.exports = { + + name: "CSV" + description: "Comma-Separated Values" + namespace: "csv" + + ### + Supported Grammars + ### + grammars: [ + "CSV" + ] + + ### + Supported extensions + ### + extensions: [ + 'csv' + ] + + options: [] + +} \ No newline at end of file diff --git a/src/languages/ejs.coffee b/src/languages/ejs.coffee new file mode 100644 index 0000000..0724e25 --- /dev/null +++ b/src/languages/ejs.coffee @@ -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: [] + +} \ No newline at end of file diff --git a/src/languages/index.coffee b/src/languages/index.coffee index 4d81432..1f2fa08 100644 --- a/src/languages/index.coffee +++ b/src/languages/index.coffee @@ -24,7 +24,9 @@ module.exports = class Languages "coffeescript" "cpp" "css" + "csv" "d" + "ejs" "erb" "handlebars" "html" @@ -44,10 +46,12 @@ module.exports = class Languages "ruby" "sass" "scss" + "spacebars" "sql" "tss" "typescript" "vala" + "xml" ] ### diff --git a/src/languages/objective-c.coffee b/src/languages/objective-c.coffee index e4c3180..f66f90e 100644 --- a/src/languages/objective-c.coffee +++ b/src/languages/objective-c.coffee @@ -23,7 +23,7 @@ module.exports = { options: configPath: - title: "Objective-C Config Path" + title: "Config Path" type: 'string' default: "" description: "Path to uncrustify config file. i.e. uncrustify.cfg" diff --git a/src/languages/spacebars.coffee b/src/languages/spacebars.coffee new file mode 100644 index 0000000..b7a6113 --- /dev/null +++ b/src/languages/spacebars.coffee @@ -0,0 +1,22 @@ +module.exports = { + + name: "Spacebars" + description: "Spacebars" + namespace: "spacebars" + fallback: ['html'] + + ### + Supported Grammars + ### + grammars: [ + "Spacebars" + ] + + ### + Supported extensions + ### + extensions: [] + + options: [] + +} \ No newline at end of file diff --git a/src/languages/xml.coffee b/src/languages/xml.coffee new file mode 100644 index 0000000..b226530 --- /dev/null +++ b/src/languages/xml.coffee @@ -0,0 +1,24 @@ +module.exports = { + + name: "XML" + description: "XML" + namespace: "xml" + fallback: ['html'] + + ### + Supported Grammars + ### + grammars: [ + "XML" + ] + + ### + Supported extensions + ### + extensions: [ + 'xml' + ] + + options: [] + +} \ No newline at end of file