redcar 0.3.4.3 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. data/CHANGES +45 -0
  2. data/README.md +2 -1
  3. data/ROADMAP.md +0 -1
  4. data/Rakefile +10 -4
  5. data/bin/redcar +2 -2
  6. data/lib/openssl/build.properties +7 -0
  7. data/lib/plugin_manager/lib/plugin_manager.rb +10 -0
  8. data/lib/plugin_manager/lib/plugin_manager/plugin_definition.rb +1 -13
  9. data/lib/redcar.rb +12 -8
  10. data/lib/redcar/installer.rb +16 -15
  11. data/lib/redcar/ruby_extensions.rb +146 -1
  12. data/lib/redcar/runner.rb +16 -7
  13. data/lib/redcar/usage.rb +4 -7
  14. data/lib/redcar_quick_start.rb +5 -5
  15. data/lib/regex_replace.rb +0 -7
  16. data/plugins/application/features/step_definitions/command_steps.rb +5 -0
  17. data/plugins/application/features/step_definitions/dialog_steps.rb +5 -0
  18. data/plugins/application/features/step_definitions/filter_list_dialog_steps.rb +38 -0
  19. data/plugins/application/features/step_definitions/window_steps.rb +1 -1
  20. data/plugins/application/features/support/env.rb +44 -8
  21. data/plugins/application/lib/application.rb +32 -33
  22. data/plugins/application/lib/application/command.rb +32 -2
  23. data/plugins/application/lib/application/command/executor.rb +2 -12
  24. data/plugins/application/lib/application/dialog.rb +14 -14
  25. data/plugins/application/lib/application/event_spewer.rb +32 -0
  26. data/plugins/application/lib/application/menu.rb +5 -5
  27. data/plugins/application/lib/application/menu/builder.rb +5 -0
  28. data/plugins/application/lib/application/menu/lazy_menu.rb +24 -0
  29. data/plugins/application/lib/application/notebook.rb +4 -3
  30. data/plugins/application/lib/application/tab.rb +6 -2
  31. data/plugins/application/lib/application/window.rb +8 -4
  32. data/plugins/application/spec/application/menu/builder_spec.rb +17 -1
  33. data/plugins/application/spec/application/notebook_spec.rb +1 -1
  34. data/plugins/application_swt/build.xml +74 -0
  35. data/plugins/application_swt/lib/application_swt.rb +79 -0
  36. data/plugins/application_swt/lib/application_swt/cucumber_patches.rb +6 -1
  37. data/plugins/application_swt/lib/application_swt/dialog_adapter.rb +25 -17
  38. data/plugins/application_swt/lib/application_swt/dialogs/filter_list_dialog_controller.rb +50 -12
  39. data/plugins/application_swt/lib/application_swt/html_tab.rb +20 -0
  40. data/plugins/application_swt/lib/application_swt/menu.rb +26 -2
  41. data/plugins/application_swt/lib/application_swt/notebook.rb +10 -12
  42. data/plugins/application_swt/lib/application_swt/window.rb +11 -11
  43. data/plugins/application_swt/src/com/redcareditor/application_swt/CocoaUIEnhancer.java +313 -0
  44. data/plugins/auto_completer/lib/auto_completer.rb +74 -67
  45. data/plugins/auto_completer/lib/auto_completer/current_document_completion_source.rb +19 -0
  46. data/plugins/auto_completer/lib/auto_completer/document_controller.rb +2 -2
  47. data/plugins/auto_completer/lib/auto_completer/word_list.rb +8 -1
  48. data/plugins/auto_indenter/features/ruby_style_indentation.feature +24 -0
  49. data/plugins/auto_indenter/features/step_definitions/indentation_steps.rb +6 -0
  50. data/plugins/auto_indenter/features/support/env.rb +2 -0
  51. data/plugins/auto_indenter/lib/auto_indenter.rb +86 -0
  52. data/plugins/auto_indenter/lib/auto_indenter/analyzer.rb +91 -0
  53. data/plugins/auto_indenter/lib/auto_indenter/commands.rb +34 -0
  54. data/plugins/auto_indenter/lib/auto_indenter/document_controller.rb +67 -12
  55. data/plugins/auto_indenter/lib/auto_indenter/rules.rb +41 -0
  56. data/plugins/auto_indenter/spec/auto_indenter/analyzer_spec.rb +151 -0
  57. data/plugins/auto_indenter/spec/spec_helper.rb +5 -0
  58. data/plugins/auto_pairer/lib/auto_pairer.rb +1 -0
  59. data/plugins/auto_pairer/lib/auto_pairer/document_controller.rb +43 -42
  60. data/plugins/auto_pairer/lib/auto_pairer/pairs_for_scope.rb +1 -5
  61. data/plugins/core/lib/core.rb +12 -1
  62. data/plugins/core/lib/core/observable.rb +7 -7
  63. data/plugins/core/lib/core/persistent_cache.rb +14 -2
  64. data/plugins/core/lib/core/plugin.rb +7 -0
  65. data/plugins/core/lib/core/resource.rb +78 -0
  66. data/plugins/core/lib/core/task.rb +62 -0
  67. data/plugins/core/lib/core/task_queue.rb +72 -0
  68. data/plugins/core/spec/core/resource_spec.rb +124 -0
  69. data/plugins/core/spec/core/task_queue_spec.rb +202 -0
  70. data/plugins/core/spec/spec_helper.rb +23 -1
  71. data/plugins/declarations/TODO +3 -0
  72. data/plugins/declarations/lib/declarations.rb +144 -0
  73. data/plugins/declarations/lib/declarations/completion_source.rb +22 -0
  74. data/plugins/declarations/lib/declarations/file.rb +68 -0
  75. data/plugins/declarations/lib/declarations/parser.rb +94 -0
  76. data/plugins/declarations/lib/declarations/select_tag_dialog.rb +44 -0
  77. data/plugins/declarations/plugin.rb +7 -0
  78. data/plugins/declarations/spec/declarations/file_spec.rb +62 -0
  79. data/plugins/declarations/spec/fixtures/federalist.rb +15 -0
  80. data/plugins/declarations/spec/spec_helper.rb +4 -0
  81. data/plugins/edit_view/features/indentation_commands.feature +40 -0
  82. data/plugins/edit_view/features/line_delimiter.feature +40 -0
  83. data/plugins/edit_view/features/step_definitions/editing_steps.rb +16 -4
  84. data/plugins/edit_view/features/step_definitions/notebook_steps.rb +1 -1
  85. data/plugins/edit_view/features/step_definitions/tab_steps.rb +1 -1
  86. data/plugins/edit_view/features/step_definitions/window_steps.rb +5 -1
  87. data/plugins/edit_view/features/support/env.rb +3 -5
  88. data/plugins/edit_view/features/undo_and_redo.feature +21 -0
  89. data/plugins/edit_view/lib/edit_view.rb +57 -4
  90. data/plugins/edit_view/lib/edit_view/actions/arrow_keys.rb +19 -3
  91. data/plugins/edit_view/lib/edit_view/document.rb +46 -11
  92. data/plugins/edit_view/lib/edit_view/document/indentation.rb +35 -0
  93. data/plugins/edit_view/lib/edit_view/modified_tabs_checker.rb +35 -0
  94. data/plugins/edit_view/lib/edit_view/tab_settings.rb +13 -3
  95. data/plugins/edit_view/spec/edit_view/document/indentation_spec.rb +112 -0
  96. data/plugins/edit_view/spec/edit_view/document_spec.rb +22 -0
  97. data/plugins/edit_view/spec/spec_helper.rb +1 -0
  98. data/plugins/edit_view_swt/lib/edit_view_swt.rb +59 -7
  99. data/plugins/edit_view_swt/lib/edit_view_swt/document.rb +3 -3
  100. data/plugins/edit_view_swt/lib/edit_view_swt/word_movement.rb +2 -2
  101. data/plugins/edit_view_swt/vendor/java-mateview.rb +3 -2
  102. data/plugins/encryption/encryption.rb +13 -6
  103. data/plugins/execute_current_tab/lib/execute_current_tab.rb +25 -15
  104. data/plugins/html_view/assets/redcar.css +32 -1
  105. data/plugins/html_view/lib/html_view.rb +23 -3
  106. data/plugins/html_view/lib/html_view/html_tab.rb +4 -0
  107. data/plugins/my_plugin/lib/my_plugin.rb +4 -12
  108. data/plugins/plugin_manager_ui/lib/plugin_manager_ui.rb +1 -0
  109. data/plugins/plugin_manager_ui/views/index.html.erb +30 -37
  110. data/plugins/project/features/find_file.feature +75 -0
  111. data/plugins/project/features/open_and_save_files.feature +7 -7
  112. data/plugins/project/features/open_directory_tree.feature +11 -3
  113. data/plugins/project/features/refresh_directory_tree.feature +7 -1
  114. data/plugins/project/features/step_definitions/directory_steps.rb +11 -1
  115. data/plugins/project/features/step_definitions/file_steps.rb +10 -0
  116. data/plugins/project/features/support/env.rb +6 -1
  117. data/plugins/project/features/watch_for_modified_files.feature +79 -0
  118. data/plugins/project/lib/project.rb +72 -306
  119. data/plugins/project/lib/project/commands.rb +128 -0
  120. data/plugins/project/lib/project/dir_mirror.rb +5 -1
  121. data/plugins/project/lib/project/drb_service.rb +21 -31
  122. data/plugins/project/lib/project/file_list.rb +76 -0
  123. data/plugins/project/lib/project/file_mirror.rb +13 -1
  124. data/plugins/project/lib/project/find_file_dialog.rb +22 -52
  125. data/plugins/project/lib/project/manager.rb +210 -0
  126. data/plugins/project/lib/project/recent_directories.rb +16 -3
  127. data/plugins/project/plugin.rb +1 -1
  128. data/plugins/project/spec/fixtures/myproject/README +2 -0
  129. data/plugins/project/spec/fixtures/myproject/lib/foo_lib.rb +1 -0
  130. data/plugins/project/spec/fixtures/myproject/spec/foo_spec.rb +1 -0
  131. data/plugins/project/{features → spec}/fixtures/winter.txt +0 -0
  132. data/plugins/project/spec/project/dir_mirror_spec.rb +1 -12
  133. data/plugins/project/spec/project/file_list_spec.rb +140 -0
  134. data/plugins/project/spec/spec_helper.rb +20 -0
  135. data/plugins/redcar/plugin.rb +1 -0
  136. data/plugins/redcar/redcar.rb +254 -84
  137. data/plugins/redcar_debug/lib/redcar_debug.rb +58 -11
  138. data/plugins/redcar_debug/vendor/jruby-prof/README +46 -0
  139. data/plugins/redcar_debug/vendor/jruby-prof/Rakefile +36 -0
  140. data/plugins/redcar_debug/vendor/jruby-prof/build.xml +31 -0
  141. data/plugins/redcar_debug/vendor/jruby-prof/example/call_tree.html +22677 -0
  142. data/plugins/redcar_debug/vendor/jruby-prof/example/call_tree.txt +589 -0
  143. data/plugins/redcar_debug/vendor/jruby-prof/example/flat.txt +28 -0
  144. data/plugins/redcar_debug/vendor/jruby-prof/example/graph.html +1670 -0
  145. data/plugins/redcar_debug/vendor/jruby-prof/example/graph.txt +125 -0
  146. data/plugins/redcar_debug/vendor/jruby-prof/example/pidigits.rb +92 -0
  147. data/plugins/redcar_debug/vendor/jruby-prof/example/test.rb +28 -0
  148. data/plugins/redcar_debug/vendor/jruby-prof/example/test2.rb +29 -0
  149. data/plugins/redcar_debug/vendor/jruby-prof/example/test_exception.rb +28 -0
  150. data/plugins/redcar_debug/vendor/jruby-prof/example/test_overhead.rb +43 -0
  151. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof.rb +66 -0
  152. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/abstract_printer.rb +21 -0
  153. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/flat_text_printer.rb +35 -0
  154. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/graph_html_printer.rb +123 -0
  155. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/graph_text_printer.rb +45 -0
  156. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/invocation_set.rb +34 -0
  157. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/method.rb +107 -0
  158. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/profile_invocation.rb +43 -0
  159. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/simple_tree_printer.rb +27 -0
  160. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/tree_html_printer.rb +144 -0
  161. data/plugins/redcar_debug/vendor/jruby-prof/src/org/jruby/prof/Invocation.java +14 -0
  162. data/plugins/redcar_debug/vendor/jruby-prof/src/org/jruby/prof/JRubyProf.java +94 -0
  163. data/plugins/redcar_debug/vendor/jruby-prof/src/org/jruby/prof/ProfEventHook.java +49 -0
  164. data/plugins/redcar_debug/vendor/jruby-prof/templates/graph_row.html.erb +18 -0
  165. data/plugins/redcar_debug/vendor/jruby-prof/test/basic_test.rb +291 -0
  166. data/plugins/redcar_debug/views/history.html.erb +33 -0
  167. data/plugins/redcar_debug/views/index.html.erb +33 -0
  168. data/plugins/repl/lib/repl/internal_mirror.rb +3 -15
  169. data/plugins/repl/spec/repl/internal_mirror_spec.rb +2 -2
  170. data/plugins/snippets/lib/snippets.rb +0 -1
  171. data/plugins/snippets/lib/snippets/document_controller.rb +7 -1
  172. data/plugins/task_manager/lib/task_manager.rb +28 -0
  173. data/plugins/task_manager/plugin.rb +11 -0
  174. data/plugins/task_manager/views/index.html.erb +67 -0
  175. data/plugins/textmate/lib/textmate.rb +17 -21
  176. data/plugins/textmate/lib/textmate/plist.rb +1 -2
  177. data/plugins/textmate/lib/textmate/preference.rb +5 -1
  178. data/plugins/textmate/lib/textmate/snippet.rb +6 -1
  179. data/plugins/tree_view_swt/lib/tree_view_swt.rb +0 -6
  180. data/textmate/Bundles/Cucumber.tmbundle/Preferences/Comments.tmPreferences +1 -1
  181. data/textmate/Bundles/Cucumber.tmbundle/Preferences/next_Cucumber_Plain_Text_Feature_Completions.tmPreferences +30 -0
  182. data/textmate/Bundles/Cucumber.tmbundle/Preferences/next_Symbol_list___Scenario.tmPreferences +19 -0
  183. data/textmate/Bundles/Cucumber.tmbundle/Syntaxes/next_Cucumber_Plain_Text_Feature.tmLanguage +221 -0
  184. data/textmate/Bundles/Cucumber.tmbundle/Syntaxes/next_Cucumber_Steps.tmLanguage +424 -0
  185. data/textmate/Bundles/Cucumber.tmbundle/Syntaxes/plaintext_template.erb +19 -77
  186. data/textmate/Bundles/Cucumber.tmbundle/info.plist +1 -20
  187. data/textmate/Bundles/Perl.tmbundle/Syntaxes/Perl.plist +1 -1
  188. data/textmate/Themes/Emacs Strict.tmTheme +241 -0
  189. data/textmate/Themes/IR_White.tmTheme +792 -0
  190. data/textmate/Themes/Monokai.tmTheme +291 -0
  191. data/textmate/Themes/WhysPoignant.tmTheme +191 -0
  192. metadata +92 -7
  193. data/plugins/application/features/main_window.feature +0 -8
  194. data/plugins/project/lib/project/project_command.rb +0 -5
  195. data/textmate/Bundles/Cucumber.tmbundle/Snippets/Scenario.tmSnippet +0 -22
  196. data/textmate/Bundles/Cucumber.tmbundle/Snippets/Story.tmSnippet +0 -25
