hss 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +5 -0
  5. data/.travis.yml +14 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +71 -0
  8. data/README.md +44 -22
  9. data/Rakefile +19 -1
  10. data/bin/hss +14 -15
  11. data/hss.gemspec +12 -2
  12. data/lib/helpers/command.rb +14 -4
  13. data/lib/helpers/default.rb +8 -4
  14. data/lib/helpers/expand.rb +10 -4
  15. data/lib/helpers/external.rb +21 -0
  16. data/lib/helpers/shortcut.rb +10 -4
  17. data/lib/hss.rb +91 -51
  18. data/lib/version.rb +6 -0
  19. data/spec/helpers/command_spec.rb +27 -0
  20. data/spec/helpers/default_spec.rb +15 -0
  21. data/spec/helpers/expand_spec.rb +18 -0
  22. data/spec/helpers/external_spec.rb +28 -0
  23. data/spec/helpers/shortcut_spec.rb +18 -0
  24. data/spec/hss_spec.rb +120 -0
  25. data/spec/spec_helper.rb +10 -0
  26. data/spec/test/bad_helpers/module.rb +2 -0
  27. data/spec/test/config.yml +73 -0
  28. data/spec/test/external_test.yml +7 -0
  29. data/spec/test/good_helpers/default.rb +8 -0
  30. data/spec/test/good_helpers/shortcut.rb +8 -0
  31. data/spec/test/incomplete.yml +6 -0
  32. data/spec/test/invalid.yml +8 -0
  33. data/vendor/cache/ast-1.1.0.gem +0 -0
  34. data/vendor/cache/coveralls-0.7.0.gem +0 -0
  35. data/vendor/cache/diff-lcs-1.2.5.gem +0 -0
  36. data/vendor/cache/docile-1.1.0.gem +0 -0
  37. data/vendor/cache/fuubar-1.2.1.gem +0 -0
  38. data/vendor/cache/hashr-0.0.22.gem +0 -0
  39. data/vendor/cache/mime-types-2.0.gem +0 -0
  40. data/vendor/cache/multi_json-1.8.2.gem +0 -0
  41. data/vendor/cache/parser-2.1.0.pre1.gem +0 -0
  42. data/vendor/cache/powerpack-0.0.9.gem +0 -0
  43. data/vendor/cache/rainbow-1.1.4.gem +0 -0
  44. data/vendor/cache/rake-10.1.0.gem +0 -0
  45. data/vendor/cache/rest-client-1.6.7.gem +0 -0
  46. data/vendor/cache/rspec-2.14.1.gem +0 -0
  47. data/vendor/cache/rspec-core-2.14.7.gem +0 -0
  48. data/vendor/cache/rspec-expectations-2.14.4.gem +0 -0
  49. data/vendor/cache/rspec-instafail-0.2.4.gem +0 -0
  50. data/vendor/cache/rspec-mocks-2.14.4.gem +0 -0
  51. data/vendor/cache/rubocop-0.15.0.gem +0 -0
  52. data/vendor/cache/ruby-progressbar-1.2.0.gem +0 -0
  53. data/vendor/cache/simplecov-0.8.2.gem +0 -0
  54. data/vendor/cache/simplecov-html-0.8.0.gem +0 -0
  55. data/vendor/cache/slop-3.4.7.gem +0 -0
  56. data/vendor/cache/term-ansicolor-1.2.2.gem +0 -0
  57. data/vendor/cache/thor-0.18.1.gem +0 -0
  58. data/vendor/cache/tins-0.13.1.gem +0 -0
  59. data/vendor/cache/travis-lint-1.7.0.gem +0 -0
  60. metadata +167 -8
  61. data/test.conf +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1daa6c499987f664f1debc997165bd07e4d4d199
4
- data.tar.gz: 1e85d0b28020d648c2496bef51074796fcda9312
3
+ metadata.gz: 24849b698b736574e86170ba2249d9a937b509f0
4
+ data.tar.gz: ffc1254913b1c7c0ae0ad9a1ab90335a10149f4e
5
5
  SHA512:
