fortrangoingonforty/facsimile / 1b015a7

Browse files

fixes

Authored by espadonne
SHA
1b015a78276f2abe6f61a587e76fa8b531d0b08a
Parents
66cb258
Tree
a3ec4a3

2 changed files

StatusFile+-
M src/commands/command_handler_module.f90 44 32
M test/integration_test.py 32 7
src/commands/command_handler_module.f90modified
@@ -561,16 +561,23 @@ contains
561561
         pos = cursor%column
562562
 
563563
         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
574581
 
575582
             cursor%column = pos
576583
         else if (cursor%line < line_count) then
@@ -2114,15 +2121,17 @@ contains
21142121
         type(buffer_t), intent(in) :: buffer
21152122
         integer, intent(in) :: line, column
21162123
         integer :: pos
2117
-        integer :: current_line, i
2124
+        integer :: current_line, i, col_in_line
21182125
         character :: ch
21192126
 
21202127
         pos = 1
21212128
         current_line = 1
2129
+        col_in_line = 1
21222130
 
21232131
         ! Find the position for the given line and column
21242132
         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
21262135
                 return
21272136
             end if
21282137
 
@@ -2130,21 +2139,18 @@ contains
21302139
             if (ch == char(10)) then
21312140
                 if (current_line == line) then
21322141
                     ! We're at the end of the target line
2142
+                    pos = i
21332143
                     return
21342144
                 end if
21352145
                 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
21392149
             end if
21402150
         end do
21412151
 
21422152
         ! 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
21482154
     end function get_buffer_position
21492155
 
21502156
     function get_buffer_content_size(buffer) result(size)
@@ -2622,7 +2628,7 @@ contains
26222628
         type(cursor_t), intent(inout) :: cursor
26232629
         type(buffer_t), intent(inout) :: buffer
26242630
         character(len=:), allocatable :: current_line, next_line
2625
-        integer :: line_count, current_len
2631
+        integer :: line_count, current_len, leading_spaces
26262632
 
26272633
         line_count = buffer_get_line_count(buffer)
26282634
 
@@ -2634,19 +2640,25 @@ contains
26342640
         next_line = buffer_get_line(buffer, cursor%line + 1)
26352641
         current_len = len(current_line)
26362642
 
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
26392650
 
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
26472657
 
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
26502662
                 if (current_line(current_len:current_len) /= ' ') then
26512663
                     call buffer_insert_text_at(buffer, cursor%line, current_len + 1, ' ')
26522664
                 end if
test/integration_test.pymodified
@@ -48,9 +48,21 @@ class FacsimileTest:
4848
     def stop(self) -> None:
4949
         """Stop the editor and clean up."""
5050
         if self.process:
51
-            self.send_key('ctrl-q')
52
-            self.process.expect(pexpect.EOF)
53
-            self.process = None
51
+            try:
52
+                # Save first to avoid unsaved changes prompt
53
+                self.send_key('ctrl-s')
54
+                time.sleep(0.1)
55
+                # Now quit
56
+                self.send_key('ctrl-q')
57
+                self.process.expect(pexpect.EOF, timeout=2)
58
+            except pexpect.TIMEOUT:
59
+                # Force terminate if it doesn't exit cleanly
60
+                self.process.terminate()
61
+                time.sleep(0.1)
62
+            except:
63
+                pass
64
+            finally:
65
+                self.process = None
5466
 
5567
         # Clean up temp file
5668
         if self.test_file:
@@ -70,22 +82,27 @@ class FacsimileTest:
7082
             'ctrl-q': '\x11', 'ctrl-r': '\x12', 'ctrl-s': '\x13', 'ctrl-t': '\x14',
7183
             'ctrl-u': '\x15', 'ctrl-v': '\x16', 'ctrl-w': '\x17', 'ctrl-x': '\x18',
7284
             'ctrl-y': '\x19', 'ctrl-z': '\x1a',
85
+            'ctrl-shift-z': '\x1a',  # Redo (may need different mapping)
7386
             'escape': '\x1b', 'enter': '\n', 'tab': '\t',
7487
             'backspace': '\x7f', 'delete': '\x1b[3~',
7588
             'up': '\x1b[A', 'down': '\x1b[B', 'right': '\x1b[C', 'left': '\x1b[D',
7689
             'home': '\x1b[H', 'end': '\x1b[F',
7790
             'pageup': '\x1b[5~', 'pagedown': '\x1b[6~',
7891
             'alt-[': '\x1b[', 'alt-]': '\x1b]',
92
+            'alt-right': '\x1b[1;3C', 'alt-left': '\x1b[1;3D',
7993
         }
8094
 
8195
         if key in key_map:
8296
             self.process.send(key_map[key])
97
+            time.sleep(0.05)  # Small delay between key presses
8398
         else:
8499
             print(f"Warning: Unknown key '{key}'")
85100
 
86101
     def type_text(self, text: str) -> None:
87102
         """Type regular text into the editor."""
88
-        self.process.send(text)
103
+        for char in text:
104
+            self.process.send(char)
105
+            time.sleep(0.01)  # Small delay between characters
89106
 
90107
     def save_file(self) -> None:
91108
         """Save the current file."""
@@ -125,17 +142,24 @@ class TestRunner:
125142
         print("=" * 60)
126143
 
127144
         for name, test_func in self.tests:
145
+            editor = None
128146
             try:
129147
                 editor = FacsimileTest()
130148
                 test_func(editor)
131149
                 print(f"✓ {name}")
132150
                 self.passed += 1
133
-            except Exception as e:
151
+            except AssertionError as e:
134152
                 print(f"✗ {name}: {str(e)}")
135153
                 self.failed += 1
154
+            except Exception as e:
155
+                print(f"✗ {name}: Unexpected error: {e.__class__.__name__}: {str(e)}")
156
+                self.failed += 1
136157
             finally:
137
-                if 'editor' in locals():
138
-                    editor.stop()
158
+                if editor:
159
+                    try:
160
+                        editor.stop()
161
+                    except:
162
+                        pass  # Ignore cleanup errors
139163
 
140164
         print("-" * 60)
141165
         print(f"Tests run: {self.passed + self.failed}, Passed: {self.passed}, Failed: {self.failed}")
@@ -153,6 +177,7 @@ def test_basic_typing(editor: FacsimileTest):
153177
     """Test basic text input."""
154178
     editor.start("")
155179
     editor.type_text("Hello World")
180
+    time.sleep(0.5)  # Give more time for text to be typed
156181
     content = editor.get_file_content()
157182
     assert content == "Hello World", f"Expected 'Hello World', got '{content}'"
158183