Add Gherkin grammar support

This resolves Glavin001/atom-beautify#377

Uses the https://github.com/cucumber/gherkin/tree/master/js node.js
package to use the official Lexer class.

The only known issue I've seen so far is that it does not format
tables properly -- the columns are not resized to match the widest
cell in each column.
This commit is contained in:
Joe Hansche 2015-07-29 20:48:53 -04:00
parent e337ea7f11
commit ff6ee21db9
5 changed files with 169 additions and 0 deletions

View File

@ -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",

View File

@ -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")
)

View File

@ -39,6 +39,7 @@ module.exports = class Beautifiers extends EventEmitter
'coffee-fmt'
'htmlbeautifier'
'csscomb'
'gherkin'
'gofmt'
'fortran-beautifier'
'js-beautify'

View File

@ -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"
}

View File

@ -22,6 +22,7 @@ module.exports = class Languages
"d"
"ejs"
"erb"
"gherkin"
"go"
"fortran"
"handlebars"