redcar 0.3.4.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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