added cucumber support via feature-mode

This commit is contained in:
Bozhidar Batsov 2011-10-09 11:32:32 +03:00
parent df73849b75
commit c7ba5e4b27
11 changed files with 1150 additions and 3 deletions

View file

@ -69,11 +69,11 @@
(require 'scss-mode) (require 'scss-mode)
;; cucumber support ;; cucumber support
;(require 'feature-mode) (require 'feature-mode)
;(add-to-list 'auto-mode-alist '("\.feature$" . feature-mode)) (add-to-list 'auto-mode-alist '("\.feature$" . feature-mode))
;; load bundle snippets ;; load bundle snippets
;(yas/load-directory (concat ext-dir "feature-mode/snippets")) (yas/load-directory (concat ext-dir "feature-mode/snippets"))
(provide 'prelude-ruby) (provide 'prelude-ruby)

461
vendor/feature-mode/feature-mode.el vendored Executable file
View file

@ -0,0 +1,461 @@
;; cucumber.el -- Emacs mode for editing plain text user stories
;;
;; Copyright (C) 2008 — 2011 Michael Klishin and other contributors
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation; either version 2
;; of the License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110.
;;
;; Copy files to ~/.emacs.d/elisp/feature-mode and add this to your
;; .emacs to load the mode
;; (add-to-list 'load-path "~/.emacs.d/elisp/feature-mode")
;; ;; optional configurations
;; ;; default language if .feature doesn't have "# language: fi"
;; ;(setq feature-default-language "fi")
;; ;; point to cucumber languages.yml or gherkin i18n.yml to use
;; ;; exactly the same localization your cucumber uses
;; ;(setq feature-default-i18n-file "/path/to/gherkin/gem/i18n.yml")
;; ;; and load it
;; (require 'feature-mode)
;; (add-to-list 'auto-mode-alist '("\.feature$" . feature-mode))
;;
;; Language used in feature file is automatically detected from
;; "language: [2-letter ISO-code]" tag in feature file. You can
;; choose the language feature-mode should use in case autodetection
;; fails. Just add
;; (setq feature-default-language "en")
;; to your .emacs
;;
;; Translations are loaded from ~/.emacs.d/elisp/feature-mode/i18n.yml
;; by default. You can configure feature-mode to load translations
;; directly from cucumber languages.yml or gherkin i18n.yml. Just add
;; (setq feature-default-i18n-file
;; "/usr/lib/ruby/gems/1.8/gems/cucumber-0.4.4/lib/cucumber/languages.yml")
;; to your .emacs before
;; (require 'feature-mode)
;;
;;
;; In order to get goto-step-definition to work, you must install the
;; ruby_parser gem (version 2.0.x). For example:
;;
;; gem install ruby_parser --version=2.0.5
;;
;; (be sure and use the ruby-interpreter that emacs will use based on
;; `exec-path')
;;
;;
;; Key Bindings
;; ------------
;;
;; \C-c ,v
;; : Verify all scenarios in the current buffer file.
;;
;; \C-c ,s
;; : Verify the scenario under the point in the current buffer.
;;
;; \C-c ,f
;; : Verify all features in project. (Available in feature and
;; ruby files)
;;
;; \C-c ,r
;; : Repeat the last verification process.
;;
;; \C-c ,g
;; : Go to step-definition under point
(eval-when-compile (require 'cl))
(require 'thingatpt)
;;
;; Keywords and font locking
;;
(when (featurep 'font-lock)
(or (boundp 'font-lock-variable-name-face)
(setq font-lock-variable-name-face font-lock-type-face)))
(defun load-gherkin-i10n (filename)
"Read and parse Gherkin l10n from given file."
(interactive "Load l10n file: ")
(with-temp-buffer
(insert-file-contents filename)
(parse-gherkin-l10n)))
(defun parse-gherkin-l10n ()
(let (languages-alist)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(if (try-find-next-language)
(let ((lang-beg (+ (point) 1))
(lang-end (progn (end-of-line) (- (point) 2)))
(kwds-beg (+ (point) 1))
(kwds-end (progn (try-find-next-language) (point))))
(add-to-list
'languages-alist
(cons
(filter-buffer-substring lang-beg lang-end)
(parse-gherkin-l10n-translations kwds-beg kwds-end)))))))
(nreverse languages-alist)))
(defun try-find-next (regexp)
(let (search-result)
(setq search-result (search-forward-regexp regexp nil t))
(if search-result
(beginning-of-line)
(goto-char (point-max)))
search-result))
(defun try-find-next-language ()
(try-find-next "^\"[^\"]+\":"))
(defun try-find-next-translation ()
(try-find-next "^ \\([^ :]+\\): +\"?\\*?|?\\([^\"\n]+\\)\"?"))
(defun parse-gherkin-l10n-translations (beg end)
(let (translations-alist)
(save-excursion
(save-restriction
(narrow-to-region beg end)
(goto-char (point-min))
(while (not (eobp))
(if (try-find-next-translation)
(let ((kwname (match-string-no-properties 1))
(kw (match-string-no-properties 2)))
(add-to-list
'translations-alist
(cons
(intern kwname)
(if (or (equal kwname "name")
(equal kwname "native"))
kw
(build-keyword-matcher kw))))))
(end-of-line))))
(nreverse translations-alist)))
(defun build-keyword-matcher (keyword)
(concat "^[ \t]*\\(" (replace-regexp-in-string "|" "\\\\|" keyword) "\\):?"))
(defvar feature-default-language "en")
(defvar feature-default-i18n-file "~/.emacs.d/elisp/feature-mode/i18n.yml")
(defconst feature-keywords-per-language
(if (file-readable-p feature-default-i18n-file)
(load-gherkin-i10n feature-default-i18n-file)
'(("en" . ((feature . "^ *Feature:")
(background . "^ *Background:")
(scenario . "^ *Scenario:")
(scenario_outline .
"^ *Scenario Outline:")
(given . "^ *Given")
(when . "^ *When")
(then . "^ *Then")
(but . "^ *But")
(and . "^ *And")
(examples . "^ *\\(Examples\\|Scenarios\\):?"))))))
(defconst feature-font-lock-keywords
'((feature (0 font-lock-keyword-face)
(".*" nil nil (0 font-lock-type-face t)))
(background . (0 font-lock-keyword-face))
(scenario (0 font-lock-keyword-face)
(".*" nil nil (0 font-lock-function-name-face t)))
(scenario_outline
(0 font-lock-keyword-face)
(".*" nil nil (0 font-lock-function-name-face t)))
(given . font-lock-keyword-face)
(when . font-lock-keyword-face)
(then . font-lock-keyword-face)
(but . font-lock-keyword-face)
(and . font-lock-keyword-face)
(examples . font-lock-keyword-face)
("^ *@.*" . font-lock-preprocessor-face)
("^ *#.*" 0 font-lock-comment-face t)))
;;
;; Keymap
;;
(defvar feature-mode-map nil "Keymap used in feature mode")
(if feature-mode-map
nil
(setq feature-mode-map (make-sparse-keymap))
(define-key feature-mode-map "\C-m" 'newline)
(define-key feature-mode-map (kbd "C-c ,s") 'feature-verify-scenario-at-pos)
(define-key feature-mode-map (kbd "C-c ,v") 'feature-verify-all-scenarios-in-buffer)
(define-key feature-mode-map (kbd "C-c ,f") 'feature-verify-all-scenarios-in-project)
(define-key feature-mode-map (kbd "C-c ,g") 'feature-goto-step-definition))
;; Add relevant feature keybindings to ruby modes
(add-hook 'ruby-mode-hook
(lambda ()
(local-set-key (kbd "C-c ,f") 'feature-verify-all-scenarios-in-project)))
;;
;; Syntax table
;;
(defvar feature-mode-syntax-table nil
"Syntax table in use in ruby-mode buffers.")
(unless feature-mode-syntax-table
(setq feature-mode-syntax-table (make-syntax-table)))
;; Constants
(defconst feature-blank-line-re "^[ \t]*$"
"Regexp matching a line containing only whitespace.")
(defun feature-feature-re (language)
(cdr (assoc 'feature (cdr (assoc language feature-keywords-per-language)))))
(defun feature-scenario-re (language)
(cdr (assoc 'scenario (cdr (assoc language feature-keywords-per-language)))))
(defun feature-background-re (language)
(cdr (assoc 'background (cdr (assoc language feature-keywords-per-language)))))
;;
;; Variables
;;
(defvar feature-mode-hook nil
"Hook run when entering `feature-mode'.")
(defcustom feature-indent-level 2
"Indentation of feature statements"
:type 'integer :group 'feature)
(defcustom feature-indent-offset 2
"*Amount of offset per level of indentation."
:type 'integer :group 'feature)
(defun feature-compute-indentation ()
"Calculate the maximum sensible indentation for the current line."
(save-excursion
(beginning-of-line)
(if (bobp) 10
(forward-line -1)
(while (and (looking-at feature-blank-line-re)
(> (point) (point-min)))
(forward-line -1))
(+ (current-indentation)
(if (or (looking-at (feature-feature-re (feature-detect-language)))
(looking-at (feature-scenario-re (feature-detect-language)))
(looking-at (feature-background-re (feature-detect-language))))
feature-indent-offset 0)))))
(defun feature-indent-line ()
"Indent the current line.
The first time this command is used, the line will be indented to the
maximum sensible indentation. Each immediately subsequent usage will
back-dent the line by `feature-indent-offset' spaces. On reaching column
0, it will cycle back to the maximum sensible indentation."
(interactive "*")
(let ((ci (current-indentation))
(cc (current-column))
(need (feature-compute-indentation)))
(save-excursion
(beginning-of-line)
(delete-horizontal-space)
(if (and (equal last-command this-command) (/= ci 0))
(indent-to (* (/ (- ci 1) feature-indent-offset) feature-indent-offset))
(indent-to need)))
(if (< (current-column) (current-indentation))
(forward-to-indentation 0))))
(defun feature-font-lock-keywords-for (language)
(let ((result-keywords . ()))
(dolist (pair feature-font-lock-keywords)
(let* ((keyword (car pair))
(font-locking (cdr pair))
(language-keyword (cdr (assoc keyword
(cdr (assoc
language
feature-keywords-per-language))))))
(push (cons (or language-keyword keyword) font-locking) result-keywords)))
result-keywords))
(defun feature-detect-language ()
(save-excursion
(goto-char (point-min))
(if (re-search-forward "language: \\([[:alpha:]-]+\\)"
(line-end-position)
t)
(match-string 1)
feature-default-language)))
(defun feature-mode-variables ()
(set-syntax-table feature-mode-syntax-table)
(setq require-final-newline t)
(setq comment-start "# ")
(setq comment-start-skip "#+ *")
(setq comment-end "")
(setq parse-sexp-ignore-comments t)
(set (make-local-variable 'indent-tabs-mode) 'nil)
(set (make-local-variable 'indent-line-function) 'feature-indent-line)
(set (make-local-variable 'font-lock-defaults)
(list (feature-font-lock-keywords-for (feature-detect-language)) nil nil))
(set (make-local-variable 'font-lock-keywords)
(feature-font-lock-keywords-for (feature-detect-language))))
(defun feature-minor-modes ()
"Enable all minor modes for feature mode."
(turn-on-orgtbl))
;;
;; Mode function
;;
;;;###autoload
(defun feature-mode()
"Major mode for editing plain text stories"
(interactive)
(kill-all-local-variables)
(use-local-map feature-mode-map)
(setq mode-name "Feature")
(setq major-mode 'feature-mode)
(feature-mode-variables)
(feature-minor-modes)
(run-mode-hooks 'feature-mode-hook))
(add-to-list 'auto-mode-alist '("\\.feature\\'" . feature-mode))
;;
;; Snippets
;;
(defvar feature-snippet-directory (concat (file-name-directory load-file-name) "snippets")
"Path to the feature-mode snippets.
If the yasnippet library is loaded, snippets in this directory
are loaded on startup. If nil, don't load snippets.")
(defvar feature-support-directory (concat (file-name-directory load-file-name) "support")
"Path to support folder
The support folder contains a ruby script that takes a step as an
argument, and outputs a list of all matching step definitions")
(declare-function yas/load-directory "yasnippet" t)
(when (and (featurep 'yasnippet)
feature-snippet-directory
(file-exists-p feature-snippet-directory))
(yas/load-directory feature-snippet-directory))
;;
;; Verifying features
;;
(defun feature-scenario-name-re (language)
(concat (feature-scenario-re (feature-detect-language)) "[[:space:]]+\\(.*\\)$"))
(defun feature-scenario-name-at-pos (&optional pos)
"Returns the name of the scenario at the specified position. if pos is not specified the current buffer location will be used."
(interactive)
(let ((start (or pos (point))))
(save-excursion
(end-of-line)
(unless (re-search-backward (feature-scenario-name-re (feature-detect-language)) nil t)
(error "Unable to find an scenario"))
(match-string-no-properties 1))))
(defun feature-verify-scenario-at-pos (&optional pos)
"Run the scenario defined at pos. If post is not specified the current buffer location will be used."
(interactive)
(feature-run-cucumber
(list "-n" (concat "'" (feature-escape-scenario-name (feature-scenario-name-at-pos)) "'"))
:feature-file (buffer-file-name)))
(defun feature-verify-all-scenarios-in-buffer ()
"Run all the scenarios defined in current buffer."
(interactive)
(feature-run-cucumber '() :feature-file (buffer-file-name)))
(defun feature-verify-all-scenarios-in-project ()
"Run all the scenarios defined in current project."
(interactive)
(feature-run-cucumber '()))
(defun feature-register-verify-redo (redoer)
"Register a bit of code that will repeat a verification process"
(let ((redoer-cmd (eval (list 'lambda ()
'(interactive)
(list 'let (list (list `default-directory
default-directory))
redoer)))))
(global-set-key (kbd "C-c ,r") redoer-cmd)))
(defun feature-run-cucumber (cuke-opts &optional &key feature-file)
"Runs cucumber with the specified options"
(feature-register-verify-redo (list 'feature-run-cucumber
(list 'quote cuke-opts)
:feature-file feature-file))
;; redoer is registered
(let ((opts-str (mapconcat 'identity cuke-opts " "))
(feature-arg (if feature-file
(concat " FEATURE='" feature-file "'")
"")))
(ansi-color-for-comint-mode-on)
(let ((default-directory (feature-project-root)))
(compile (concat "rake cucumber CUCUMBER_OPTS=\"" opts-str "\"" feature-arg) t)))
(end-of-buffer-other-window 0))
(defun feature-escape-scenario-name (scenario-name)
"Escapes all the characaters in a scenario name that mess up using in the -n options"
(replace-regexp-in-string "\\(\"\\)" "\\\\\\\\\\\\\\1" (replace-regexp-in-string "\\([()\']\\|\\[\\|\\]\\)" "\\\\\\1" scenario-name)))
(defun feature-root-directory-p (a-directory)
"Tests if a-directory is the root of the directory tree (i.e. is it '/' on unix)."
(equal a-directory (file-name-directory (directory-file-name a-directory))))
(defun feature-project-root (&optional directory)
"Finds the root directory of the project by walking the directory tree until it finds Rakefile (presumably, application root)"
(let ((directory (file-name-as-directory (or directory default-directory))))
(if (feature-root-directory-p directory) (error "No rakefle found"))
(if (file-exists-p (concat directory "Rakefile"))
directory
(feature-project-root (file-name-directory (directory-file-name directory))))))
(defun feature-goto-step-definition ()
"Goto the step-definition under (point). Requires ruby"
(interactive)
(let* ((root (feature-project-root))
(input (thing-at-point 'line))
(_ (set-text-properties 0 (length input) nil input))
(result (shell-command-to-string (format "cd %S && ruby %S/go_to_step.rb %S"
root
feature-support-directory
input)))
(file-and-line (car (split-string result "\n")))
(matched? (string-match "^\\(.+\\):\\([0-9]+\\)$" file-and-line)))
(if matched?
(let ((file (format "%s/%s" root (match-string 1 file-and-line)))
(line-no (string-to-number (match-string 2 file-and-line))))
(find-file file)
(goto-char (point-min))
(forward-line (1- line-no)))
(if (equal "" result)
(message "No matching steps found for:\n%s" input)
(message "An error occurred:\n%s" result)))))
(provide 'cucumber-mode)
(provide 'feature-mode)

575
vendor/feature-mode/i18n.yml vendored Executable file
View file

@ -0,0 +1,575 @@
# encoding: UTF-8
#
# We use ISO 639-1 (language) and ISO 3166 alpha-2 (region - if appliccable):
# http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
# http://en.wikipedia.org/wiki/ISO_3166-1
#
# If you want several aliases for a keyword, just separate them
# with a | character. Make sure there are no ambiguities in the
# keywords.
#
# If you do *not* want a trailing space after a keyword, end it with a < character.
# (See Chinese for examples).
#
"en":
name: English
native: English
feature: Feature
background: Background
scenario: Scenario
scenario_outline: Scenario Outline
examples: Examples|Scenarios
given: "*|Given"
when: "*|When"
then: "*|Then"
and: "*|And"
but: "*|But"
# Please keep the grammars in alphabetical order by name from here and down.
"ar":
name: Arabic
native: العربية
feature: خاصية
background: الخلفية
scenario: سيناريو
scenario_outline: سيناريو مخطط
examples: امثلة
given: "*|بفرض"
when: "*|متى|عندما"
then: "*|اذاً|ثم"
and: "*|و"
but: "*|لكن"
"bg":
name: Bulgarian
native: български
feature: Функционалност
background: Предистория
scenario: Сценарий
scenario_outline: Рамка на сценарий
examples: Примери
given: "*|Дадено"
when: "*|Когато"
then: "*|То"
and: "*|И"
but: "*|Но"
"ca":
name: Catalan
native: català
background: Rerefons|Antecedents
feature: Característica|Funcionalitat
scenario: Escenari
scenario_outline: Esquema de l'escenari
examples: Exemples
given: "*|Donat|Donada|Atès|Atesa"
when: "*|Quan"
then: "*|Aleshores|Cal"
and: "*|I"
but: "*|Però"
"cy-GB":
name: Welsh
native: Cymraeg
background: Cefndir
feature: Arwedd
scenario: Scenario
scenario_outline: Scenario Amlinellol
examples: Enghreifftiau
given: "*|Anrhegedig a"
when: "*|Pryd"
then: "*|Yna"
and: "*|A"
but: "*|Ond"
"cs":
name: Czech
native: Česky
feature: Požadavek
background: Pozadí|Kontext
scenario: Scénář
scenario_outline: Náčrt Scénáře|Osnova scénáře
examples: Příklady
given: "*|Pokud"
when: "*|Když"
then: "*|Pak"
and: "*|A|A také"
but: "*|Ale"
"da":
name: Danish
native: dansk
feature: Egenskab
background: Baggrund
scenario: Scenarie
scenario_outline: Abstrakt Scenario
examples: Eksempler
given: "*|Givet"
when: "*|Når"
then: "*|Så"
and: "*|Og"
but: "*|Men"
"de":
name: German
native: Deutsch
feature: Funktionalität
background: Grundlage
scenario: Szenario
scenario_outline: Szenariogrundriss
examples: Beispiele
given: "*|Angenommen|Gegeben sei"
when: "*|Wenn"
then: "*|Dann"
and: "*|Und"
but: "*|Aber"
"en-au":
name: Australian
native: Australian
feature: Crikey
background: Background
scenario: Mate
scenario_outline: Blokes
examples: Cobber
given: "*|Ya know how"
when: "*|When"
then: "*|Ya gotta"
and: "*|N"
but: "*|Cept"
"en-lol":
name: LOLCAT
native: LOLCAT
feature: OH HAI
background: B4
scenario: MISHUN
scenario_outline: MISHUN SRSLY
examples: EXAMPLZ
given: "*|I CAN HAZ"
when: "*|WEN"
then: "*|DEN"
and: "*|AN"
but: "*|BUT"
"en-Scouse":
name: Scouse
native: Scouse
feature: Feature
background: "Dis is what went down"
scenario: "The thing of it is"
scenario_outline: "Wharrimean is"
examples: Examples
given: "*|Givun|Youse know when youse got"
when: "*|Wun|Youse know like when"
then: "*|Dun|Den youse gotta"
and: "*|An"
but: "*|Buh"
"en-tx":
name: Texan
native: Texan
feature: Feature
background: Background
scenario: Scenario
scenario_outline: All y'all
examples: Examples
given: "*|Given y'all"
when: "*|When y'all"
then: "*|Then y'all"
and: "*|And y'all"
but: "*|But y'all"
"eo":
name: Esperanto
native: Esperanto
feature: Trajto
background: Fono
scenario: Scenaro
scenario_outline: Konturo de la scenaro
examples: Ekzemploj
given: "*|Donitaĵo"
when: "*|Se"
then: "*|Do"
and: "*|Kaj"
but: "*|Sed"
"es":
name: Spanish
native: español
background: Antecedentes
feature: Característica
scenario: Escenario
scenario_outline: Esquema del escenario
examples: Ejemplos
given: "*|Dado"
when: "*|Cuando"
then: "*|Entonces"
and: "*|Y"
but: "*|Pero"
"et":
name: Estonian
native: eesti keel
feature: Omadus
background: Taust
scenario: Stsenaarium
scenario_outline: Raamstsenaarium
examples: Juhtumid
given: "*|Eeldades"
when: "*|Kui"
then: "*|Siis"
and: "*|Ja"
but: "*|Kuid"
"fi":
name: Finnish
native: suomi
feature: Ominaisuus
background: Tausta
scenario: Tapaus
scenario_outline: Tapausaihio
examples: Tapaukset
given: "*|Oletetaan"
when: "*|Kun"
then: "*|Niin"
and: "*|Ja"
but: "*|Mutta"
"fr":
name: French
native: français
feature: Fonctionnalité
background: Contexte
scenario: Scénario
scenario_outline: Plan du scénario|Plan du Scénario
examples: Exemples
given: "*|Soit|Etant donné"
when: "*|Quand|Lorsque|Lorsqu'<"
then: "*|Alors"
and: "*|Et"
but: "*|Mais"
"he":
name: Hebrew
native: עברית
feature: תכונה
background: רקע
scenario: תרחיש
scenario_outline: תבנית תרחיש
examples: דוגמאות
given: "*|בהינתן"
when: "*|כאשר"
then: "*|אז|אזי"
and: "*|וגם"
but: "*|אבל"
"hr":
name: Croatian
native: hrvatski
feature: Osobina|Mogućnost|Mogucnost
background: Pozadina
scenario: Scenarij
scenario_outline: Skica|Koncept
examples: Primjeri|Scenariji
given: "*|Zadan|Zadani|Zadano"
when: "*|Kada|Kad"
then: "*|Onda"
and: "*|I"
but: "*|Ali"
"hu":
name: Hungarian
native: magyar
feature: Jellemző
background: Háttér
scenario: Forgatókönyv
scenario_outline: Forgatókönyv vázlat
examples: Példák
given: "*|Ha"
when: "*|Majd"
then: "*|Akkor"
and: "*|És"
but: "*|De"
"id":
name: Indonesian
native: Bahasa Indonesia
feature: Fitur
background: Dasar
scenario: Skenario
scenario_outline: Skenario konsep
examples: Contoh
given: "*|Dengan"
when: "*|Ketika"
then: "*|Maka"
and: "*|Dan"
but: "*|Tapi"
"it":
name: Italian
native: italiano
feature: Funzionalità
background: Contesto
scenario: Scenario
scenario_outline: Schema dello scenario
examples: Esempi
given: "*|Dato"
when: "*|Quando"
then: "*|Allora"
and: "*|E"
but: "*|Ma"
"ja":
name: Japanese
native: 日本語
feature: フィーチャ|機能
background: 背景
scenario: シナリオ
scenario_outline: シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ
examples: 例|サンプル
given: "*|前提<"
when: "*|もし<"
then: "*|ならば<"
and: "*|かつ<"
but: "*|しかし<|但し<|ただし<"
"ko":
name: Korean
native: 한국어
background: 배경
feature: 기능
scenario: 시나리오
scenario_outline: 시나리오 개요
examples:
given: "*|조건<|먼저<"
when: "*|만일<|만약<"
then: "*|그러면<"
and: "*|그리고<"
but: "*|하지만<|단<"
"lt":
name: Lithuanian
native: lietuvių kalba
feature: Savybė
background: Kontekstas
scenario: Scenarijus
scenario_outline: Scenarijaus šablonas
examples: Pavyzdžiai|Scenarijai|Variantai
given: "*|Duota"
when: "*|Kai"
then: "*|Tada"
and: "*|Ir"
but: "*|Bet"
"lv":
name: Latvian
native: latviešu
feature: Funkcionalitāte|Fīča
background: Konteksts|Situācija
scenario: Scenārijs
scenario_outline: Scenārijs pēc parauga
examples: Piemēri|Paraugs
given: "*|Kad"
when: "*|Ja"
then: "*|Tad"
and: "*|Un"
but: "*|Bet"
"nl":
name: Dutch
native: Nederlands
feature: Functionaliteit
background: Achtergrond
scenario: Scenario
scenario_outline: Abstract Scenario
examples: Voorbeelden
given: "*|Gegeven|Stel"
when: "*|Als"
then: "*|Dan"
and: "*|En"
but: "*|Maar"
"no":
name: Norwegian
native: norsk
feature: Egenskap
background: Bakgrunn
scenario: Scenario
scenario_outline: Abstrakt Scenario
examples: Eksempler
given: "*|Gitt"
when: "*|Når"
then: "*|Så"
and: "*|Og"
but: "*|Men"
"pl":
name: Polish
native: polski
feature: Właściwość
background: Założenia
scenario: Scenariusz
scenario_outline: Szablon scenariusza
examples: Przykłady
given: "*|Zakładając"
when: "*|Jeżeli"
then: "*|Wtedy"
and: "*|Oraz"
but: "*|Ale"
"pt":
name: Portuguese
native: português
background: Contexto
feature: Funcionalidade
scenario: Cenário|Cenario
scenario_outline: Esquema do Cenário|Esquema do Cenario
examples: Exemplos
given: "*|Dado"
when: "*|Quando"
then: "*|Então|Entao"
and: "*|E"
but: "*|Mas"
"ro":
name: Romanian
native: română
background: Conditii
feature: Functionalitate
scenario: Scenariu
scenario_outline: Scenariul de sablon
examples: Exemplele
given: "*|Daca"
when: "*|Cand"
then: "*|Atunci"
and: "*|Si"
but: "*|Dar"
"ro-RO":
name: Romanian (diacritical)
native: română (diacritical)
background: Condiţii
feature: Funcționalitate
scenario: Scenariu
scenario_outline: Scenariul de şablon
examples: Exemplele
given: "*|Dacă"
when: "*|Când"
then: "*|Atunci"
and: "*|Și"
but: "*|Dar"
"ru":
name: Russian
native: русский
feature: Функционал|Фича
background: Предыстория
scenario: Сценарий
scenario_outline: Структура сценария
examples: Значения
given: "*|Допустим"
when: "*|Если"
then: "*|То"
and: "*|И|К тому же"
but: "*|Но|А"
"sv":
name: Swedish
native: Svenska
feature: Egenskap
background: Bakgrund
scenario: Scenario
scenario_outline: Abstrakt Scenario
examples: Exempel
given: "*|Givet"
when: "*|När"
then: "*|Så"
and: "*|Och"
but: "*|Men"
"sk":
name: Slovak
native: Slovensky
feature: Požiadavka
background: Pozadie
scenario: Scenár
scenario_outline: Náčrt Scenáru
examples: Príklady
given: "*|Pokiaľ"
when: "*|Keď"
then: "*|Tak"
and: "*|A"
but: "*|Ale"
"sr-Latn":
name: Serbian (Latin)
native: Srpski (Latinica)
feature: Funkcionalnost|Mogućnost|Mogucnost|Osobina
background: Kontekst|Osnova|Pozadina
scenario: Scenario|Primer
scenario_outline: Struktura scenarija|Skica|Koncept
examples: Primeri|Scenariji
given: "*|Zadato|Zadate|Zatati"
when: "*|Kada|Kad"
then: "*|Onda"
and: "*|I"
but: "*|Ali"
"sr-Cyrl":
name: Serbian
native: Српски
feature: Функционалност|Могућност|Особина
background: Контекст|Основа|Позадина
scenario: Сценарио|Пример
scenario_outline: Структура сценарија|Скица|Концепт
examples: Примери|Сценарији
given: "*|Задато|Задате|Задати"
when: "*|Када|Кад"
then: "*|Онда"
and: "*|И"
but: "*|Али"
"tr":
name: Turkish
native: Türkçe
feature: Özellik
background: Geçmiş
scenario: Senaryo
scenario_outline: Senaryo taslağı
examples: Örnekler
given: "*|Diyelim ki"
when: "*|Eğer ki"
then: "*|O zaman"
and: "*|Ve"
but: "*|Fakat|Ama"
"uk":
name: Ukrainian
native: Українська
feature: Функціонал
background: Передумова
scenario: Сценарій
scenario_outline: Структура сценарію
examples: Приклади
given: "*|Припустимо|Припустимо, що|Нехай"
when: "*|Якщо"
then: "*|То"
and: "*|І"
but: "*|Але"
"uz":
name: Uzbek
native: Узбекча
feature: Функционал
background: Тарих
scenario: Сценарий
scenario_outline: Сценарий структураси
examples: Мисоллар
given: "*|Агар"
when: "*|Агар"
then: "*|Унда"
and: "*|Ва"
but: "*|Лекин|Бирок|Аммо"
"vi":
name: Vietnamese
native: Tiếng Việt
feature: Tính năng
background: Bối cảnh
scenario: Tình huống|Kịch bản
scenario_outline: Khung tình huống|Khung kịch bản
examples: Dữ liệu
given: "*|Biết|Cho"
when: "*|Khi"
then: "*|Thì"
and: "*|Và"
but: "*|Nhưng"
"zh-CN":
name: Chinese simplified
native: 简体中文
feature: 功能
background: 背景
scenario: 场景
scenario_outline: 场景大纲
examples: 例子
given: "*|假如<"
when: "*|当<"
then: "*|那么<"
and: "*|而且<"
but: "*|但是<"
"zh-TW":
name: Chinese traditional
native: 繁體中文
feature: 功能
background: 背景
scenario: 場景|劇本
scenario_outline: 場景大綱|劇本大綱
examples: 例子
given: "*|假設<"
when: "*|當<"
then: "*|那麼<"
and: "*|而且<|並且<"
but: "*|但是<"

View file

@ -0,0 +1,4 @@
#name: And something else
# --
And ${1:something else}
$0

View file

@ -0,0 +1,5 @@
#name: Background
# --
Background:
Given ${1: a known starting condition}
$0

View file

@ -0,0 +1,7 @@
#name: Feature: Name
# --
Feature: ${1:Name}
In order to ${2:get some business value}
${3:Role} will need ${4:this sweet new feature}
$0

View file

@ -0,0 +1,4 @@
#name: Given a known starting condition
# --
Given ${1:a known starting condition}
$0

View file

@ -0,0 +1,4 @@
#name: Scenario: Name
# --
Scenario: ${1:Name}
$0

View file

@ -0,0 +1,4 @@
#name: Then some expected outcome
# --
Then ${1:some expected outcome}
$0

View file

@ -0,0 +1,4 @@
#name: When some action
# --
When ${1:some action}
$0

79
vendor/feature-mode/support/go_to_step.rb vendored Executable file
View file

@ -0,0 +1,79 @@
require 'rubygems'
gem "ruby_parser", "~> 2.0"
require 'ruby_parser'
class Step
attr_reader :file, :line, :regexp
def initialize(regexp, file, line)
@file, @line = file, line
self.regexp = regexp
end
def regexp=(value)
@regexp =
case value
when String
pieces, regexp = [], value.dup
regexp.gsub!(/\$\w+/) { |match| pieces << match; "TOKEN" }
regexp = Regexp.escape(regexp)
regexp.gsub!(/TOKEN/) { |match| "(.*)" }
Regexp.new("^#{regexp}$")
when Regexp
value
else
STDERR.puts "Warning: invalid parameter to Given/When/Then on #{file}:#{line}. Expected Regexp or String, got #{value.class} #{value.inspect}"
Regexp.new(/^INVALID PARAM$/)
end
end
def match?(text)
@regexp.match(text)
end
end
class StepParser
def self.parser
@parser ||= RubyParser.new
end
attr_accessor :steps, :file
def initialize(file)
@file = file
@steps = []
extract_steps(self.class.parser.parse(File.read(file)))
end
def extract_steps(sexp)
return unless sexp.is_a?(Sexp)
case sexp.first
when :block
sexp[1..-1].each do |child_sexp|
extract_steps(child_sexp)
end
when :iter
child_sexp = sexp[1]
return unless child_sexp[0] == :call && [:When, :Then, :Given].include?(child_sexp[2])
regexp = child_sexp[3][1] && child_sexp[3][1][1]
@steps << Step.new(regexp, file, child_sexp.line)
else
sexp.each do |child_sexp|
extract_steps(child_sexp)
end
end
end
end
input_text = ARGV[0].strip.gsub(/(When|Then|Given|And) */, "")
files = Dir["features/step_definitions/**/*_steps.rb"]
steps = []
files.each do |file|
steps.concat(StepParser.new(file).steps)
end
steps.each do |step|
if step.match?(input_text)
puts "#{step.file}:#{step.line}"
end
end