6
- metadata.gz: 0495ca1ce274046ecd6f484d3c9da982125e11feaf09f53eadfa254710c3ae98b1579d5196a1da87d020725806bdf89a1d07ec0be1987b88ebf0abecbe27d711
7
- data.tar.gz: f1de32083e1c9962d6ad34e752aefc24b2926c343a790cd885643af68cba0421a64a07f46dcf5cad0cfc03566a015d584a3d704280687745ca957aa6753bdf45
6
+ metadata.gz: 96192df55e26bd41698d3a8d5f612710b2c29770e847f7befa678032dad7dc26fd740d11eccdbe798d8a30f474aa08744544f4234651e739bdf20950c801e67e
7
+ data.tar.gz: 9cd091bd67d04f4af7478891a093f40dabf39e67055f07a23e0ab46995e04eeb7d118de14e80476c7692dec13525677bf5617c1d2e6cab3ac575f9aa5e55fd28
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
- config.yml
2
- *.gem
1
+ pkg/*.gem
2
+ coverage/
3
+ .coveralls.yml
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format Fuubar
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ AllCops:
2
+ Excludes:
3
+ - spec/test/bad_helpers/module.rb
4
+ Encoding:
5
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - ruby-head
5
+ - 2.0.0
6
+ - 1.9.3
7
+ notifications:
8
+ email: false
9
+ irc:
10
+ channels:
11
+ - ircs://irc.oftc.net:6697#akerl
12
+ channel_key: sekrit
13
+ template:
14
+ - '%{repository}/%{branch}/%{build_number}: %{message} -- %{build_url}'
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,71 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ hss (0.2.5)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (1.1.0)
10
+ coveralls (0.7.0)
11
+ multi_json (~> 1.3)
12
+ rest-client
13
+ simplecov (>= 0.7)
14
+ term-ansicolor
15
+ thor
16
+ diff-lcs (1.2.5)
17
+ docile (1.1.0)
18
+ fuubar (1.2.1)
19
+ rspec (~> 2.0)
20
+ rspec-instafail (~> 0.2.0)
21
+ ruby-progressbar (~> 1.0)
22
+ hashr (0.0.22)
23
+ mime-types (2.0)
24
+ multi_json (1.8.2)
25
+ parser (2.1.0.pre1)
26
+ ast (~> 1.1)
27
+ slop (~> 3.4, >= 3.4.5)
28
+ powerpack (0.0.9)
29
+ rainbow (1.1.4)
30
+ rake (10.1.0)
31
+ rest-client (1.6.7)
32
+ mime-types (>= 1.16)
33
+ rspec (2.14.1)
34
+ rspec-core (~> 2.14.0)
35
+ rspec-expectations (~> 2.14.0)
36
+ rspec-mocks (~> 2.14.0)
37
+ rspec-core (2.14.7)
38
+ rspec-expectations (2.14.4)
39
+ diff-lcs (>= 1.1.3, < 2.0)
40
+ rspec-instafail (0.2.4)
41
+ rspec-mocks (2.14.4)
42
+ rubocop (0.15.0)
43
+ parser (~> 2.0)
44
+ powerpack (~> 0.0.6)
45
+ rainbow (>= 1.1.4)
46
+ ruby-progressbar (1.2.0)
47
+ simplecov (0.8.2)
48
+ docile (~> 1.1.0)
49
+ multi_json
50
+ simplecov-html (~> 0.8.0)
51
+ simplecov-html (0.8.0)
52
+ slop (3.4.7)
53
+ term-ansicolor (1.2.2)
54
+ tins (~> 0.8)
55
+ thor (0.18.1)
56
+ tins (0.13.1)
57
+ travis-lint (1.7.0)
58
+ hashr (~> 0.0.22)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ coveralls
65
+ fuubar
66
+ hss!
67
+ parser (~> 2.1.0.pre1)
68
+ rake
69
+ rspec
70
+ rubocop
71
+ travis-lint
data/README.md CHANGED
@@ -2,21 +2,19 @@ hss
2
2
  =========
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/hss.png)](http://badge.fury.io/rb/hss)
5
- [![Stories in Ready](https://badge.waffle.io/akerl/hss.png)](http://waffle.io/akerl/hss)
5
+ [![Dependency Status](https://gemnasium.com/akerl/hss.png)](https://gemnasium.com/akerl/hss)
6
+ [![Code Climate](https://codeclimate.com/github/akerl/hss.png)](https://codeclimate.com/github/akerl/hss)
7
+ [![Coverage Status](https://coveralls.io/repos/akerl/hss/badge.png)](https://coveralls.io/r/akerl/hss)
8
+ [![Build Status](https://travis-ci.org/akerl/hss.png?branch=master)](https://travis-ci.org/akerl/hss)
6
9
 
7
10
  SSH helper that uses regex and fancy expansion to dynamically manage SSH shortcuts
8
11
 
9
- ## Usage
10
-
11
- 1. Install as per the Installation section below
12
- 2. Set your configuration yaml up as desired (See Configuration below)
13
- 3. Run `hss help` for a list of available commands
14
- 4. Run `hss $command` to do that thing
15
-
16
12
  ## Installation
17
13
 
18
- gem install hss
19
- ln -s /path/to/your/config.yml ~/.hss.yml
14
+ ```
15
+ gem install hss
16
+ ln -s /path/to/your/config.yml ~/.hss.yml
17
+ ```
20
18
 
21
19
  ## Configuration
22
20
 
@@ -28,26 +26,50 @@ SSH helper that uses regex and fancy expansion to dynamically manage SSH shortcu
28
26
  * Use matching to collect things you want to use in the expanded form
29
27
  * long: Expanded form of this shortcut ("root@#$1.example.org")
30
28
  * This will be evaluated using Ruby's string interpolation, so you can use "#{var}", "#$1", "#{function()}", etc.
31
- 3. Other helpers are available for use in long forms
32
- * expand(x): Uses the "expansions" section of the config. Format for this section is a hash of lists, as such
33
- expansions:
34
- expanded_form:
35
- - short_form1
36
- - short_form2
37
- - shrtfrm3
29
+ 3. Helpers are available for use in long forms
30
+ * expand(x): Uses the "expansions" section of the config. Format for this section is a hash of lists, as such:
31
+
32
+ ```
33
+ expansions:
34
+ expanded_form:
35
+ - short_form1
36
+ - short_form2
37
+ - shrtfrm3
38
+ ```
39
+
38
40
  * shortcut(x): Uses the "shortcuts" section of the config. Format for this section is a hash of strings, as such
39
- shortcuts:
40
- short1: expand to this
41
- other_short: 'expand to something else!'
41
+
42
+ ```
43
+ shortcuts:
44
+ short1: expand to this
45
+ other_short: 'expand to something else!'
46
+ ```
47
+
42
48
  * command(x): Runs the given string as a command and uses the output for the expanded form
43
49
  * default(x, y): If x is not nil, uses x. If it's nil, use y
50
+ * external(source, key): Loads source as a YAML file and looks for the given key. The YAML should be made of hashes (you can nest them) and the key should be dot-separated:
51
+
52
+ ```
53
+ fish:
54
+ color: blue # accessible with key = 'fish.color'
55
+ alpha:
56
+ dog: sparky
57
+ cat: grouchy # accessible with key 'fish.alpha.cat'
58
+ ```
59
+
60
+ ## Usage
61
+
62
+ 1. Run `hss help` for a list of available commands
63
+ 2. Run `hss $command` to do that thing
44
64
 
45
65
  ## Debugging
46
66
 
47
67
  If you want hss to print the command it would have run rather than executing it, you just need to set the HSS\_DEBUG environment variable to something:
48
68
 
49
- export HSS_DEBUG=foo
50
- hss bar # will print rather than exec
69
+ ```
70
+ export HSS_DEBUG=foo
71
+ hss bar # will print rather than exec
72
+ ```
51
73
 
52
74
  ## License
53
75
 
data/Rakefile CHANGED
@@ -1,2 +1,20 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ desc 'Run tests'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ desc 'Run Rubocop on the gem'
9
+ Rubocop::RakeTask.new(:rubocop) do |task|
10
+ task.patterns = ['lib/**/*.rb', 'spec/*.rb', 'spec/helpers/*.rb', 'bin/*']
11
+ task.fail_on_error = true
12
+ end
13
+
14
+ desc 'Run travis-lint on .travis.yml'
15
+ task :travislint do
16
+ fail 'There is an issue with your .travis.yml' unless system('travis-lint')
17
+ end
18
+
19
+ task default: [:spec, :travislint, :rubocop, :build, :install]
2
20
 
data/bin/hss CHANGED
@@ -2,24 +2,23 @@
2
2
 
3
3
  require 'hss'
4
4
 
5
- My_Handler = HSS::Handler.new ENV['HSS_CONFIG']
5
+ My_Handler = HSS::Handler.new(config: ENV['HSS_CONFIG'])
6
6
 
7
7
  if ARGV == ['version']
8
- puts HSS::Version
9
- exit
10
- elsif ARGV == ['help'] or ARGV.empty?
11
- puts 'How to use:'
12
- puts '(what you type) -> (where it takes you)'
13
- My_Handler.patterns.each { |pattern| puts pattern['example'] }
14
- exit
8
+ puts HSS::Version
9
+ exit
10
+ elsif ARGV == ['help'] || ARGV.empty?
11
+ puts 'How to use:'
12
+ puts '(what you type) -> (where it takes you)'
13
+ My_Handler.patterns.each { |pattern| puts pattern['example'] }
14
+ exit
15
15
  end
16
16
 
17
- Short_Host = ARGV.delete_at( ARGV.find_index { |x| x[0, 1] != '-' } || 0 )
18
- Args = ARGV.inject('') { |memo, obj| memo += " '" + obj.gsub(/([$"])/, '\1') + "'" }
19
- Command = (ENV.include? 'HSS_DEBUG') ? 'echo ssh' : 'ssh'
17
+ short_host = ARGV.delete_at(ARGV.find_index { |x| x[0, 1] != '-' } || 0)
18
+ args = ARGV.reduce('') { |a, e| a + " '" + e.gsub(/([$"])/, '\1') + "'" }
19
+ command = ENV.include?('HSS_DEBUG') ? 'echo ssh' : 'ssh'
20
20
 
21
- Long_Host = My_Handler.handle Short_Host
22
-
23
- $stdout.syswrite "\033]0;#{Short_Host}\007" if $stdout.tty? and $stdin.tty?
24
- exec "#{Command} #{Long_Host} #{Args}"
21
+ long_host = My_Handler.handle short_host
25
22
 
23
+ $stdout.syswrite "\033]0;#{short_host}\007" if $stdout.tty? && $stdin.tty?
24
+ exec "#{command} #{long_host} #{args}"
data/hss.gemspec CHANGED
@@ -1,16 +1,26 @@
1
- require File.join(Dir.pwd, 'lib/hss.rb')
1
+ $:.unshift File.expand_path('../lib/', __FILE__)
2
+ require 'version'
2
3
 
3
4
  Gem::Specification.new do |s|
4
5
  s.name = 'hss'
5
- s.version = HSS::Version
6
+ s.version = HSS::VERSION
6
7
  s.date = Time.now.strftime("%Y-%m-%d")
7
8
  s.summary = 'SSH helper'
8
9
  s.description = 'Regex-based SSH shortcut tool'
9
10
  s.authors = ['Les Aker']
10
11
  s.email = 'me@lesaker.org'
11
12
  s.files = `git ls-files`.split
13
+ s.test_files = `git ls-files spec/*`.split
12
14
  s.executables = ['hss']
13
15
  s.homepage = 'https://github.com/akerl/hss'
14
16
  s.license = 'MIT'
17
+
18
+ s.add_development_dependency 'rubocop'
19
+ s.add_development_dependency 'travis-lint'
20
+ s.add_development_dependency 'rake'
21
+ s.add_development_dependency 'coveralls'
22
+ s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'fuubar'
24
+ s.add_development_dependency 'parser', '~> 2.1.0.pre1'
15
25
  end
16
26
 
@@ -1,6 +1,16 @@
1
+ require 'English'
2
+
3
+ ##
4
+ # Runs a shell command and returns the output
5
+
1
6
  class HSS::Parser
2
- def command(input)
3
- return IO.popen(input) { |cmd| cmd.read }
4
- end
5
- end
7
+ private
6
8
 
9
+ def command(input)
10
+ result = IO.popen(input) { |cmd| cmd.read.chomp }
11
+ fail "Command failed: #{input}" unless $CHILD_STATUS == 0
12
+ result
13
+ rescue Errno::ENOENT
14
+ raise "Command not found: #{input}"
15
+ end
16
+ end
@@ -1,6 +1,10 @@
1
+ ##
2
+ # Provides a helper to have default values
3
+
1
4
  class HSS::Parser
2
- def default(a, b)
3
- (a.nil? or a.empty?) ? b : a
4
- end
5
- end
5
+ private
6
6
 
7
+ def default(a, b)
8
+ a.nil? || a.empty? ? b : a
9
+ end
10
+ end
@@ -1,7 +1,13 @@
1
+ ##
2
+ # Expand a shortcode based the config hash
3
+
1
4
  class HSS::Parser
2
- def expand(input)
3
- @config['expansions'].each { |long, shorts| return long if shorts.include? input }
4
- raise NameError, "No expansion found for: #{input}"
5
+ private
6
+
7
+ def expand(input)
8
+ @config['expansions'].each do |long, shorts|
9
+ return long if shorts.include? input
5
10
  end
11
+ fail NameError, "No expansion found for: #{input}"
12
+ end
6
13
  end
7
-
@@ -0,0 +1,21 @@
1
+ require 'yaml'
2
+
3
+ ##
4
+ # Load values from an external YAML hash
5
+
6
+ class HSS::Parser
7
+ private
8
+
9
+ def external(source, key)
10
+ begin
11
+ config = open(File.expand_path(source)) { |f| YAML.load f.read }
12
+ rescue Psych::SyntaxError, Errno::ENOENT
13
+ raise "Failed to open YAML file: #{source}"
14
+ end
15
+ begin
16
+ key.split('.').reduce(config) { |a, e| a[e] } || fail
17
+ rescue
18
+ raise NameError, "Key not found in YAML: #{key}"
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,12 @@
1
+ ##
2
+ # Allow shortcut expansion from the config
3
+
1
4
  class HSS::Parser
2
- def shortcut(input)
3
- return @config['shortcuts'][input]
4
- end
5
- end
5
+ private
6
6
 
7
+ def shortcut(input)
8
+ @config['shortcuts'][input] || fail
9
+ rescue
10
+ raise NameError, "Shortcut does not exist #{input}"
11
+ end
12
+ end
data/lib/hss.rb CHANGED
@@ -1,68 +1,108 @@
1
1
  require 'yaml'
2
2
  require 'pathname'
3
- require 'erb'
3
+ require 'version'
4
+
5
+ ##
6
+ # HSS module provides a helper for SSH shortcuts
4
7
 
5
8
  module HSS
6
- Version = '0.2.4'
7
- Default_Config = '~/.hss.yml'
8
- Default_Library = Pathname.new(__FILE__).realpath.split()[0].to_s + '/helpers'
9
+ DEFAULT_CONFIG = '~/.hss.yml'
10
+ DEFAULT_LIBRARY = Pathname.new(__FILE__).realpath.split[0].to_s + '/helpers'
9
11
 
10
- class << self
11
- def new(*args)
12
- HSS::Handler.new(*args)
13
- end
12
+ class << self
13
+ ##
14
+ # Insert a helper .new() method for creating a new Cache object
15
+
16
+ def new(*args)
17
+ HSS::Handler.new(*args)
14
18
  end
19
+ end
15
20
 
16
- class Handler
17
- attr_reader :patterns, :config
21
+ ##
22
+ # Handlers load configurations and control their use
18
23
 
19
- def initialize(config_path = nil, helper_path = nil)
20
- load_config(config_path)
21
- load_parser(helper_path)
22
- end
24
+ class Handler
25
+ attr_reader :patterns, :config, :helpers
23
26
 
24
- def load_config(config_path = nil)
25
- begin
26
- @config = YAML.load open(File.expand_path(config_path || HSS::Default_Config)).read
27
- @patterns = @config.delete('patterns')
28
- rescue
29
- raise "Failed to load config: #{config_path}"
30
- end
31
- end
27
+ ## Make a new handler with a config and parser
32
28
 
33
- def load_parser(helper_path = nil)
34
- Dir::glob((helper_path || HSS::Default_Library) + '/*').each do |helper|
35
- begin
36
- require_relative helper
37
- rescue LoadError
38
- raise LoadError, "Failed to load helper: #{helper}"
39
- end
40
- end
41
- @parser = HSS::Parser.new(@config)
42
- end
29
+ def initialize(params = {})
30
+ params = { config: params } if params.is_a? String
31
+ load_config(params[:config])
32
+ @helpers = []
33
+ load_helpers(params[:helpers])
34
+ @parser = HSS::Parser.new(@config)
35
+ end
43
36
 
44
- def handle(input)
45
- @patterns.each do |pattern|
46
- next unless @parser.check(input, pattern['short'])
47
- return @parser.parse(pattern['long'])
48
- end
49
- raise "Couldn't find a matching host for: #{input}"
50
- end
37
+ ##
38
+ # Check patterns for a match and parse the long form
39
+
40
+ def handle(input)
41
+ @patterns.each do |pattern|
42
+ next unless @parser.check(input, pattern['short'])
43
+ return @parser.parse(pattern['long'])
44
+ end
45
+ fail "Couldn't find a matching host for: #{input}"
51
46
  end
52
47
 
53
- class Parser
54
- def initialize(config)
55
- @config = config
56
- end
48
+ private
57
49
 
58
- def check(input, short_form)
59
- return false unless input.match short_form
60
- @match_data = binding
61
- true
62
- end
63
- def parse(long_form)
64
- eval '"' + long_form + '"', @match_data
50
+ ##
51
+ # Load the config file
52
+
53
+ def load_config(config_path = nil)
54
+ path = File.expand_path(config_path || HSS::DEFAULT_CONFIG)
55
+ @config = YAML.load open(path).read
56
+ @patterns = @config.delete('patterns') || fail
57
+ rescue Psych::SyntaxError, RuntimeError, Errno::ENOENT
58
+ raise "Failed to load config: #{config_path}"
59
+ end
60
+
61
+ ##
62
+ # Load helper modules
63
+
64
+ def load_helpers(helper_path = nil)
65
+ helper_path ||= HSS::DEFAULT_LIBRARY
66
+ helper_path = File.absolute_path(helper_path)
67
+ Dir.glob(helper_path + '/*').each do |helper|
68
+ begin
69
+ require helper
70
+ @helpers << helper
71
+ rescue LoadError, SyntaxError
72
+ raise LoadError, "Failed to load helper: #{helper}"
65
73
  end
74
+ end
75
+ end
76
+ end
77
+
78
+ ##
79
+ # Parser objects exist as containers for helper methods
80
+
81
+ class Parser
82
+ ##
83
+ # The config is scoped here so it is available to helpers
84
+
85
+ def initialize(config)
86
+ @config = config
66
87
  end
67
- end
68
88
 
89
+ ##
90
+ # Check for a match
91
+ # If the input matches, store the context for use in helpers
92
+
93
+ def check(input, short_form)
94
+ return false unless input.match short_form
95
+ x = Regexp.last_match # rubocop:disable UselessSetterCall
96
+ @match_data = binding
97
+ true
98
+ end
99
+
100
+ ##
101
+ # Evaluate the long_form using the stored context
102
+
103
+ def parse(long_form)
104
+ a = eval '%Q{' + long_form + '}', @match_data # rubocop:disable Eval
105
+ a == long_form ? a : parse(a)
106
+ end
107
+ end
108
+ end