@@ -561,16 +561,23 @@ contains |
| 561 | 561 | pos = cursor%column |
| 562 | 562 | |
| 563 | 563 | if (pos <= len(line)) then |
| 564 | | - ! Skip current word |
| 565 | | - in_word = is_word_char(line(pos:pos)) |
| 566 | | - do while (pos <= len(line) .and. is_word_char(line(pos:pos)) .eqv. in_word) |
| 567 | | - pos = pos + 1 |
| 568 | | - end do |
| 569 | | - |
| 570 | | - ! Skip whitespace |
| 571 | | - do while (pos <= len(line) .and. line(pos:pos) == ' ') |
| 572 | | - pos = pos + 1 |
| 573 | | - end do |
| 564 | + ! Check what we're currently on |
| 565 | + if (pos <= len(line) .and. is_word_char(line(pos:pos))) then |
| 566 | + ! We're on a word character - skip to end of word |
| 567 | + do while (pos <= len(line) .and. is_word_char(line(pos:pos))) |
| 568 | + pos = pos + 1 |
| 569 | + end do |
| 570 | + else |
| 571 | + ! We're on whitespace or punctuation - skip to next word |
| 572 | + ! Skip non-word characters |
| 573 | + do while (pos <= len(line) .and. .not. is_word_char(line(pos:pos))) |
| 574 | + pos = pos + 1 |
| 575 | + end do |
| 576 | + ! Then skip to end of that word |
| 577 | + do while (pos <= len(line) .and. is_word_char(line(pos:pos))) |
| 578 | + pos = pos + 1 |
| 579 | + end do |
| 580 | + end if |
| 574 | 581 | |
| 575 | 582 | cursor%column = pos |
| 576 | 583 | else if (cursor%line < line_count) then |
@@ -2114,15 +2121,17 @@ contains |
| 2114 | 2121 | type(buffer_t), intent(in) :: buffer |
| 2115 | 2122 | integer, intent(in) :: line, column |
| 2116 | 2123 | integer :: pos |
| 2117 | | - integer :: current_line, i |
| 2124 | + integer :: current_line, i, col_in_line |
| 2118 | 2125 | character :: ch |
| 2119 | 2126 | |
| 2120 | 2127 | pos = 1 |
| 2121 | 2128 | current_line = 1 |
| 2129 | + col_in_line = 1 |
| 2122 | 2130 | |
| 2123 | 2131 | ! Find the position for the given line and column |
| 2124 | 2132 | do i = 1, get_buffer_content_size(buffer) |
| 2125 | | - if (current_line == line .and. pos == column) then |
| 2133 | + if (current_line == line .and. col_in_line == column) then |
| 2134 | + pos = i |
| 2126 | 2135 | return |
| 2127 | 2136 | end if |
| 2128 | 2137 | |
@@ -2130,21 +2139,18 @@ contains |
| 2130 | 2139 | if (ch == char(10)) then |
| 2131 | 2140 | if (current_line == line) then |
| 2132 | 2141 | ! We're at the end of the target line |
| 2142 | + pos = i |
| 2133 | 2143 | return |
| 2134 | 2144 | end if |
| 2135 | 2145 | current_line = current_line + 1 |
| 2136 | | - pos = 1 |
| 2137 | | - else if (current_line == line) then |
| 2138 | | - pos = pos + 1 |
| 2146 | + col_in_line = 1 |
| 2147 | + else |
| 2148 | + col_in_line = col_in_line + 1 |
| 2139 | 2149 | end if |
| 2140 | 2150 | end do |
| 2141 | 2151 | |
| 2142 | 2152 | ! If we reach here, we're at the end of the buffer |
| 2143 | | - if (current_line == line) then |
| 2144 | | - pos = i |
| 2145 | | - else |
| 2146 | | - pos = get_buffer_content_size(buffer) + 1 |
| 2147 | | - end if |
| 2153 | + pos = get_buffer_content_size(buffer) + 1 |
| 2148 | 2154 | end function get_buffer_position |
| 2149 | 2155 | |
| 2150 | 2156 | function get_buffer_content_size(buffer) result(size) |
@@ -2622,7 +2628,7 @@ contains |
| 2622 | 2628 | type(cursor_t), intent(inout) :: cursor |
| 2623 | 2629 | type(buffer_t), intent(inout) :: buffer |
| 2624 | 2630 | character(len=:), allocatable :: current_line, next_line |
| 2625 | | - integer :: line_count, current_len |
| 2631 | + integer :: line_count, current_len, leading_spaces |
| 2626 | 2632 | |
| 2627 | 2633 | line_count = buffer_get_line_count(buffer) |
| 2628 | 2634 | |
@@ -2634,19 +2640,25 @@ contains |
| 2634 | 2640 | next_line = buffer_get_line(buffer, cursor%line + 1) |
| 2635 | 2641 | current_len = len(current_line) |
| 2636 | 2642 | |
| 2637 | | - ! Delete the newline at the end of the current line |
| 2638 | | - call buffer_delete_range(buffer, cursor%line, current_len + 1, cursor%line + 1, 1) |
| 2643 | + ! Count leading whitespace in next line |
| 2644 | + leading_spaces = 0 |
| 2645 | + do while (leading_spaces < len(next_line) .and. & |
| 2646 | + (next_line(leading_spaces + 1:leading_spaces + 1) == ' ' .or. & |
| 2647 | + next_line(leading_spaces + 1:leading_spaces + 1) == char(9))) |
| 2648 | + leading_spaces = leading_spaces + 1 |
| 2649 | + end do |
| 2639 | 2650 | |
| 2640 | | - ! If the next line wasn't empty, insert a space between the lines |
| 2641 | | - if (len(trim(next_line)) > 0) then |
| 2642 | | - ! Find first non-whitespace character in next line |
| 2643 | | - do while (len(next_line) > 0 .and. & |
| 2644 | | - (next_line(1:1) == ' ' .or. next_line(1:1) == char(9))) |
| 2645 | | - next_line = next_line(2:) |
| 2646 | | - end do |
| 2651 | + ! Delete the newline and leading whitespace from next line |
| 2652 | + if (leading_spaces > 0) then |
| 2653 | + call buffer_delete_range(buffer, cursor%line, current_len + 1, cursor%line + 1, leading_spaces + 1) |
| 2654 | + else |
| 2655 | + call buffer_delete_range(buffer, cursor%line, current_len + 1, cursor%line + 1, 1) |
| 2656 | + end if |
| 2647 | 2657 | |
| 2648 | | - ! Insert a space if current line doesn't end with space and next line has content |
| 2649 | | - if (current_len > 0 .and. len(next_line) > 0) then |
| 2658 | + ! If the next line had non-whitespace content, insert a space between the lines |
| 2659 | + if (leading_spaces < len(next_line)) then |
| 2660 | + ! Insert a space if current line doesn't end with space |
| 2661 | + if (current_len > 0) then |
| 2650 | 2662 | if (current_line(current_len:current_len) /= ' ') then |
| 2651 | 2663 | call buffer_insert_text_at(buffer, cursor%line, current_len + 1, ' ') |
| 2652 | 2664 | end if |