@@ -3,52 +3,61 @@ module Redcar
3
3
  class ApplicationSWT
4
4
  class Menu
5
5
  def move(x, y)
6
- @menu_bar.setLocation(x, y)
6
+ @menu_bar.setLocation(x, y)
7
7
  end
8
8
  end
9
9
  end
10
10
  end
11
11
 
12
+ require 'auto_completer/current_document_completion_source'
12
13
  require 'auto_completer/document_controller'
13
14
  require 'auto_completer/word_iterator'
14
15
  require 'auto_completer/word_list'
15
16
 
16
17
  module Redcar
17
18
  class AutoCompleter
18
- WORD_CHARACTERS = /:|@|\w/ # /(\s|\t|\.|\r|\(|\)|,|;)/
19
+ WORD_CHARACTERS = /\w|_/ # /(\s|\t|\.|\r|\(|\)|,|;)/
19
20
 
20
21
  def self.document_controller_types
21
22
  [AutoCompleter::DocumentController]
22
23
  end
23
24
 
25
+ def self.autocompletion_source_types
26
+ [AutoCompleter::CurrentDocumentCompletionSource]
27
+ end
28
+
29
+ def self.all_autocompletion_source_types
30
+ result = []
31
+ Redcar.plugin_manager.objects_implementing(:autocompletion_source_types).each do |object|
32
+ result += object.autocompletion_source_types
33
+ end
34
+ result
35
+ end
36
+
24
37
  class AutoCompleteCommand < Redcar::EditTabCommand
