watirmark 5.14.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/app_generators/create_project/create_project_generator.rb +115 -0
  2. data/app_generators/create_project/templates/features/env.rb.erb +8 -0
  3. data/app_generators/create_project/templates/features/model_steps.rb.erb +9 -0
  4. data/app_generators/create_project/templates/features/post_error_steps.rb.erb +15 -0
  5. data/app_generators/create_project/templates/features/sample.feature.erb +5 -0
  6. data/app_generators/create_project/templates/features/site_steps.rb.erb +7 -0
  7. data/app_generators/create_project/templates/generators/controller.rb.erb +9 -0
  8. data/app_generators/create_project/templates/generators/generate.rb.erb +9 -0
  9. data/app_generators/create_project/templates/generators/model.rb.erb +7 -0
  10. data/app_generators/create_project/templates/generators/mvc_generator.rb.erb +100 -0
  11. data/app_generators/create_project/templates/generators/rbeautify.rb.erb +212 -0
  12. data/app_generators/create_project/templates/generators/view.rb.erb +16 -0
  13. data/app_generators/create_project/templates/generators/workflow_loader.rb.erb +1 -0
  14. data/app_generators/create_project/templates/library/base_controller.rb.erb +9 -0
  15. data/app_generators/create_project/templates/library/base_view.rb.erb +6 -0
  16. data/app_generators/create_project/templates/library/configuration.rb.erb +6 -0
  17. data/app_generators/create_project/templates/library/core_libraries.rb.erb +9 -0
  18. data/app_generators/create_project/templates/library/loader.rb.erb +23 -0
  19. data/app_generators/create_project/templates/library/page_load_checker.rb.erb +11 -0
  20. data/app_generators/create_project/templates/library/post_errors_checker.rb.erb +23 -0
  21. data/app_generators/create_project/templates/library/project_require_file.rb.erb +8 -0
  22. data/app_generators/create_project/templates/library/search_controller.rb.erb +12 -0
  23. data/app_generators/create_project/templates/library/workflows.rb.erb +0 -0
  24. data/app_generators/create_project/templates/project/config.yml.erb +3 -0
  25. data/app_generators/create_project/templates/project/gemfile.rb.erb +11 -0
  26. data/app_generators/create_project/templates/project/rakefile.rb.erb +21 -0
  27. data/bin/etapestry/Gemfile +11 -0
  28. data/bin/etapestry/config.yml +3 -0
  29. data/bin/etapestry/features/etapestry_home.feature +5 -0
  30. data/bin/etapestry/features/step_definitions/model_steps.rb +9 -0
  31. data/bin/etapestry/features/step_definitions/post_error_steps.rb +15 -0
  32. data/bin/etapestry/features/step_definitions/site_steps.rb +7 -0
  33. data/bin/etapestry/features/support/env.rb +8 -0
  34. data/bin/etapestry/generators/mvc/mvc_generator.rb +100 -0
  35. data/bin/etapestry/generators/mvc/rbeautify.rb +212 -0
  36. data/bin/etapestry/generators/mvc/templates/controller.rb.erb +9 -0
  37. data/bin/etapestry/generators/mvc/templates/model.rb.erb +7 -0
  38. data/bin/etapestry/generators/mvc/templates/view.rb.erb +16 -0
  39. data/bin/etapestry/generators/mvc/templates/workflow_loader.rb.erb +1 -0
  40. data/bin/etapestry/lib/etapestry.rb +8 -0
  41. data/bin/etapestry/lib/etapestry/checkers/page_load_checker.rb +11 -0
  42. data/bin/etapestry/lib/etapestry/checkers/post_errors_checker.rb +23 -0
  43. data/bin/etapestry/lib/etapestry/configuration.rb +6 -0
  44. data/bin/etapestry/lib/etapestry/core_libraries.rb +9 -0
  45. data/bin/etapestry/lib/etapestry/loader.rb +23 -0
  46. data/bin/etapestry/lib/etapestry/site/base_controller.rb +9 -0
  47. data/bin/etapestry/lib/etapestry/site/base_view.rb +6 -0
  48. data/bin/etapestry/lib/etapestry/site/search_controller.rb +12 -0
  49. data/bin/etapestry/lib/etapestry/workflows.rb +0 -0
  50. data/bin/etapestry/rakefile.rb +21 -0
  51. data/bin/etapestry/script/generate.rb +9 -0
  52. data/bin/twitter/features/hashtag_search.feature +93 -0
  53. data/bin/twitter/features/step_definitions/hashtag_steps.rb +9 -0
  54. data/bin/twitter/lib/twitter/workflows/search/result_controller.rb +13 -0
  55. data/bin/twitter/lib/twitter/workflows/search/result_model.rb +5 -0
  56. data/bin/twitter/lib/twitter/workflows/search/result_view.rb +19 -0
  57. data/bin/watirmark +10 -0
  58. data/lib/watirmark.rb +26 -0
  59. data/lib/watirmark/at_exit.rb +13 -0
  60. data/lib/watirmark/configuration.rb +201 -0
  61. data/lib/watirmark/controller/actions.rb +172 -0
  62. data/lib/watirmark/controller/assertions.rb +116 -0
  63. data/lib/watirmark/controller/controller.rb +191 -0
  64. data/lib/watirmark/controller/dialogs.rb +33 -0
  65. data/lib/watirmark/controller/matcher.rb +19 -0
  66. data/lib/watirmark/cucumber/cuke_helper.rb +150 -0
  67. data/lib/watirmark/cucumber/email_helper.rb +103 -0
  68. data/lib/watirmark/cucumber/env.rb +9 -0
  69. data/lib/watirmark/cucumber/hooks.rb +16 -0
  70. data/lib/watirmark/cucumber/model_helper.rb +34 -0
  71. data/lib/watirmark/cucumber/transforms.rb +55 -0
  72. data/lib/watirmark/exceptions.rb +15 -0
  73. data/lib/watirmark/extensions/ruby_extensions.rb +129 -0
  74. data/lib/watirmark/extensions/webdriver_extensions.rb +150 -0
  75. data/lib/watirmark/formatters/snapshot_formatter.rb +23 -0
  76. data/lib/watirmark/loader.rb +87 -0
  77. data/lib/watirmark/model.rb +3 -0
  78. data/lib/watirmark/models/cucumber_helper.rb +49 -0
  79. data/lib/watirmark/models/debug_methods.rb +21 -0
  80. data/lib/watirmark/models/default_values.rb +21 -0
  81. data/lib/watirmark/models/factory.rb +168 -0
  82. data/lib/watirmark/models/factory_method_generators.rb +84 -0
  83. data/lib/watirmark/models/factory_methods.rb +72 -0
  84. data/lib/watirmark/models/trait.rb +35 -0
  85. data/lib/watirmark/models/upload_csv.rb +24 -0
  86. data/lib/watirmark/page/keyed_element.rb +63 -0
  87. data/lib/watirmark/page/page.rb +50 -0
  88. data/lib/watirmark/page/page_definition.rb +187 -0
  89. data/lib/watirmark/page/process_page.rb +112 -0
  90. data/lib/watirmark/page/radio_maps.rb +53 -0
  91. data/lib/watirmark/profile.rb +22 -0
  92. data/lib/watirmark/rake/smoketest.rb +17 -0
  93. data/lib/watirmark/screenshot.rb +127 -0
  94. data/lib/watirmark/session.rb +115 -0
  95. data/lib/watirmark/version.rb +5 -0
  96. data/spec/assertions_spec.rb +95 -0
  97. data/spec/config_spec.rb +82 -0
  98. data/spec/controller_actions_spec.rb +91 -0
  99. data/spec/controller_spec.rb +426 -0
  100. data/spec/controllers_and_models_spec.rb +52 -0
  101. data/spec/model_factory_spec.rb +568 -0
  102. data/spec/model_traits_spec.rb +141 -0
  103. data/spec/page_spec.rb +127 -0
  104. data/spec/process_page_spec.rb +163 -0
  105. data/spec/spec_helper.rb +17 -0
  106. metadata +238 -0
