diff --git a/README.md b/README.md index 02152d9de..64df4d471 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ Usage: --theme=THEME Choose Textmate theme ## INSTALLING FROM SOURCE - Download from github, checkout the submodules and build JavaMateView. You will need Ant installed, and RSpec and Cucumber installed as JRuby gems. diff --git a/plugins/edit_view/features/soft_tabs.feature b/plugins/edit_view/features/soft_tabs.feature index 71403770f..1b9925600 100644 --- a/plugins/edit_view/features/soft_tabs.feature +++ b/plugins/edit_view/features/soft_tabs.feature @@ -1,55 +1,5 @@ Feature: Soft and hard tabs - Scenario: Inserts hard tab at the start of a line - When I open a new edit tab - And tabs are hard - And I press the Tab key in the edit tab - Then the contents of the edit tab should be "\t" - - Scenario: Inserts hard tab at the end of a line - When I open a new edit tab - And tabs are hard - And I replace the contents with "Hacker" - And I move the cursor to 6 - And I press the Tab key in the edit tab - Then the contents of the edit tab should be "Hacker\t" - - Scenario: Inserts 2 space soft tab at the start of a line - When I open a new edit tab - And tabs are soft, 2 spaces - And I press the Tab key in the edit tab - Then the contents of the edit tab should be " " - - Scenario: Inserts 2 space soft tab at the end of a line - When I open a new edit tab - And tabs are soft, 2 spaces - And I replace the contents with "Hacker" - And I move the cursor to 6 - And I press the Tab key in the edit tab - Then the contents of the edit tab should be "Hacker " - - Scenario: Inserts 4 space soft tab at the start of a line - When I open a new edit tab - And tabs are soft, 4 spaces - And I press the Tab key in the edit tab - Then the contents of the edit tab should be " " - - Scenario: Inserts 4 space soft tab at the end of a line - When I open a new edit tab - And tabs are soft, 4 spaces - And I replace the contents with "Hacker" - And I move the cursor to 6 - And I press the Tab key in the edit tab - Then the contents of the edit tab should be "Hacker " - - Scenario: Inserts 4 space soft tab at the end of a line, with a tab character - When I open a new edit tab - And tabs are soft, 4 spaces - And I replace the contents with "\tHacker" - And I move the cursor to 7 - And I press the Tab key in the edit tab - Then the contents of the edit tab should be "\tHacker " - Scenario: Move left through soft tabs When I open a new edit tab And tabs are soft, 2 spaces @@ -290,4 +240,4 @@ Feature: Soft and hard tabs And I move the cursor to 0 And I press the Delete key in the edit tab Then the cursor should be at 0 - \ No newline at end of file + diff --git a/plugins/edit_view/features/step_definitions/editing_steps.rb b/plugins/edit_view/features/step_definitions/editing_steps.rb index ac35d513b..3b8f1e45a 100644 --- a/plugins/edit_view/features/step_definitions/editing_steps.rb +++ b/plugins/edit_view/features/step_definitions/editing_steps.rb @@ -98,4 +98,21 @@ Redcar::EditView.focussed_edit_view_document.to_s.should == text end +When /^I block select from (\d+) to (\d+)$/ do |from_str, to_str| + doc = Redcar::EditView.focussed_edit_view_document + doc.block_selection_mode = true + doc.set_selection_range(from_str.to_i, to_str.to_i) +end + +Then /^the selection range should be from (\d+) to (\d+)$/ do |from_str, to_str| + doc = Redcar::EditView.focussed_edit_view_document + doc.block_selection_mode = true + r = doc.selection_range + r.begin.should == from_str.to_i + r.end.should == to_str.to_i +end + + + + \ No newline at end of file diff --git a/plugins/edit_view/features/tabs.feature b/plugins/edit_view/features/tabs.feature new file mode 100644 index 000000000..1ff94602b --- /dev/null +++ b/plugins/edit_view/features/tabs.feature @@ -0,0 +1,146 @@ +Feature: Insert a tab + + Scenario: Inserts hard tab at the start of a line + When I open a new edit tab + And tabs are hard + And I press the Tab key in the edit tab + Then the contents of the edit tab should be "\t" + + Scenario: Inserts hard tab at the end of a line + When I open a new edit tab + And tabs are hard + And I replace the contents with "Hacker" + And I move the cursor to 6 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be "Hacker\t" + + Scenario: Inserts 2 space soft tab at the start of a line + When I open a new edit tab + And tabs are soft, 2 spaces + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " " + + Scenario: Inserts 2 space soft tab at the end of a line + When I open a new edit tab + And tabs are soft, 2 spaces + And I replace the contents with "Hacker" + And I move the cursor to 6 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be "Hacker " + + Scenario: Inserts 4 space soft tab at the start of a line + When I open a new edit tab + And tabs are soft, 4 spaces + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " " + + Scenario: Inserts 4 space soft tab at the end of a line + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Hacker" + And I move the cursor to 6 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be "Hacker " + + Scenario: Inserts soft tabs correctly if there is selected text + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Ha" + And I move the cursor to 0 + And I press Shift+Right key in the edit tab + And I press Shift+Right key in the edit tab + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " " + + Scenario: Inserts hard tabs correctly if there is selected text + When I open a new edit tab + And tabs are hard + And I replace the contents with "Ha" + And I move the cursor to 0 + And I press Shift+Right key in the edit tab + And I press Shift+Right key in the edit tab + And I press the Tab key in the edit tab + Then the contents of the edit tab should be "\t" + + Scenario: Inserts soft tabs correctly if there is selected text that covers a tab + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "H\t" + And I move the cursor to 0 + And I press Shift+Right key in the edit tab + And I press Shift+Right key in the edit tab + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " " + + Scenario: Inserts 4 space soft tab at the end of a line, with a tab character + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "\tHacker" + And I move the cursor to 7 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be "\tHacker " + + @block_selection + Scenario: In block selection mode inserts 4 space soft tab on 1 line + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Jim\nHacker" + And I block select from 0 to 0 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " Jim\nHacker" + And the selection range should be from 4 to 4 + + @block_selection + Scenario: In block selection mode inserts 4 space soft tab on 2 lines + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Jim\nHacker" + And I block select from 0 to 4 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " Jim\n Hacker" + And the selection range should be from 4 to 12 + + @block_selection + Scenario: In block selection mode inserts 4 space soft tab on 3 lines + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Jim\nHacker\nMP" + And I block select from 0 to 11 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " Jim\n Hacker\n MP" + And the selection range should be from 4 to 23 + + @block_selection + Scenario: In block selection mode inserts 4 space soft tab overwriting text on 1 line + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Jim\nHacker" + And I block select from 0 to 2 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " m\nHacker" + And the selection range should be from 4 to 4 + + @block_selection + Scenario: In block selection mode inserts 4 space soft tab overwriting text on 2 lines + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Jim\nHacker" + And I block select from 0 to 6 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " m\n cker" + And the selection range should be from 4 to 10 + + @block_selection + Scenario: In block selection mode inserts 4 space soft tab overwriting text on 3 lines + When I open a new edit tab + And tabs are soft, 4 spaces + And I replace the contents with "Jim\nHacker\nMP" + And I block select from 0 to 13 + And I press the Tab key in the edit tab + Then the contents of the edit tab should be " m\n cker\n " + And the selection range should be from 4 to 19 + + + + + diff --git a/plugins/edit_view/lib/edit_view/actions/tab.rb b/plugins/edit_view/lib/edit_view/actions/tab.rb index 752a486a5..5bd8ebf45 100644 --- a/plugins/edit_view/lib/edit_view/actions/tab.rb +++ b/plugins/edit_view/lib/edit_view/actions/tab.rb @@ -7,11 +7,6 @@ def self.handle(edit_view, modifiers) doc = edit_view.document if doc.block_selection_mode? if edit_view.soft_tabs? - line = doc.get_line(doc.cursor_line) - width = edit_view.tab_width - imaginary_cursor_offset = ArrowHandler.real_offset_to_imaginary(line, width, doc.cursor_line_offset) - next_tab_stop_offset = (imaginary_cursor_offset/width + 1)*width - insert_string = " "*(next_tab_stop_offset - imaginary_cursor_offset) selections = doc.selection_ranges.map do |selection_range| line = doc.line_at_offset(selection_range.begin) line_offset = doc.offset_at_line(line) @@ -19,16 +14,37 @@ def self.handle(edit_view, modifiers) line_offset_end = selection_range.end - line_offset [line, line_offset_start, line_offset_end] end + length = 0 + selections.each do |line, line_offset_start, line_offset_end| + line_offset = doc.offset_at_line(line) + doc.replace(line_offset + line_offset_start, line_offset_end - line_offset_start, " "*(line_offset_end - line_offset_start)) + length = line_offset_end - line_offset_start + end + line = doc.get_line(doc.cursor_line) + width = edit_view.tab_width + imaginary_cursor_offset = ArrowHandler.real_offset_to_imaginary(line, width, doc.cursor_line_offset) + next_tab_stop_offset = (imaginary_cursor_offset/width + 1)*width + insert_string = " "*(next_tab_stop_offset - imaginary_cursor_offset) selections.each do |line, line_offset_start, line_offset_end| line_offset = doc.offset_at_line(line) - doc.delete(line_offset + line_offset_start, line_offset_end - line_offset_start) doc.insert(line_offset + line_offset_start, insert_string) end + new_selection_ranges = selections.map do |line, line_offset_start, line_offset_end| + offset = doc.offset_at_line(line) + line_offset_end + insert_string.length + [offset, offset] + end + doc.set_selection_range(new_selection_ranges.last.last, new_selection_ranges.first.first) true else false end else + if doc.selection? + bits = [doc.cursor_offset, doc.selection_offset].sort + start = bits.first + length = bits.last - bits.first + doc.delete(start, length) + end if edit_view.soft_tabs? line = doc.get_line(doc.cursor_line) width = edit_view.tab_width diff --git a/plugins/edit_view/lib/edit_view/document.rb b/plugins/edit_view/lib/edit_view/document.rb index d09b5f7c4..dc07c0536 100644 --- a/plugins/edit_view/lib/edit_view/document.rb +++ b/plugins/edit_view/lib/edit_view/document.rb @@ -115,29 +115,6 @@ def single_line? controller.single_line? end - # The line index the cursor is on (zero-based) - # - # @return [Integer] - def cursor_line - line_at_offset(cursor_offset) - end - - def cursor_line_start_offset - offset_at_line(cursor_line) - end - - def cursor_line_end_offset - offset_at_line_end(cursor_line) - end - - def offset_at_line_end(line_ix) - if line_ix == line_count - 1 - end_offset = length - else - end_offset = offset_at_line(line_ix + 1) - end - end - # Is there any text selected? (Or equivalently, is the length # of the selection equal to 0) # @@ -239,6 +216,29 @@ def cursor_offset=(offset) controller.cursor_offset = offset end + # The line index the cursor is on (zero-based) + # + # @return [Integer] + def cursor_line + line_at_offset(cursor_offset) + end + + def cursor_line_start_offset + offset_at_line(cursor_line) + end + + def cursor_line_end_offset + offset_at_line_end(cursor_line) + end + + def offset_at_line_end(line_ix) + if line_ix == line_count - 1 + end_offset = length + else + end_offset = offset_at_line(line_ix + 1) + end + end + # The range of text selected by the user. # # @return [Range] a range between two character offsets diff --git a/plugins/edit_view_swt/lib/edit_view_swt/document.rb b/plugins/edit_view_swt/lib/edit_view_swt/document.rb index d23580ad9..71028c574 100644 --- a/plugins/edit_view_swt/lib/edit_view_swt/document.rb +++ b/plugins/edit_view_swt/lib/edit_view_swt/document.rb @@ -91,7 +91,19 @@ def selection_ranges end def set_selection_range(cursor_offset, selection_offset) - styledText.set_selection_range(selection_offset, cursor_offset - selection_offset) + if block_selection_mode? + start_offset, end_offset = *[cursor_offset, selection_offset].sort + start_location = styledText.getLocationAtOffset(start_offset) + end_location = styledText.getLocationAtOffset(end_offset) + styledText.set_block_selection_bounds( + start_location.x, + start_location.y, + end_location.x - start_location.x, + end_location.y - start_location.y + styledText.get_line_height + ) + else + styledText.set_selection_range(selection_offset, cursor_offset - selection_offset) + end @model.selection_range_changed(cursor_offset, selection_offset) end