25
38
 
26
39
  def execute
27
40
  controller = doc.controllers(AutoCompleter::DocumentController).first
28
41
  controller.start_modification
29
-
42
+
30
43
  if controller.in_completion?
31
44
  doc.delete(doc.cursor_offset - controller.length_of_previous, controller.length_of_previous)
32
- word = controller.word
45
+ prefix = controller.prefix
33
46
  left = controller.left
34
47
  right = controller.right
35
48
  word_list = controller.word_list
36
49
  else
37
- word, left, right = touched_word
38
- if word
39
- iterator = WordIterator.new(doc, WORD_CHARACTERS)
40
- word_list = WordList.new
41
- iterator.each_word_with_offset(word) do |matching_word, offset|
42
- distance = (offset - doc.cursor_offset).abs
43
- word_list.add_word(matching_word, distance)
44
- end
50
+ prefix, left, right = touched_prefix
51
+ if prefix
52
+ word_list = alternatives(prefix)
45
53
  controller.word_list = word_list
46
- controller.word = word
54
+ controller.prefix = prefix
47
55
  controller.left = left
48
56
  controller.right = right
49
57
  end
50
58
  end
51
- if word
59
+
60
+ if prefix
52
61
  index = (controller.index || 0) + 1
53
62
  if word_list.completions.length == index