@@ -0,0 +1,16 @@
1
+ module <%= name.camelize %>
2
+ <%%= create_modules %>
3
+ class <%%= name.camelize %>View < BaseView
4
+ keyword(:keyword_name) { browser.text_field(:id, 'element_id') }
5
+
6
+ def home(model)
7
+ end
8
+
9
+ def create(model)
10
+ end
11
+
12
+ def edit(model)
13
+ end
14
+ end
15
+ <%%= create_module_end %>
16
+ end
@@ -0,0 +1 @@
1
+ <%= name.camelize %>::Loader.load_product '<%%= product.downcase %>'
@@ -0,0 +1,9 @@
1
+ module <%= name.camelize %>
2
+ class BaseController < Watirmark::WebPage::Controller
3
+
4
+ # default way of submitting a form
5
+ def submit
6
+ # @view.save_button.click
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ module <%= name.camelize %>
2
+ class BaseView < Watirmark::Page
3
+ class << self
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'watirmark/configuration'
2
+
3
+ Watirmark::Configuration.instance.defaults = {
4
+ :configfile => "#{File.dirname(__FILE__) + '/../..'}/config.yml",
5
+ }
6
+ Watirmark::Configuration.instance.reload
@@ -0,0 +1,9 @@
1
+ require '<%= name.downcase %>/site/base_view'
2
+ require '<%= name.downcase %>/site/base_controller'
3
+ require '<%= name.downcase %>/site/search_controller'
4
+ Watirmark.loader do
5
+ base_directory File.dirname(__FILE__)
6
+ product '<%= name.camelize %>'
7
+ load_files 'checkers/**/*.rb'
8
+ end
9
+
@@ -0,0 +1,23 @@
1
+ require 'watirmark/loader'
2
+ module <%= name.camelize %>
3
+ class Loader
4
+ class << self
5
+ @@loaded = {}
6
+
7
+ def load_workflow(name)
8
+ load_files name, "*{_view}.rb"
9
+ load_files name, "*{_model}.rb"
10
+ load_files name, "*{_controller}.rb"
11
+ load_files name, "*.rb"
12
+ end
13
+
14
+ def load_files(name, files)
15
+ Watirmark.loader do
16
+ base_directory File.dirname(__FILE__)
17
+ product '<%= name.camelize %>'
18
+ load_files "workflows/#{name}#{files}"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module Watirmark
2
+ class Session
3
+
4
+ # put in here the appropriate waits
5
+ # to verify that the page has loaded completely, if your app has javascript-loaded content
6
+ def self.page_load
7
+ Watir::Wait.until { Page.browser.url != "about:blank" }
8
+ end
9
+ Watirmark::Session::POST_WAIT_CHECKERS << Proc.new { Watirmark::Session::page_load }
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require 'watirmark/session'
2
+
3
+ module Watirmark
4
+ class Session
5
+
6
+ # Post errors are basically any error messages that
7
+ # appear to the user when a form submission fails. This catches that
8
+ # error and allows the cucumber to catch the error (@@buffer_post_failure)
9
+ # or just throw an exception when an error is seen after a post
10
+ def self.post_errors
11
+ #if Page.browser.table(:class, 'error').present?
12
+ # message = Page.browser.table(:class, 'error').text
13
+ # if @@buffer_post_failure
14
+ # @@post_failure = message.strip
15
+ # else
16
+ # raise Watirmark::PostFailure, message.strip
17
+ # end
18
+ #end
19
+ end
20
+
21
+ Watirmark::Session::POST_WAIT_CHECKERS << Proc.new { Watirmark::Session::post_errors }
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ module <%= name.camelize %>; end
2
+
3
+ require '<%= name.downcase %>/configuration'
4
+ require 'watirmark'
5
+ require '<%= name.downcase %>/loader'
6
+ require '<%= name.downcase %>/core_libraries'
7
+ require '<%= name.downcase %>/workflows'
8
+
@@ -0,0 +1,12 @@
1
+ module <%= name.camelize %>
2
+ class SearchController < BaseController
3
+
4
+ def current_record_visible?
5
+ raise "Method needs to be defined in the subclass and return a true/false value"
6
+ end
7
+
8
+ def populate_data
9
+ super unless current_record_visible?
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ hostname: www.<%= name.downcase %>.com
2
+ webdriver: firefox
3
+ default_firefox_profile: default
@@ -0,0 +1,11 @@
1
+ source "http://gemcutter.org"
2
+ source "http://gemserver.qa.convioanalyticstest.net:8808"
3
+
4
+ gem 'watirmark'
5
+ gem 'watir-webdriver', '0.6.1.6'
6
+ gem 'rspec'
7
+ gem 'rake'
8
+ gem 'builder'
9
+ gem 'cucumber'
10
+ gem 'gherkin'
11
+ gem 'bundler'
@@ -0,0 +1,21 @@
1
+ $: << File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ # Run a bundle install if running from Jenkins
4
+ begin
5
+ sh "bundle install" if File.dirname(__FILE__) =~ /\/(hudson|mnt)\/workspace\//
6
+ rescue Gem::RemoteFetcher::FetchError
7
+ puts "Unable to connect - retrying #{Time.now}"
8
+ retry
9
+ end
10
+
11
+ require 'bundler/setup'
12
+ require 'cucumber/rake/task'
13
+
14
+ module RakeHelper
15
+ def self.cucumber_task(task_name, files=nil)
16
+ Cucumber::Rake::Task.new(task_name) do |t|
17
+ t.cucumber_opts = "-r features #{FileList[files]} -b --format html -o reports/report.html --format pretty"
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,11 @@
1
+ source "http://gemcutter.org"
2
+ source "http://gemserver.qa.convioanalyticstest.net:8808"
3
+
4
+ gem 'watirmark'
5
+ gem 'watir-webdriver', '0.6.1.6'
6
+ gem 'rspec'
7
+ gem 'rake'
8
+ gem 'builder'
9
+ gem 'cucumber'
10
+ gem 'gherkin'
11
+ gem 'bundler'
@@ -0,0 +1,3 @@
1
+ hostname: www.etapestry.com
2
+ webdriver: firefox
3
+ default_firefox_profile: default
@@ -0,0 +1,5 @@
1
+ Feature: This is a sample feature file to make sure you have everything set up properly
2
+
3
+ Scenario: Navigate to the site by hostname
4
+ Given I go to the home page
5
+ Then the url should contain "etapestry.com"
@@ -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,7 @@
1
+ Given /I go to the home page/ do
2
+ Page.browser.goto "www.etapestry.com"
3
+ end
4
+
5
+ Then /the url should contain "(.*?)"/ do |url|
6
+ Page.browser.url.should match(url)
7
+ end
@@ -0,0 +1,8 @@
1
+ dir = File.join(File.dirname(__FILE__))
2
+ $: << File.expand_path("#{dir}/../../lib")
3
+ $: << File.expand_path(dir)
4
+
5
+ require 'etapestry'
6
+ require 'watirmark/cucumber/env'
7
+
8
+ include Etapestry
@@ -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/etapestry/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/etapestry/workflows.rb" do |f|
48
+ f.puts "Etapestry::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