watirmark 5.14.16
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.
- data/app_generators/create_project/create_project_generator.rb +115 -0
- data/app_generators/create_project/templates/features/env.rb.erb +8 -0
- data/app_generators/create_project/templates/features/model_steps.rb.erb +9 -0
- data/app_generators/create_project/templates/features/post_error_steps.rb.erb +15 -0
- data/app_generators/create_project/templates/features/sample.feature.erb +5 -0
- data/app_generators/create_project/templates/features/site_steps.rb.erb +7 -0
- data/app_generators/create_project/templates/generators/controller.rb.erb +9 -0
- data/app_generators/create_project/templates/generators/generate.rb.erb +9 -0
- data/app_generators/create_project/templates/generators/model.rb.erb +7 -0
- data/app_generators/create_project/templates/generators/mvc_generator.rb.erb +100 -0
- data/app_generators/create_project/templates/generators/rbeautify.rb.erb +212 -0
- data/app_generators/create_project/templates/generators/view.rb.erb +16 -0
- data/app_generators/create_project/templates/generators/workflow_loader.rb.erb +1 -0
- data/app_generators/create_project/templates/library/base_controller.rb.erb +9 -0
- data/app_generators/create_project/templates/library/base_view.rb.erb +6 -0
- data/app_generators/create_project/templates/library/configuration.rb.erb +6 -0
- data/app_generators/create_project/templates/library/core_libraries.rb.erb +9 -0
- data/app_generators/create_project/templates/library/loader.rb.erb +23 -0
- data/app_generators/create_project/templates/library/page_load_checker.rb.erb +11 -0
- data/app_generators/create_project/templates/library/post_errors_checker.rb.erb +23 -0
- data/app_generators/create_project/templates/library/project_require_file.rb.erb +8 -0
- data/app_generators/create_project/templates/library/search_controller.rb.erb +12 -0
- data/app_generators/create_project/templates/library/workflows.rb.erb +0 -0
- data/app_generators/create_project/templates/project/config.yml.erb +3 -0
- data/app_generators/create_project/templates/project/gemfile.rb.erb +11 -0
- data/app_generators/create_project/templates/project/rakefile.rb.erb +21 -0
- data/bin/etapestry/Gemfile +11 -0
- data/bin/etapestry/config.yml +3 -0
- data/bin/etapestry/features/etapestry_home.feature +5 -0
- data/bin/etapestry/features/step_definitions/model_steps.rb +9 -0
- data/bin/etapestry/features/step_definitions/post_error_steps.rb +15 -0
- data/bin/etapestry/features/step_definitions/site_steps.rb +7 -0
- data/bin/etapestry/features/support/env.rb +8 -0
- data/bin/etapestry/generators/mvc/mvc_generator.rb +100 -0
- data/bin/etapestry/generators/mvc/rbeautify.rb +212 -0
- data/bin/etapestry/generators/mvc/templates/controller.rb.erb +9 -0
- data/bin/etapestry/generators/mvc/templates/model.rb.erb +7 -0
- data/bin/etapestry/generators/mvc/templates/view.rb.erb +16 -0
- data/bin/etapestry/generators/mvc/templates/workflow_loader.rb.erb +1 -0
- data/bin/etapestry/lib/etapestry.rb +8 -0
- data/bin/etapestry/lib/etapestry/checkers/page_load_checker.rb +11 -0
- data/bin/etapestry/lib/etapestry/checkers/post_errors_checker.rb +23 -0
- data/bin/etapestry/lib/etapestry/configuration.rb +6 -0
- data/bin/etapestry/lib/etapestry/core_libraries.rb +9 -0
- data/bin/etapestry/lib/etapestry/loader.rb +23 -0
- data/bin/etapestry/lib/etapestry/site/base_controller.rb +9 -0
- data/bin/etapestry/lib/etapestry/site/base_view.rb +6 -0
- data/bin/etapestry/lib/etapestry/site/search_controller.rb +12 -0
- data/bin/etapestry/lib/etapestry/workflows.rb +0 -0
- data/bin/etapestry/rakefile.rb +21 -0
- data/bin/etapestry/script/generate.rb +9 -0
- data/bin/twitter/features/hashtag_search.feature +93 -0
- data/bin/twitter/features/step_definitions/hashtag_steps.rb +9 -0
- data/bin/twitter/lib/twitter/workflows/search/result_controller.rb +13 -0
- data/bin/twitter/lib/twitter/workflows/search/result_model.rb +5 -0
- data/bin/twitter/lib/twitter/workflows/search/result_view.rb +19 -0
- data/bin/watirmark +10 -0
- data/lib/watirmark.rb +26 -0
- data/lib/watirmark/at_exit.rb +13 -0
- data/lib/watirmark/configuration.rb +201 -0
- data/lib/watirmark/controller/actions.rb +172 -0
- data/lib/watirmark/controller/assertions.rb +116 -0
- data/lib/watirmark/controller/controller.rb +191 -0
- data/lib/watirmark/controller/dialogs.rb +33 -0
- data/lib/watirmark/controller/matcher.rb +19 -0
- data/lib/watirmark/cucumber/cuke_helper.rb +150 -0
- data/lib/watirmark/cucumber/email_helper.rb +103 -0
- data/lib/watirmark/cucumber/env.rb +9 -0
- data/lib/watirmark/cucumber/hooks.rb +16 -0
- data/lib/watirmark/cucumber/model_helper.rb +34 -0
- data/lib/watirmark/cucumber/transforms.rb +55 -0
- data/lib/watirmark/exceptions.rb +15 -0
- data/lib/watirmark/extensions/ruby_extensions.rb +129 -0
- data/lib/watirmark/extensions/webdriver_extensions.rb +150 -0
- data/lib/watirmark/formatters/snapshot_formatter.rb +23 -0
- data/lib/watirmark/loader.rb +87 -0
- data/lib/watirmark/model.rb +3 -0
- data/lib/watirmark/models/cucumber_helper.rb +49 -0
- data/lib/watirmark/models/debug_methods.rb +21 -0
- data/lib/watirmark/models/default_values.rb +21 -0
- data/lib/watirmark/models/factory.rb +168 -0
- data/lib/watirmark/models/factory_method_generators.rb +84 -0
- data/lib/watirmark/models/factory_methods.rb +72 -0
- data/lib/watirmark/models/trait.rb +35 -0
- data/lib/watirmark/models/upload_csv.rb +24 -0
- data/lib/watirmark/page/keyed_element.rb +63 -0
- data/lib/watirmark/page/page.rb +50 -0
- data/lib/watirmark/page/page_definition.rb +187 -0
- data/lib/watirmark/page/process_page.rb +112 -0
- data/lib/watirmark/page/radio_maps.rb +53 -0
- data/lib/watirmark/profile.rb +22 -0
- data/lib/watirmark/rake/smoketest.rb +17 -0
- data/lib/watirmark/screenshot.rb +127 -0
- data/lib/watirmark/session.rb +115 -0
- data/lib/watirmark/version.rb +5 -0
- data/spec/assertions_spec.rb +95 -0
- data/spec/config_spec.rb +82 -0
- data/spec/controller_actions_spec.rb +91 -0
- data/spec/controller_spec.rb +426 -0
- data/spec/controllers_and_models_spec.rb +52 -0
- data/spec/model_factory_spec.rb +568 -0
- data/spec/model_traits_spec.rb +141 -0
- data/spec/page_spec.rb +127 -0
- data/spec/process_page_spec.rb +163 -0
- data/spec/spec_helper.rb +17 -0
- metadata +238 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'rubigen'
|
|
2
|
+
class CreateProjectGenerator < RubiGen::Base
|
|
3
|
+
default_options :author => nil
|
|
4
|
+
attr_reader :name
|
|
5
|
+
|
|
6
|
+
def initialize(runtime_args, runtime_options = {})
|
|
7
|
+
super
|
|
8
|
+
usage if args.empty?
|
|
9
|
+
@name = File.basename(args.shift)
|
|
10
|
+
@destination_root = File.expand_path(@name)
|
|
11
|
+
extract_options
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def manifest
|
|
15
|
+
record do |m|
|
|
16
|
+
create_directories(m)
|
|
17
|
+
create_project_files(m)
|
|
18
|
+
create_library_checker_files(m)
|
|
19
|
+
create_library_site_files(m)
|
|
20
|
+
create_library_toplevel_files(m)
|
|
21
|
+
create_mvc_generators(m)
|
|
22
|
+
create_test_files(m)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create_project_files(manifest)
|
|
27
|
+
manifest.template "project/gemfile.rb.erb", "Gemfile"
|
|
28
|
+
manifest.template "project/config.yml.erb", "config.yml"
|
|
29
|
+
manifest.template "project/rakefile.rb.erb", "rakefile.rb"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def create_library_checker_files(manifest)
|
|
33
|
+
manifest.template "library/page_load_checker.rb.erb", File.join("lib", name, "checkers", "page_load_checker.rb")
|
|
34
|
+
manifest.template "library/post_errors_checker.rb.erb", File.join("lib", name, "checkers", "post_errors_checker.rb")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def create_library_site_files(manifest)
|
|
38
|
+
manifest.template "library/base_controller.rb.erb", File.join("lib", name, "site", "base_controller.rb")
|
|
39
|
+
manifest.template "library/search_controller.rb.erb", File.join("lib", name, "site", "search_controller.rb")
|
|
40
|
+
manifest.template "library/base_view.rb.erb", File.join("lib", name, "site", "base_view.rb")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def create_library_toplevel_files(manifest)
|
|
44
|
+
manifest.template "library/configuration.rb.erb", File.join("lib", name, "configuration.rb")
|
|
45
|
+
manifest.template "library/workflows.rb.erb", File.join("lib", name, "workflows.rb")
|
|
46
|
+
manifest.template "library/core_libraries.rb.erb", File.join("lib", name, "core_libraries.rb")
|
|
47
|
+
manifest.template "library/loader.rb.erb", File.join("lib", name, "loader.rb")
|
|
48
|
+
manifest.template "library/project_require_file.rb.erb", File.join("lib","#{name}.rb")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def create_mvc_generators(manifest)
|
|
52
|
+
manifest.template "generators/generate.rb.erb", File.join("script","generate.rb")
|
|
53
|
+
manifest.template "generators/mvc_generator.rb.erb", File.join("generators","mvc","mvc_generator.rb")
|
|
54
|
+
manifest.template "generators/rbeautify.rb.erb", File.join("generators", "mvc", "rbeautify.rb")
|
|
55
|
+
manifest.template "generators/controller.rb.erb", File.join("generators","mvc","templates","controller.rb.erb")
|
|
56
|
+
manifest.template "generators/model.rb.erb", File.join("generators","mvc","templates","model.rb.erb")
|
|
57
|
+
manifest.template "generators/view.rb.erb", File.join("generators","mvc","templates","view.rb.erb")
|
|
58
|
+
manifest.template "generators/workflow_loader.rb.erb", File.join("generators","mvc","templates","workflow_loader.rb.erb")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def create_test_files(manifest)
|
|
62
|
+
manifest.template "features/model_steps.rb.erb", File.join("features","step_definitions","model_steps.rb")
|
|
63
|
+
manifest.template "features/post_error_steps.rb.erb", File.join("features","step_definitions","post_error_steps.rb")
|
|
64
|
+
manifest.template "features/site_steps.rb.erb", File.join("features","step_definitions","site_steps.rb")
|
|
65
|
+
manifest.template "features/env.rb.erb", File.join("features","support","env.rb")
|
|
66
|
+
manifest.template "features/sample.feature.erb", File.join("features","#{@name}_home.feature")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def create_directories(m)
|
|
70
|
+
BASEDIRS.each { |path| m.directory path }
|
|
71
|
+
create_subdirectories m, File.join('features'), %w(step_definitions support)
|
|
72
|
+
create_subdirectories m, File.join('lib', @name), %w(checkers site workflows)
|
|
73
|
+
create_subdirectories m, File.join('generators', 'mvc'), %w(templates)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def create_subdirectories (m, root, directories)
|
|
77
|
+
m.directory root
|
|
78
|
+
directories.each {|dir| m.directory File.join(root, dir)}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
protected
|
|
83
|
+
def banner
|
|
84
|
+
<<-EOS
|
|
85
|
+
USAGE: #{spec.name} path/for/your/test/create_project project_name [options]
|
|
86
|
+
EOS
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def add_options!(opts)
|
|
90
|
+
opts.separator ''
|
|
91
|
+
opts.separator 'Options:'
|
|
92
|
+
# For each option below, place the default
|
|
93
|
+
# at the top of the file next to "default_options"
|
|
94
|
+
# opts.on("-a", "--author=\"Your Name\"", String,
|
|
95
|
+
# "Some comment about this option",
|
|
96
|
+
# "Default: none") { |options[:author]| }
|
|
97
|
+
opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def extract_options
|
|
101
|
+
# for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
|
|
102
|
+
# Templates can access these value via the attr_reader-generated methods, but not the
|
|
103
|
+
# raw instance variable value.
|
|
104
|
+
# @author = options[:author]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Installation skeleton. Intermediate directories are automatically
|
|
108
|
+
# created so don't sweat their absence here.
|
|
109
|
+
BASEDIRS = %w(
|
|
110
|
+
features
|
|
111
|
+
generators
|
|
112
|
+
lib
|
|
113
|
+
script
|
|
114
|
+
)
|
|
115
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# There are cases where we want a bare model,
|
|
2
|
+
# For example in the API we can use the model to generate the defaults for the API call
|
|
3
|
+
When /I create a model (\[[^\]]+\])$/ do |model|
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
When /I (create|update) a model (\[[^\]]+\]) with values$/ do |action, model, table|
|
|
7
|
+
update_model(model, table)
|
|
8
|
+
end
|
|
9
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Exact matches
|
|
2
|
+
Then /^I should see the error: '?"?([^\/].*)"?'?$/ do |error|
|
|
3
|
+
# Replace carriage returns with a space to make it easier to declare the error
|
|
4
|
+
if Watirmark::Session.instance.post_failure
|
|
5
|
+
Watirmark::Session.instance.post_failure.gsub(/[\r\n]+/, ' ').strip.should == error.strip
|
|
6
|
+
else
|
|
7
|
+
'No POST failure seen!'.should == error
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Pattern matches
|
|
12
|
+
Then /^I should see the error: \/(.+)\/$/ do |error|
|
|
13
|
+
Watirmark::Session.instance.post_failure.gsub(/[\r\n]+/, ' ').should =~ /#{error.gsub!(/[\r\n]+/, ' ')}/
|
|
14
|
+
end
|
|
15
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
|
3
|
+
|
|
4
|
+
require 'rubigen'
|
|
5
|
+
require 'rubigen/scripts/generate'
|
|
6
|
+
|
|
7
|
+
ARGV.shift if %w(--help -h).include?(ARGV[0])
|
|
8
|
+
RubiGen::Base.use_component_sources! [:rubygems]
|
|
9
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'rubigen'
|
|
2
|
+
require 'active_support/inflector'
|
|
3
|
+
require_relative 'rbeautify'
|
|
4
|
+
|
|
5
|
+
class MvcGenerator < RubiGen::Base
|
|
6
|
+
attr_reader :product, :name
|
|
7
|
+
|
|
8
|
+
def initialize(runtime_args, runtime_options = {})
|
|
9
|
+
super
|
|
10
|
+
usage if args.empty?
|
|
11
|
+
@product = args.shift
|
|
12
|
+
@name = args.shift
|
|
13
|
+
usage unless @name && @product
|
|
14
|
+
@destination_root = File.expand_path(File.dirname(__FILE__) + '/../../')
|
|
15
|
+
extract_options
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def workflow_directory
|
|
19
|
+
"lib/<%= name.downcase %>/workflows/#{@product}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def manifest
|
|
23
|
+
record do |m|
|
|
24
|
+
create_directories(m)
|
|
25
|
+
add_mvc_stubs m
|
|
26
|
+
add_loader
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def add_mvc_stubs m
|
|
31
|
+
m.template "model.rb.erb", File.join(workflow_directory, "#{@name}_model.rb")
|
|
32
|
+
m.template "view.rb.erb", File.join(workflow_directory,"#{@name}_view.rb")
|
|
33
|
+
m.template "controller.rb.erb", File.join(workflow_directory,"#{@name}_controller.rb")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def workflow_exists?
|
|
37
|
+
File.directory? "../#{workflow_directory}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_rake_task
|
|
41
|
+
append_to_file "../rakefile.rb" do |f|
|
|
42
|
+
f.puts "RakeHelper.cucumber_task(:#{@product}, \"features/#{@product}/**/*.feature\")"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add_loader
|
|
47
|
+
append_to_file "../lib/<%= name.downcase %>/workflows.rb" do |f|
|
|
48
|
+
f.puts "<%= name.camelize %>::Loader.load_workflow '#{@product.downcase}/#{@name.downcase}'"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def append_to_file name, &block
|
|
53
|
+
File.open(name, 'a+') {|f| yield f}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def create_directories(m)
|
|
57
|
+
m.directory workflow_directory
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def create_modules
|
|
61
|
+
@product.split('/').map{|x| "module #{x.camelize}\n"}.join.strip
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def create_module_end
|
|
65
|
+
@product.split('/').map{|x| "end\n"}.join.strip
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
protected
|
|
69
|
+
def banner
|
|
70
|
+
<<-EOS
|
|
71
|
+
USAGE: #{spec.name} path/for/your/test/mvc workflow_directory name [options]
|
|
72
|
+
EOS
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def after_generate
|
|
76
|
+
mvc_file_path = "#{@destination_root}/#{workflow_directory}/#{@name}"
|
|
77
|
+
RBeautify.new({}).beautify_file("#{mvc_file_path}_model.rb")
|
|
78
|
+
RBeautify.new({}).beautify_file("#{mvc_file_path}_view.rb")
|
|
79
|
+
RBeautify.new({}).beautify_file("#{mvc_file_path}_controller.rb")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def add_options!(opts)
|
|
83
|
+
opts.separator ''
|
|
84
|
+
opts.separator 'Options:'
|
|
85
|
+
# For each option below, place the default
|
|
86
|
+
# at the top of the file next to "default_options"
|
|
87
|
+
# opts.on("-a", "--author=\"Your Name\"", String,
|
|
88
|
+
# "Some comment about this option",
|
|
89
|
+
# "Default: none") { |options[:author]| }
|
|
90
|
+
opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def extract_options
|
|
94
|
+
# for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
|
|
95
|
+
# Templates can access these value via the attr_reader-generated methods, but not the
|
|
96
|
+
# raw instance variable value.
|
|
97
|
+
# @author = options[:author]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/ruby -w
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
=begin
|
|
5
|
+
/***************************************************************************
|
|
6
|
+
* Copyright (C) 2008, Paul Lutus *
|
|
7
|
+
* *
|
|
8
|
+
* This program is free software; you can redistribute it and/or modify *
|
|
9
|
+
* it under the terms of the GNU General Public License as published by *
|
|
10
|
+
* the Free Software Foundation; either version 2 of the License, or *
|
|
11
|
+
* (at your option) any later version. *
|
|
12
|
+
* *
|
|
13
|
+
* This program is distributed in the hope that it will be useful, *
|
|
14
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
15
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
16
|
+
* GNU General Public License for more details. *
|
|
17
|
+
* *
|
|
18
|
+
* You should have received a copy of the GNU General Public License *
|
|
19
|
+
* along with this program; if not, write to the *
|
|
20
|
+
* Free Software Foundation, Inc., *
|
|
21
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
22
|
+
***************************************************************************/
|
|
23
|
+
=end
|
|
24
|
+
|
|
25
|
+
PVERSION = "Version 2.9, 10/24/2008"
|
|
26
|
+
|
|
27
|
+
class RBeautify
|
|
28
|
+
|
|
29
|
+
# indent regexp tests
|
|
30
|
+
|
|
31
|
+
IndentExp = [
|
|
32
|
+
/^module\b/,
|
|
33
|
+
/^class\b/,
|
|
34
|
+
/^if\b/,
|
|
35
|
+
/(=\s*|^)until\b/,
|
|
36
|
+
/(=\s*|^)for\b/,
|
|
37
|
+
/^unless\b/,
|
|
38
|
+
/(=\s*|^)while\b/,
|
|
39
|
+
/(=\s*|^)begin\b/,
|
|
40
|
+
/(^| )case\b/,
|
|
41
|
+
/\bthen\b/,
|
|
42
|
+
/^rescue\b/,
|
|
43
|
+
/^def\b/,
|
|
44
|
+
/\bdo\b/,
|
|
45
|
+
/^else\b/,
|
|
46
|
+
/^elsif\b/,
|
|
47
|
+
/^ensure\b/,
|
|
48
|
+
/\bwhen\b/,
|
|
49
|
+
/\{[^\}]*$/,
|
|
50
|
+
/\[[^\]]*$/
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
# outdent regexp tests
|
|
54
|
+
|
|
55
|
+
OutdentExp = [
|
|
56
|
+
/^rescue\b/,
|
|
57
|
+
/^ensure\b/,
|
|
58
|
+
/^elsif\b/,
|
|
59
|
+
/^end\b/,
|
|
60
|
+
/^else\b/,
|
|
61
|
+
/\bwhen\b/,
|
|
62
|
+
/^[^\{]*\}/,
|
|
63
|
+
/^[^\[]*\]/
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
# user-customizable values
|
|
67
|
+
OPTIONS = {
|
|
68
|
+
tab_string: ' ',
|
|
69
|
+
tab_size: 2
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def initialize(options)
|
|
73
|
+
options = OPTIONS.merge(options)
|
|
74
|
+
@tab_string, @tab_size = options[:tab_string], options[:tab_size]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def rb_make_tab(tab)
|
|
78
|
+
tab < 0 ? "" : (@tab_string * @tab_size * tab)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def rb_add_line(line,tab)
|
|
82
|
+
line.strip!
|
|
83
|
+
line = rb_make_tab(tab) + line if line.length > 0
|
|
84
|
+
line
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def beautify_string(source, path = "")
|
|
88
|
+
comment_block = false
|
|
89
|
+
in_here_doc = false
|
|
90
|
+
here_doc_term = ""
|
|
91
|
+
program_end = false
|
|
92
|
+
multiLine_array = []
|
|
93
|
+
multiLine_str = ""
|
|
94
|
+
tab = 0
|
|
95
|
+
output = []
|
|
96
|
+
source.each_line do |line|
|
|
97
|
+
line.chomp!
|
|
98
|
+
if !program_end
|
|
99
|
+
# detect program end mark
|
|
100
|
+
if line =~ /^__END__$/
|
|
101
|
+
program_end = true
|
|
102
|
+
else
|
|
103
|
+
# combine continuing lines
|
|
104
|
+
if !(line =~ /^\s*#/) && line =~ /[^\\]\\\s*$/
|
|
105
|
+
multiLine_array.push line
|
|
106
|
+
multiLine_str += line.sub(/^(.*)\\\s*$/,"\\1")
|
|
107
|
+
next
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# add final line
|
|
111
|
+
if multiLine_str.length > 0
|
|
112
|
+
multiLine_array.push line
|
|
113
|
+
multiLine_str += line.sub(/^(.*)\\\s*$/,"\\1")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
tline = ((multiLine_str.length > 0) ? multiLine_str : line).strip
|
|
117
|
+
if tline =~ /^=begin/
|
|
118
|
+
comment_block = true
|
|
119
|
+
end
|
|
120
|
+
if in_here_doc
|
|
121
|
+
in_here_doc = false if tline =~ %r{\s*#{here_doc_term}\s*}
|
|
122
|
+
else # not in here_doc
|
|
123
|
+
if tline =~ %r{=\s*<<}
|
|
124
|
+
here_doc_term = tline.sub(%r{.*=\s*<<-?\s*([_|\w]+).*},"\\1")
|
|
125
|
+
in_here_doc = here_doc_term.size > 0
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
if comment_block || program_end || in_here_doc
|
|
131
|
+
# add the line unchanged
|
|
132
|
+
output << line
|
|
133
|
+
else
|
|
134
|
+
comment_line = (tline =~ /^#/)
|
|
135
|
+
if !comment_line
|
|
136
|
+
# throw out sequences that will
|
|
137
|
+
# only sow confusion
|
|
138
|
+
while tline.gsub!(/\{[^\{]*?\}/,"")
|
|
139
|
+
end
|
|
140
|
+
while tline.gsub!(/\[[^\[]*?\]/,"")
|
|
141
|
+
end
|
|
142
|
+
while tline.gsub!(/'.*?'/,"")
|
|
143
|
+
end
|
|
144
|
+
while tline.gsub!(/".*?"/,"")
|
|
145
|
+
end
|
|
146
|
+
while tline.gsub!(/\`.*?\`/,"")
|
|
147
|
+
end
|
|
148
|
+
while tline.gsub!(/\([^\(]*?\)/,"")
|
|
149
|
+
end
|
|
150
|
+
while tline.gsub!(/\/.*?\//,"")
|
|
151
|
+
end
|
|
152
|
+
while tline.gsub!(/%r(.).*?\1/,"")
|
|
153
|
+
end
|
|
154
|
+
# delete end-of-line comments
|
|
155
|
+
tline.sub!(/#[^\"]+$/,"")
|
|
156
|
+
# convert quotes
|
|
157
|
+
tline.gsub!(/\\\"/,"'")
|
|
158
|
+
OutdentExp.each do |re|
|
|
159
|
+
if tline =~ re
|
|
160
|
+
tab -= 1
|
|
161
|
+
break
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
if multiLine_array.length > 0
|
|
166
|
+
multiLine_array.each do |ml|
|
|
167
|
+
output << rb_add_line(ml,tab)
|
|
168
|
+
end
|
|
169
|
+
multiLine_array.clear
|
|
170
|
+
multiLine_str = ""
|
|
171
|
+
else
|
|
172
|
+
output << rb_add_line(line,tab)
|
|
173
|
+
end
|
|
174
|
+
if !comment_line
|
|
175
|
+
IndentExp.each do |re|
|
|
176
|
+
if tline =~ re && !(tline =~ /\s+end\s*$/)
|
|
177
|
+
tab += 1
|
|
178
|
+
break
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
if tline =~ /^=end/
|
|
184
|
+
comment_block = false
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
error = (tab != 0)
|
|
188
|
+
STDERR.puts "Error: indent/outdent mismatch: #{tab}." if error
|
|
189
|
+
return output.join("\n") + "\n",error
|
|
190
|
+
end # beautify_string
|
|
191
|
+
|
|
192
|
+
def beautify_file(path)
|
|
193
|
+
error = false
|
|
194
|
+
|
|
195
|
+
if path == '-' # stdin source
|
|
196
|
+
source = STDIN.read
|
|
197
|
+
dest,error = beautify_string(source,"stdin")
|
|
198
|
+
print dest
|
|
199
|
+
else # named file source
|
|
200
|
+
source = File.read(path)
|
|
201
|
+
dest,error = beautify_string(source,path)
|
|
202
|
+
|
|
203
|
+
if source != dest
|
|
204
|
+
# make a backup copy
|
|
205
|
+
File.open(path + "~","w") { |f| f.write(source) }
|
|
206
|
+
# overwrite the original
|
|
207
|
+
File.open(path,"w") { |f| f.write(dest) }
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
error
|
|
211
|
+
end # beautify_file
|
|
212
|
+
end # module RBeautify
|