54
63
  index = 0
@@ -57,12 +66,12 @@ module Redcar
57
66
  controller.index = index
58
67
 
59
68
  start_offset = right
60
- doc.insert(right, completion[word.length..-1])
61
- word_end_offset = right + completion.length - word.length
69
+ doc.insert(right, completion[prefix.length..-1])
70
+ word_end_offset = right + completion.length - prefix.length
62
71
  doc.cursor_offset = word_end_offset
63
-
64
- controller.length_of_previous = completion.length - word.length
65
-
72
+
73
+ controller.length_of_previous = completion.length - prefix.length
74
+
66
75
  controller.start_completion
67
76
  end
68
77
  controller.end_modification
@@ -70,18 +79,29 @@ module Redcar
70
79
 
71
80
  private
72
81
 
73
- # returns the word that is being touched by the cursor and an array
74
- # containing [left, right] document offsets of the word.
75
- def touched_word
82
+ def alternatives(prefix)
83
+ sources = AutoCompleter.all_autocompletion_source_types.map do |t|
84
+ t.new(doc, Project::Manager.focussed_project)
85
+ end
86
+ word_list = WordList.new
87
+ sources.each do |source|
88
+ if alts = source.alternatives(prefix)
89
+ word_list.merge!(alts)
90
+ end
91
+ end
92
+ word_list
93
+ end
94
+
95
+ # returns the prefix that is being touched by the cursor and an array
96
+ # containing [left, right] document offsets of the prefix.
97
+ def touched_prefix
76
98
  line = doc.get_line(doc.cursor_line)
