hash_syntax 1.0.0

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Michael Edgar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ = hash_syntax
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Michael Edgar. See LICENSE for details.
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require './lib/hash_syntax/version'
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "hash_syntax"
9
+ gem.summary = %Q{Converts Ruby files to and from Ruby 1.9's Hash syntax}
10
+ gem.description = %Q{The new label style for Ruby 1.9's literal hash keys
11
+ is somewhat controversial. This tool seamlessly converts Ruby files between
12
+ the old and the new syntaxes.}
13
+ gem.email = "michael.j.edgar@dartmouth.edu"
14
+ gem.homepage = "http://github.com/michaeledgar/hash_syntax"
15
+ gem.authors = ["Michael Edgar"]
16
+ gem.add_dependency 'object_regex', '~> 1.0.1'
17
+ gem.add_dependency 'trollop', '~> 1.16.2'
18
+ gem.add_development_dependency 'rspec', '>= 2.3.0'
19
+ gem.add_development_dependency "yard", ">= 0"
20
+ gem.version = HashSyntax::Version::STRING
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ require 'rspec/core/rake_task'
28
+ RSpec::Core::RakeTask.new(:spec) do |spec|
29
+ spec.pattern = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ task :spec => :check_dependencies
33
+
34
+ task :default => :spec
35
+
36
+ begin
37
+ require 'yard'
38
+ YARD::Rake::YardocTask.new
39
+ rescue LoadError
40
+ task :yardoc do
41
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby -w
2
+
3
+ require 'rubygems'
4
+ require 'hash_syntax'
5
+ HashSyntax::Runner.new.run!
@@ -0,0 +1,65 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{hash_syntax}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Michael Edgar}]
12
+ s.date = %q{2011-06-24}
13
+ s.description = %q{The new label style for Ruby 1.9's literal hash keys
14
+ is somewhat controversial. This tool seamlessly converts Ruby files between
15
+ the old and the new syntaxes.}
16
+ s.email = %q{michael.j.edgar@dartmouth.edu}
17
+ s.executables = [%q{hash_syntax}]
18
+ s.extra_rdoc_files = [
19
+ "LICENSE",
20
+ "README.rdoc"
21
+ ]
22
+ s.files = [
23
+ ".document",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "bin/hash_syntax",
28
+ "hash_syntax.gemspec",
29
+ "lib/hash_syntax.rb",
30
+ "lib/hash_syntax/runner.rb",
31
+ "lib/hash_syntax/token.rb",
32
+ "lib/hash_syntax/transformer.rb",
33
+ "lib/hash_syntax/version.rb",
34
+ "spec/hash_syntax_spec.rb",
35
+ "spec/spec.opts",
36
+ "spec/spec_helper.rb",
37
+ "spec/transformer_spec.rb"
38
+ ]
39
+ s.homepage = %q{http://github.com/michaeledgar/hash_syntax}
40
+ s.require_paths = [%q{lib}]
41
+ s.rubygems_version = %q{1.8.5}
42
+ s.summary = %q{Converts Ruby files to and from Ruby 1.9's Hash syntax}
43
+
44
+ if s.respond_to? :specification_version then
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_runtime_dependency(%q<object_regex>, ["~> 1.0.1"])
49
+ s.add_runtime_dependency(%q<trollop>, ["~> 1.16.2"])
50
+ s.add_development_dependency(%q<rspec>, [">= 2.3.0"])
51
+ s.add_development_dependency(%q<yard>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<object_regex>, ["~> 1.0.1"])
54
+ s.add_dependency(%q<trollop>, ["~> 1.16.2"])
55
+ s.add_dependency(%q<rspec>, [">= 2.3.0"])
56
+ s.add_dependency(%q<yard>, [">= 0"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<object_regex>, ["~> 1.0.1"])
60
+ s.add_dependency(%q<trollop>, ["~> 1.16.2"])
61
+ s.add_dependency(%q<rspec>, [">= 2.3.0"])
62
+ s.add_dependency(%q<yard>, [">= 0"])
63
+ end
64
+ end
65
+
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby -w
2
+ require 'ripper'
3
+ require 'object_regex'
4
+ require 'trollop'
5
+
6
+ require 'hash_syntax/token'
7
+ require 'hash_syntax/runner'
8
+ require 'hash_syntax/transformer'
9
+ require 'hash_syntax/version'
@@ -0,0 +1,43 @@
1
+ module HashSyntax
2
+ class Runner
3
+
4
+ def run!
5
+ options = gather_options
6
+ validate_options(options)
7
+ files = gather_files
8
+ files.each do |name|
9
+ transformed_file = Transformer.transform(File.read(name), options)
10
+ File.open(name, 'w') { |fp| fp.write(transformed_file) }
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def gather_options
17
+ Trollop::options do
18
+ version HashSyntax::Version::STRING
19
+ banner <<-EOF
20
+ hash_syntax #{HashSyntax::Version::STRING} by Michael Edgar (adgar@carboni.ca)
21
+
22
+ Automatically convert hash symbol syntaxes in your Ruby code.
23
+ EOF
24
+ opt :"to-18", 'Convert to Ruby 1.8 syntax (:key => value)', :short => '-o'
25
+ opt :"to-19", 'Convert to Ruby 1.9 syntax (key: value)', :short => '-n'
26
+ end
27
+ end
28
+
29
+ def validate_options(opts)
30
+ Trollop::die 'Must specify --to_18 or --to_19' unless opts[:"to-18"] or opts[:"to-19"]
31
+ end
32
+
33
+ AUTO_SUBDIRS = %w(app ext features lib spec test)
34
+
35
+ def gather_files
36
+ if ARGV.empty?
37
+ AUTO_SUBDIRS.map { |dir| Dir["#{Dir.pwd}/#{dir}/**/*.rb"] }.flatten
38
+ else
39
+ ARGV
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ module HashSyntax
2
+ Token = Struct.new(:type, :body, :line, :col) do
3
+ # Unpacks the token from Ripper and breaks it into its separate components.
4
+ #
5
+ # @param [Array<Array<Integer, Integer>, Symbol, String>] token the token
6
+ # from Ripper that we're wrapping
7
+ def initialize(token)
8
+ (self.line, self.col), self.type, self.body = token
9
+ end
10
+
11
+ def width
12
+ body.size
13
+ end
14
+
15
+ def reg_desc
16
+ if type == :on_op && body == '=>'
17
+ 'hashrocket'
18
+ else
19
+ type.to_s.sub(/^on_/, '')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,70 @@
1
+ module HashSyntax
2
+ module Transformer
3
+ MATCH_18 = ObjectRegex.new('symbeg (ident | kw) sp? hashrocket')
4
+ MATCH_19 = ObjectRegex.new('label')
5
+
6
+ extend self
7
+
8
+ def transform(input_text, options)
9
+ tokens = extract_tokens(input_text)
10
+ if options[:"to-18"]
11
+ transform_to_18(input_text, tokens, options)
12
+ elsif options[:"to-19"]
13
+ transform_to_19(input_text, tokens, options)
14
+ else
15
+ raise ArgumentError.new('Either :to_18 or :to_19 must be specified.')
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def extract_tokens(text)
22
+ swizzle_parser_flags do
23
+ Ripper.lex(text).map { |token| Token.new(token) }
24
+ end
25
+ end
26
+
27
+ def swizzle_parser_flags
28
+ old_w = $-w
29
+ old_v = $-v
30
+ old_d = $-d
31
+ $-w = $-v = $-d = false
32
+ yield
33
+ ensure
34
+ $-w = old_w
35
+ $-v = old_v
36
+ $-d = old_d
37
+ end
38
+
39
+ def transform_to_18(input_text, tokens, options)
40
+ lines = input_text.lines.to_a # eagerly expand lines
41
+ matches = MATCH_19.all_matches(tokens)
42
+ line_adjustments = Hash.new(0)
43
+ matches.each do |label_list|
44
+ label = label_list.first
45
+ lines[label.line - 1][label.col + line_adjustments[label.line],label.width] = ":#{label.body[0..-2]} =>"
46
+ line_adjustments[label.line] += 3 # " =>" is inserted and is 3 chars
47
+ end
48
+ lines.join
49
+ end
50
+
51
+ def transform_to_19(input_text, tokens, options)
52
+ lines = input_text.lines.to_a # eagerly expand lines
53
+ matches = MATCH_18.all_matches(tokens)
54
+ line_adjustments = Hash.new(0)
55
+ matches.each do |match_tokens|
56
+ symbeg, ident, *spacing_and_comments, rocket = match_tokens
57
+ lines[symbeg.line - 1][symbeg.col + line_adjustments[symbeg.line],1] = ''
58
+ lines[ident.line - 1].insert(ident.col + line_adjustments[ident.line] + ident.width - 1, ':')
59
+ lines[rocket.line - 1][rocket.col + line_adjustments[rocket.line],2] = ''
60
+ if spacing_and_comments.last != nil && spacing_and_comments.last.type == :on_sp
61
+ lines[rocket.line - 1][rocket.col + line_adjustments[rocket.line] - 1,1] = ''
62
+ line_adjustments[rocket.line] -= 3 # chomped " =>"
63
+ else
64
+ line_adjustments[rocket.line] -= 2 # only chomped the "=>"
65
+ end
66
+ end
67
+ lines.join
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,14 @@
1
+ module HashSyntax
2
+ module Version
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ PATCH = 0
6
+ BUILD = ''
7
+
8
+ if BUILD.empty?
9
+ STRING = [MAJOR, MINOR, PATCH].compact.join('.')
10
+ else
11
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe "HashSyntax" do
4
+ it "has a version" do
5
+ HashSyntax::Version::STRING.should be >= "1.0.0"
6
+ end
7
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'hash_syntax'
4
+ require 'rspec'
5
+ require 'rspec/autorun'
6
+
7
+ RSpec::Matchers.define :transform_to do |output, target|
8
+ match do |input|
9
+ @result = HashSyntax::Transformer.transform(input, target => true)
10
+ @result == output
11
+ end
12
+
13
+ failure_message_for_should do |input|
14
+ "expected '#{input}' to correct to #{output}, not #{@result}"
15
+ end
16
+
17
+ diffable
18
+ end
19
+
20
+ RSpec.configure do |config|
21
+
22
+ end
@@ -0,0 +1,88 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe HashSyntax::Transformer do
4
+ describe 'transforming from 1.8 to 1.9 syntax' do
5
+ it 'can transform a simple hash' do
6
+ 'x = {:foo => :bar}'.should transform_to('x = {foo: :bar}', :to_19)
7
+ end
8
+
9
+ it 'transforms all hashes in a block of code' do
10
+ input = %q{
11
+ with_jumps_redirected(:break => ensure_body[1], :redo => ensure_body[1], :next => ensure_body[1],
12
+ :return => ensure_body[1], :rescue => ensure_body[1],
13
+ :yield_fail => ensure_body[1]) do
14
+ rescue_target, yield_fail_target =
15
+ build_rescue_target(node, result, rescue_body, ensure_block,
16
+ current_rescue, current_yield_fail)
17
+ walk_body_with_rescue_target(result, body, body_block, rescue_target, yield_fail_target)
18
+ end
19
+ }
20
+ output = %q{
21
+ with_jumps_redirected(break: ensure_body[1], redo: ensure_body[1], next: ensure_body[1],
22
+ return: ensure_body[1], rescue: ensure_body[1],
23
+ yield_fail: ensure_body[1]) do
24
+ rescue_target, yield_fail_target =
25
+ build_rescue_target(node, result, rescue_body, ensure_block,
26
+ current_rescue, current_yield_fail)
27
+ walk_body_with_rescue_target(result, body, body_block, rescue_target, yield_fail_target)
28
+ end
29
+ }
30
+ input.should transform_to(output, :to_19)
31
+ end
32
+
33
+ it 'transforms all hashes in a block of code without minding tight spacing' do
34
+ input = %q{
35
+ with_jumps_redirected(:break=>ensure_body[1], :redo=>ensure_body[1], :next=>ensure_body[1],
36
+ :return=>ensure_body[1], :rescue=>ensure_body[1],
37
+ :yield_fail=>ensure_body[1]) do
38
+ rescue_target, yield_fail_target =
39
+ build_rescue_target(node, result, rescue_body, ensure_block,
40
+ current_rescue, current_yield_fail)
41
+ walk_body_with_rescue_target(result, body, body_block, rescue_target, yield_fail_target)
42
+ end
43
+ }
44
+ output = %q{
45
+ with_jumps_redirected(break:ensure_body[1], redo:ensure_body[1], next:ensure_body[1],
46
+ return:ensure_body[1], rescue:ensure_body[1],
47
+ yield_fail:ensure_body[1]) do
48
+ rescue_target, yield_fail_target =
49
+ build_rescue_target(node, result, rescue_body, ensure_block,
50
+ current_rescue, current_yield_fail)
51
+ walk_body_with_rescue_target(result, body, body_block, rescue_target, yield_fail_target)
52
+ end
53
+ }
54
+ input.should transform_to(output, :to_19)
55
+ end
56
+
57
+ end
58
+
59
+ describe 'transforming from 1.9 to 1.8 syntax' do
60
+ it 'can transform a simple hash' do
61
+ 'x = {foo: :bar}'.should transform_to('x = {:foo => :bar}', :to_18)
62
+ end
63
+
64
+ it 'transforms all hashes in a block of code' do
65
+ input = %q{
66
+ with_jumps_redirected(break: ensure_body[1], redo: ensure_body[1], next: ensure_body[1],
67
+ return: ensure_body[1], rescue: ensure_body[1],
68
+ yield_fail: ensure_body[1]) do
69
+ rescue_target, yield_fail_target =
70
+ build_rescue_target(node, result, rescue_body, ensure_block,
71
+ current_rescue, current_yield_fail)
72
+ walk_body_with_rescue_target(result, body, body_block, rescue_target, yield_fail_target)
73
+ end
74
+ }
75
+ output = %q{
76
+ with_jumps_redirected(:break => ensure_body[1], :redo => ensure_body[1], :next => ensure_body[1],
77
+ :return => ensure_body[1], :rescue => ensure_body[1],
78
+ :yield_fail => ensure_body[1]) do
79
+ rescue_target, yield_fail_target =
80
+ build_rescue_target(node, result, rescue_body, ensure_block,
81
+ current_rescue, current_yield_fail)
82
+ walk_body_with_rescue_target(result, body, body_block, rescue_target, yield_fail_target)
83
+ end
84
+ }
85
+ input.should transform_to(output, :to_18)
86
+ end
87
+ end
88
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hash_syntax
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 1.0.0
6
+ platform: ruby
7
+ authors:
8
+ - Michael Edgar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-24 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: object_regex
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.1
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: trollop
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 1.16.2
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: rspec
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 2.3.0
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: yard
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ description: |-
60
+ The new label style for Ruby 1.9's literal hash keys
61
+ is somewhat controversial. This tool seamlessly converts Ruby files between
62
+ the old and the new syntaxes.
63
+ email: michael.j.edgar@dartmouth.edu
64
+ executables:
65
+ - hash_syntax
66
+ extensions: []
67
+
68
+ extra_rdoc_files:
69
+ - LICENSE
70
+ - README.rdoc
71
+ files:
72
+ - .document
73
+ - LICENSE
74
+ - README.rdoc
75
+ - Rakefile
76
+ - bin/hash_syntax
77
+ - hash_syntax.gemspec
78
+ - lib/hash_syntax.rb
79
+ - lib/hash_syntax/runner.rb
80
+ - lib/hash_syntax/token.rb
81
+ - lib/hash_syntax/transformer.rb
82
+ - lib/hash_syntax/version.rb
83
+ - spec/hash_syntax_spec.rb
84
+ - spec/spec.opts
85
+ - spec/spec_helper.rb
86
+ - spec/transformer_spec.rb
87
+ homepage: http://github.com/michaeledgar/hash_syntax
88
+ licenses: []
89
+
90
+ post_install_message:
91
+ rdoc_options: []
92
+
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: "0"
107
+ requirements: []
108
+
109
+ rubyforge_project:
110
+ rubygems_version: 1.8.5
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: Converts Ruby files to and from Ruby 1.9's Hash syntax
114
+ test_files: []
115
+