diff --git a/package.json b/package.json index d613653..0b54653 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "event-kit": "^1.2.0", "expand-home-dir": "0.0.2", "extend": "^2.0.1", + "gherkin": "2.12.2", "handlebars": "^3.0.3", "js-beautify": "^1.5.7", "jscs": "^1.13.1", diff --git a/src/beautifiers/gherkin.coffee b/src/beautifiers/gherkin.coffee new file mode 100644 index 0000000..7717c0b --- /dev/null +++ b/src/beautifiers/gherkin.coffee @@ -0,0 +1,129 @@ +### +### + +"use strict" +Beautifier = require('./beautifier') +Lexer = require('gherkin').Lexer('en') +logger = require('../logger')(__filename) + +module.exports = class Gherkin extends Beautifier + name: "Gherkin formatter" + + options: { + gherkin: true + } + + beautify: (text, language, options) -> + return new @Promise((resolve, reject) -> + recorder = { + lines: [] + tags: [] + comments: [] + + last_obj: null + + indent_to: (indent_level = 0) -> + return options.indent_char.repeat(options.indent_size * indent_level) + + write_blank: () -> + @lines.push('') + + write_indented: (content, indent = 0) -> + for line in content.trim().split("\n") + @lines.push("#{@indent_to(indent)}#{line.trim()}") + + write_comments: (indent = 0) -> + for comment in @comments.splice(0, @comments.length) + @write_indented(comment, indent) + + write_tags: (indent = 0) -> + for tag in @tags.splice(0, @tags.length) + @write_indented(tag, indent) + + comment: (value, line) -> + logger.verbose({token: 'comment', value: value.trim(), line: line}) + @comments.push(value) + + tag: (value, line) -> + logger.verbose({token: 'tag', value: value, line: line}) + @tags.push(value) + + feature: (keyword, name, description, line) -> + logger.verbose({token: 'feature', keyword: keyword, name: name, description: description, line: line}) + + @write_comments(0) + @write_tags(0) + @write_indented("#{keyword}: #{name}", '') + @write_indented(description, 1) if description + + background: (keyword, name, description, line) -> + logger.verbose({token: 'background', keyword: keyword, name: name, description: description, line: line}) + + @write_blank() + @write_comments(1) + @write_indented("#{keyword}: #{name}", 1) + @write_indented(description, 2) if description + + scenario: (keyword, name, description, line) -> + logger.verbose({token: 'scenario', keyword: keyword, name: name, description: description, line: line}) + + @write_blank() + @write_comments(1) + @write_tags(1) + @write_indented("#{keyword}: #{name}", 1) + @write_indented(description, 2) if description + + scenario_outline: (keyword, name, description, line) -> + logger.verbose({token: 'outline', keyword: keyword, name: name, description: description, line: line}) + + @write_blank() + @write_comments(1) + @write_tags(1) + @write_indented("#{keyword}: #{name}", 1) + @write_indented(description, 2) if description + + examples: (keyword, name, description, line) -> + logger.verbose({token: 'examples', keyword: keyword, name: name, description: description, line: line}) + + @write_blank() + @write_comments(2) + @write_tags(2) + @write_indented("#{keyword}: #{name}", 2) + @write_indented(description, 3) if description + + step: (keyword, name, line) -> + logger.verbose({token: 'step', keyword: keyword, name: name, line: line}) + + @write_comments(2) + @write_indented("#{keyword}#{name}", 2) + + doc_string: (content_type, string, line) -> + logger.verbose({token: 'doc_string', content_type: content_type, string: string, line: line}) + three_quotes = '"""' + + @write_comments(2) + @write_indented("#{three_quotes}#{content_type}\n#{string}\n#{three_quotes}", 3) + + row: (cells, line) -> + logger.verbose({token: 'row', cells: cells, line: line}) + + # TODO: need to collect rows so that we can align the vertical pipes to the widest columns + # See Gherkin::Formatter::PrettyFormatter#table(rows) + @write_comments(3) + @write_indented("| #{cells.join(' | ')} |", 3) + + eof: () -> + logger.verbose({token: 'eof'}) + # If there were any comments left, treat them as step comments. + @write_comments(2) + } + + lexer = new Lexer(recorder) + lexer.scan(text) + + if options.debug_lexer + for line in recorder.lines + logger.verbose("> #{line}") + + resolve recorder.lines.join("\n") + ) diff --git a/src/beautifiers/index.coffee b/src/beautifiers/index.coffee index d317a4c..ac84254 100644 --- a/src/beautifiers/index.coffee +++ b/src/beautifiers/index.coffee @@ -39,6 +39,7 @@ module.exports = class Beautifiers extends EventEmitter 'coffee-fmt' 'htmlbeautifier' 'csscomb' + 'gherkin' 'gofmt' 'fortran-beautifier' 'js-beautify' diff --git a/src/languages/gherkin.coffee b/src/languages/gherkin.coffee new file mode 100644 index 0000000..33f0ca9 --- /dev/null +++ b/src/languages/gherkin.coffee @@ -0,0 +1,37 @@ +# Get Atom defaults +tabLength = atom?.config.get('editor.tabLength') ? 4 +softTabs = atom?.config.get('editor.softTabs') ? true +defaultIndentSize = (if softTabs then tabLength else 1) +defaultIndentChar = (if softTabs then " " else "\t") +defaultIndentWithTabs = not softTabs + +module.exports = { + + name: "gherkin" + namespace: "gherkin" + + grammars: [ + "Gherkin" + ] + + extensions: [ + "feature" + ] + + options: + indent_size: + type: 'integer' + default: defaultIndentSize + minimum: 0 + description: "Indentation size/length" + indent_char: + type: 'string' + default: defaultIndentChar + minimum: 0 + description: "Indentation character" + debug_lexer: + type: 'boolean' + default: false + description: "Enable debug logs of the Gherkin Lexer" + +} diff --git a/src/languages/index.coffee b/src/languages/index.coffee index 10bad55..5ce2222 100644 --- a/src/languages/index.coffee +++ b/src/languages/index.coffee @@ -22,6 +22,7 @@ module.exports = class Languages "d" "ejs" "erb" + "gherkin" "go" "fortran" "handlebars"