77
99
  left, right = word_range(line)
78
- word = doc.get_range(left, right - left)
79
- return nil if word.length == 0
80
- return word, left, right
100
+ prefix = doc.get_range(left, right - left)
101
+ return nil if prefix.length == 0
102
+ return prefix, left, right
81
103
  end
82
104
 
83
- private
84
-
85
105
  # returns the range that holds the current word (depending on WORD_CHARACTERS)
86
106
  def word_range(line)
87
107
  left = doc.cursor_line_offset - 1
@@ -95,60 +115,47 @@ module Redcar
95
115
  left_range -= 1
96
116
  end
97
117
 
98
- # until right == line.length || WORD_CHARACTERS !~ (line[right].chr)
99
- # right += 1
100
- # right_range += 1
101
- # end
102
118
  return [offset+left_range, offset+right_range]
103
119
  end
104
120
  end
105
121
 
106
122
  class MenuAutoCompleterCommand < AutoCompleteCommand
107
-
123
+
108
124
  def execute
109
125
  controller = doc.controllers(AutoCompleter::DocumentController).first
110
126
  input_word = ""
111
127
  word_list = controller.word_list
112
- word, left, right = touched_word
113
- if word
114
- iterator = WordIterator.new(doc, WORD_CHARACTERS)
115
- word_list = WordList.new
116
- iterator.each_word_with_offset(word) do |matching_word, offset|
117
- distance = (offset - doc.cursor_offset).abs
118
- unless (distance - matching_word.length) == 0
119
- word_list.add_word(matching_word, distance)
120
- else
121
- input_word = matching_word
122
- end
123
- end
128
+ prefix, left, right = touched_prefix
129
+ if prefix
130
+ word_list = alternatives(prefix)
124
131
  controller.word_list = word_list
