diff --git a/examples/nested-jsbeautifyrc/gherkin/expected/tables.feature b/examples/nested-jsbeautifyrc/gherkin/expected/tables.feature new file mode 100644 index 0000000..cbeb73c --- /dev/null +++ b/examples/nested-jsbeautifyrc/gherkin/expected/tables.feature @@ -0,0 +1,10 @@ +Feature: Description + + Scenario Outline: This one will have examples + Given the + Then the + + Examples: + | what | then | + | first value | first then | + | second what value | second then value | \ No newline at end of file diff --git a/examples/nested-jsbeautifyrc/gherkin/expected/test.feature b/examples/nested-jsbeautifyrc/gherkin/expected/test.feature new file mode 100644 index 0000000..57c0f8a --- /dev/null +++ b/examples/nested-jsbeautifyrc/gherkin/expected/test.feature @@ -0,0 +1,23 @@ +Feature: The description of the feature that + might need to be wrapped + onto multiple lines + + Scenario: The description of the scenario that + might need to be wrapped + onto multiple lines + Given I am in some state + When I take some action + # And I can add a comment + Then I should see some outcome + + # A comment gets moved above the tag + @tag1 + Scenario: This scenario has a tag + Then I should see some outcome + + @tag1 @tag2 + Scenario: This scenario has two tags + Then I should see some outcome + + Scenario: This scenario does not have any tags + Then I should see some outcome \ No newline at end of file diff --git a/examples/nested-jsbeautifyrc/gherkin/original/_tables.feature b/examples/nested-jsbeautifyrc/gherkin/original/_tables.feature new file mode 100644 index 0000000..038fc33 --- /dev/null +++ b/examples/nested-jsbeautifyrc/gherkin/original/_tables.feature @@ -0,0 +1,9 @@ +Feature: Description + +Scenario Outline: This one will have examples + Given the + Then the + Examples: + | what | then | + | first value | first then| + | second what|second then| \ No newline at end of file diff --git a/examples/nested-jsbeautifyrc/gherkin/original/test.feature b/examples/nested-jsbeautifyrc/gherkin/original/test.feature new file mode 100644 index 0000000..73dddfd --- /dev/null +++ b/examples/nested-jsbeautifyrc/gherkin/original/test.feature @@ -0,0 +1,23 @@ +Feature: The description of the feature that +might need to be wrapped +onto multiple lines + +Scenario: The description of the scenario that +might need to be wrapped +onto multiple lines +Given I am in some state +When I take some action +# And I can add a comment +Then I should see some outcome + +@tag1 +# A comment gets moved above the tag +Scenario: This scenario has a tag +Then I should see some outcome + +@tag1 @tag2 +Scenario: This scenario has two tags +Then I should see some outcome + +Scenario: This scenario does not have any tags +Then I should see some outcome \ No newline at end of file diff --git a/package.json b/package.json index 4e0ac45..4bd2bfe 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..9569cb3 --- /dev/null +++ b/src/beautifiers/gherkin.coffee @@ -0,0 +1,130 @@ +### +### + +"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) -> + if @tags.length > 0 + @write_indented(@tags.splice(0, @tags.length).join(' '), 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) + + loggerLevel = atom?.config.get('atom-beautify._loggerLevel') + if loggerLevel is 'verbose' + 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..bfd9599 --- /dev/null +++ b/src/languages/gherkin.coffee @@ -0,0 +1,32 @@ +# 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" +} 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"