125
- controller.word = word
132
+ controller.prefix = prefix
126
133
  controller.left = left
127
134
  controller.right = right
135
+
136
+ cur_doc = doc
137
+ builder = Menu::Builder.new do
138
+ word_list.words.each do |current_word, word_distance|
139
+ item(current_word) do
140
+ offset = cur_doc.cursor_offset - prefix.length
141
+ text = current_word[input_word.length..current_word.length]
142
+ cur_doc.replace(offset, prefix.length, text)
143
+ end
144
+ end
145
+ end
146
+
147
+ window = Redcar.app.focussed_window
148
+ location = window.focussed_notebook.focussed_tab.controller.edit_view.mate_text.viewer.getTextWidget.getLocationAtOffset(window.focussed_notebook.focussed_tab.controller.edit_view.cursor_offset)
149
+ absolute_x = location.x
150
+ absolute_y = location.y
151
+ location = window.focussed_notebook.focussed_tab.controller.edit_view.mate_text.viewer.getTextWidget.toDisplay(0,0)
152
+ absolute_x += location.x
153
+ absolute_y += location.y
154
+ menu = ApplicationSWT::Menu.new(window.controller, builder.menu, nil, Swt::SWT::POP_UP)
155
+ menu.move(absolute_x, absolute_y)
156
+ menu.show
128
157
  end
129
-
130
- cur_doc = doc
131
- builder = Menu::Builder.new do
132
- word_list.words.each do |current_word, word_distance|
133
- item(current_word) do
134
- cur_doc.insert(cur_doc.cursor_offset, current_word[input_word.length..current_word.length])
135
- cur_doc.cursor_offset = cur_doc.cursor_offset + current_word[input_word.length..current_word.length].length
136
- end
137
- end
138
- end
139
-
140
- window = Redcar.app.focussed_window
141
- location = window.focussed_notebook.focussed_tab.controller.edit_view.mate_text.viewer.getTextWidget.getLocationAtOffset(window.focussed_notebook.focussed_tab.controller.edit_view.cursor_offset)
142
- absolute_x = location.x
143
- absolute_y = location.y
144
- location = window.focussed_notebook.focussed_tab.controller.edit_view.mate_text.viewer.getTextWidget.toDisplay(0,0)
145
- absolute_x += location.x
146
- absolute_y += location.y
147
- menu = ApplicationSWT::Menu.new(window.controller, builder.menu, nil, Swt::SWT::POP_UP)
148
- menu.move(absolute_x, absolute_y)
149
- menu.show
150
158
  end
151
-
152
159
  end
153
160
  end
154
161
  end
@@ -0,0 +1,19 @@
1
+ module Redcar
2
+ class AutoCompleter
3
+ class CurrentDocumentCompletionSource
4
+ def initialize(document, _)
5
+ @document = document
6
+ end
7
+
8
+ def alternatives(prefix)
9
+ iterator = WordIterator.new(@document, WORD_CHARACTERS)
10
+ word_list = WordList.new
11
+ iterator.each_word_with_offset(prefix) do |matching_word, offset|
12
+ distance = (offset - @document.cursor_offset).abs
13
+ word_list.add_word(matching_word, distance)
14
+ end
15
+ word_list
16
+ end
17
+ end
18
+ end
19
+ end
@@ -30,7 +30,7 @@ module Redcar
30
30
 
31
31
  attr_accessor :index
32
32
  attr_accessor :length_of_previous
33
- attr_accessor :word_list, :word, :left, :right
33
+ attr_accessor :word_list, :prefix, :left, :right
34
34
 
35
35
  def before_modify(*_)
36
36
  end
@@ -41,7 +41,7 @@ module Redcar
41
41
  @index = 0
42
42
  @length_of_previous = nil
43
43
  @word_list = nil
44
- @word = nil
44
+ @prefix = nil
45
45
  @left = nil
46
46
  @right = nil
47
47
  end
@@ -11,7 +11,6 @@ module Redcar
11
11
 
12
12
  def initialize
13
13
  @words = Hash.new
14
- @offset = 0
15
14
  end
16
15
 
17
16
  # adds a new word, iff it doesn't yet exist.
@@ -35,6 +34,14 @@ module Redcar
35
34
  def each
36
35
  @words.each {|word,distance| yield word, distance }
37
36
  end
37
+
38
+ def merge!(other)
39
+ @words.merge!(other.words)
40
+ end
41
+
42
+ def inspect
43
+ "<WordList: " + @words.map {|k,v| "#{k}:#{v}"}.join(" ") + ">"
44
+ end
38
45
  end
39
46
  end
40
47
  end
@@ -0,0 +1,24 @@
1
+ Feature: Indents Ruby code correctly
2
+
3
+ Background:
4
+ Given the indentation rules are like Ruby's
5
+ When I open a new edit tab
6
+ And tabs are hard
7
+
8
+ Scenario: It should increase indentation after 'def's
9
+ When I insert "def f" at the cursor
10
+ And I move the cursor to 5
11
+ And I insert "\n" at the cursor
12
+ Then the contents should be "def f\n\t"
13
+
14
+ Scenario: It should decrease indentation on 'end' line
15
+ When I insert "def f\n\t1\n\ten" at the cursor
16
+ And I move the cursor to 12
17
+ And I insert "d" at the cursor
18
+ Then the contents should be "def f\n\t1\nend"
19
+
20
+ Scenario: It should keep indentation the same if no change
21
+ When I insert "\tfoo" at the cursor
22
+ And I move the cursor to 4
23
+ And I insert "\n" at the cursor
24
+ Then the contents should be "\tfoo\n\t"
@@ -0,0 +1,6 @@
1
+
2
+ Given /^the indentation rules are like Ruby's$/ do
3
+ Redcar::AutoIndenter.test_rules = Redcar::AutoIndenter::Rules.new(/def/, /end/)
4
+ end
5
+
6
+
@@ -0,0 +1,2 @@
1
+
2
+ RequireSupportFiles File.dirname(__FILE__) + "/../../../edit_view/features/"
@@ -1,5 +1,8 @@
1
1
 
2
+ require 'auto_indenter/analyzer'
3
+ require 'auto_indenter/commands'
2
4
  require 'auto_indenter/document_controller'
5
+ require 'auto_indenter/rules'
3
6
 
4
7
  module Redcar
5
8
  class AutoIndenter
@@ -7,5 +10,88 @@ module Redcar
7
10
  def self.document_controller_types
8
11
  [AutoIndenter::DocumentController]
9
12
  end
13
+
14
+ class << self
15
+ attr_accessor :test_rules
16
+ end
17
+
18
+ def self.cache
19
+ @cache ||= {}
20
+ end
21
+
22
+ def self.best_match(hash, current_scope)
23
+ matches = hash.map do |scope_name, value|
24
+ if match = JavaMateView::ScopeMatcher.get_match(scope_name, current_scope)
25
+ [scope_name, match, value]
26
+ end
27
+ end.compact
28
+
29
+ ranked_matches = matches.sort do |a, b|
30
+ JavaMateView::ScopeMatcher.compare_match(current_scope, a[1], b[1])
31
+ end
32
+
33
+ if best_match = ranked_matches.last
34
+ best_match[2]
35
+ end
36
+ end
37
+
38
+ def self.rules_for_scope(current_scope)
39
+ return unless current_scope
40
+ if rules = AutoIndenter.test_rules
41
+ return rules
42
+ end
43
+ cache[current_scope] ||= begin
44
+ if inc_best_match = best_match(indentation_rules[:increase], current_scope)
45
+ inc_best_match = Regexp.new(inc_best_match)
46
+ end
47
+ if dec_best_match = best_match(indentation_rules[:decrease], current_scope)
48
+ dec_best_match = Regexp.new(dec_best_match)
49
+ end
50
+ if indent_next_best_match = best_match(indentation_rules[:indent_next], current_scope)
51
+ indent_next_best_match = Regexp.new(indent_next_best_match)
52
+ end
53
+ if unindented_match = best_match(indentation_rules[:unindented], current_scope)
54
+ unindented_match = Regexp.new(unindented_match)
55
+ end
56
+ Rules.new(inc_best_match, dec_best_match, indent_next_best_match, unindented_match)
57
+ end
58
+ end
59
+
60
+ def self.initialize_rules(settings, rules)
61
+ settings.each do |setting|
62
+ if setting.scope
63
+ rules[setting.scope] = setting.pattern
64
+ else
65
+ puts "indent setting without scope! #{setting.inspect}"
66
+ end
67
+ end
68
+ end
69
+
70
+ def self.indentation_rules
71
+ @indentation_rules ||= begin
72
+ increase_rules = Hash.new {|h, k| h[k] = {}}
73
+ decrease_rules = Hash.new {|h, k| h[k] = {}}
74
+ indent_next_rules = Hash.new {|h, k| h[k] = {}}
75
+ unindented_rules = Hash.new {|h, k| h[k] = {}}
76
+ increase_settings = Textmate.settings(Textmate::IncreaseIndentPatternSetting)
77
+ decrease_settings = Textmate.settings(Textmate::DecreaseIndentPatternSetting)
78
+ indent_next_settings = Textmate.settings(Textmate::IndentNextLinePatternSetting)
79
+ unindented_settings = Textmate.settings(Textmate::UnIndentedLinePatternSetting)
80
+ initialize_rules(increase_settings, increase_rules)
81
+ initialize_rules(decrease_settings, decrease_rules)
82
+ initialize_rules(indent_next_settings, indent_next_rules)
83
+ initialize_rules(unindented_settings, unindented_rules)
84
+ increase_rules.default = nil
85
+ decrease_rules.default = nil
86
+ indent_next_rules.default = nil
87
+ unindented_rules.default = nil
88
+ {
89
+ :increase => increase_rules,
90
+ :decrease => decrease_rules,
91
+ :indent_next => indent_next_rules,
92
+ :unindented => unindented_rules
93
+ }
94
+ end
95
+ end
10
96
  end
11
97
  end
@@ -0,0 +1,91 @@
1
+
2
+ module Redcar
3
+ class AutoIndenter
4
+ class Analyzer
5
+ attr_reader :rules
6
+
7
+ def initialize(rules, doc, tab_width, soft_tabs)
8
+ @rules, @doc, @tab_width, @soft_tabs = rules, doc, tab_width, soft_tabs
9
+ @indentation = doc.indentation
10
+ end
11
+
12
+ def calculate_for_line(line_ix, typing=false)
13
+ return 0 if line_ix == 0
14
+ #p [:line_ix, line_ix]
15
+ current_line = @doc.get_line(line_ix)
16
+ previous_ix, indent_next_line = index_of_previous_normally_indented(line_ix)
17
+ #p [:previous_ix, previous_ix, indent_next_line]
18
+ previous_line = @doc.get_line(previous_ix)
19
+ current_level = @indentation.get_level(previous_ix)
20
+ new_level = current_level
21
+ #p [:previous_line, previous_line]
22
+ #p [:current_line, current_line]
23
+ #p [:current_level, current_level]
24
+
25
+ if !typing and rules.unindented_line?(current_line)
26
+ #p [:unindented_line]
27
+ return @indentation.get_level(line_ix)
28
+ end
29
+
30
+ if rules.increase_indent?(previous_line)
31
+ #p [:inc_indent]
32
+ new_level += 1
33
+ end
34
+ if rules.decrease_indent?(current_line)
35
+ #p [:dec_indent]
36
+ new_level -= 1
37
+ end
38
+ if !typing and indent_next_line and !rules.increase_indent?(current_line)
39
+ #p [:indent_next_line]
40
+ new_level += 1
41
+ end
42
+
43
+ #p [:new_level, new_level]
44
+ new_level
45
+ end
46
+
47
+ def index_of_previous_normally_indented(line_ix)
48
+ current = line_ix - 1
49
+ indent_next_line = nil
50
+ loop do
51
+ if current == 0
52
+ return 0, indent_next_line
53
+ end
54
+ line = @doc.get_line(current)
55
+ if rules.unindented_line?(line)
56
+ current -= 1
57
+ else
58
+ if indent_next_line == nil
59
+ #p [:indent_next_line?, line, rules.indent_next_line?(line)]
60
+ indent_next_line = rules.indent_next_line?(line)
61
+ end
62
+ previous_ix = index_of_previous_non_unindented_line(current)
63
+ if previous_ix < 0
64
+ return current, indent_next_line
65
+ else
66
+ previous_line = @doc.get_line(previous_ix)
67
+
68
+ if rules.indent_next_line?(previous_line) and !rules.increase_indent?(line)
69
+ current -= 1
70
+ else
71
+ return current, indent_next_line
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def index_of_previous_non_unindented_line(line_ix)
79
+ current = line_ix - 1
80
+ while current >= 0 and
81
+ line = @doc.get_line(current) and
82
+ rules.unindented_line?(line)
83
+ current -= 1
84
+ end
85
+ #p [:index_of_previous_non_unindented_line, line_ix, current]
86
+ current
87
+ end
88
+
89
+ end
90
+ end
91
+ end