fortrangoingonforty/fortsh / 853c41e

Browse files

add Ctrl+V paste from clipboard with kill-buffer fallback

Authored by espadonne
SHA
853c41e44a96a0e68eaea578d8a135301e9bd4e7
Parents
dd2b33c
Tree
b22ef96

2 changed files

StatusFile+-
M src/io/readline.f90 51 1
M tests/interactive/utils/keys.py 2 1
src/io/readline.f90modified
@@ -47,6 +47,7 @@ module readline
4747
   integer, parameter :: KEY_TAB = 9
4848
   integer, parameter :: KEY_CTRL_C = 3
4949
   integer, parameter :: KEY_CTRL_D = 4
50
+  integer, parameter :: KEY_CTRL_V = 22   ! Paste from system clipboard / kill buffer
5051
   integer, parameter :: KEY_CTRL_X = 24   ! Process kill mode
5152
   integer, parameter :: KEY_CTRL_A = 1    ! Home (beginning of line)
5253
   integer, parameter :: KEY_CTRL_E = 5    ! End (end of line)
@@ -1673,6 +1674,13 @@ contains
16731674
             call handle_kill_word(module_input_state)
16741675
           end if
16751676
           
1677
+        case(KEY_CTRL_V)
1678
+          ! Ctrl+V — paste (Sprint 5). Reads from the system clipboard
1679
+          ! first; falls back to the in-session kill_buffer if no
1680
+          ! clipboard tool is available or the clipboard is empty.
1681
+          ! If a selection is active, it's deleted first (paste-over).
1682
+          if (.not. module_input_state%in_search) call handle_paste(module_input_state)
1683
+
16761684
         case(KEY_CTRL_Y)
16771685
           ! Yank - no-op in search mode
16781686
           if (.not. module_input_state%in_search) call handle_yank(module_input_state)
@@ -7514,7 +7522,49 @@ contains
75147522
     input_state%cursor_pos = input_state%cursor_pos + insert_len
75157523
     input_state%dirty = .true.
75167524
   end subroutine
7517
-  
7525
+
7526
+  ! Ctrl+V paste handler (Sprint 5). Reads from the system clipboard;
7527
+  ! if the clipboard is empty or no tool is available, falls back to
7528
+  ! yanking from the in-session kill_buffer. If a selection is active
7529
+  ! it is deleted first (paste-over behavior, same as Ctrl+Y).
7530
+  subroutine handle_paste(input_state)
7531
+    type(input_state_t), intent(inout) :: input_state
7532
+    character(len=MAX_LINE_LEN) :: paste_buf
7533
+    integer :: paste_len, insert_len, i, j
7534
+
7535
+    ! Delete active selection first (paste-over).
7536
+    if (input_state%selection_active) call delete_selection(input_state)
7537
+
7538
+    ! Try the system clipboard.
7539
+    paste_len = 0
7540
+    call clipboard_paste(paste_buf, MAX_LINE_LEN, paste_len)
7541
+
7542
+    if (paste_len > 0) then
7543
+      ! Truncate to available space.
7544
+      insert_len = min(paste_len, MAX_LINE_LEN - input_state%length)
7545
+      if (insert_len <= 0) return
7546
+
7547
+      ! Shift existing text right.
7548
+      do i = input_state%length, input_state%cursor_pos + 1, -1
7549
+        if (i + insert_len <= MAX_LINE_LEN) then
7550
+          call state_buffer_set_char(input_state, i + insert_len, state_buffer_get_char(input_state, i))
7551
+        end if
7552
+      end do
7553
+
7554
+      ! Insert clipboard text at cursor.
7555
+      do j = 1, insert_len
7556
+        call state_buffer_set_char(input_state, input_state%cursor_pos + j, paste_buf(j:j))
7557
+      end do
7558
+
7559
+      input_state%length = input_state%length + insert_len
7560
+      input_state%cursor_pos = input_state%cursor_pos + insert_len
7561
+      input_state%dirty = .true.
7562
+    else
7563
+      ! Clipboard empty or unavailable — fall back to kill buffer (same as C-y).
7564
+      call handle_yank(input_state)
7565
+    end if
7566
+  end subroutine handle_paste
7567
+
75187568
   subroutine handle_clear_screen(input_state, prompt)
75197569
     type(input_state_t), intent(inout) :: input_state
75207570
     character(len=*), intent(in) :: prompt
tests/interactive/utils/keys.pymodified
@@ -55,7 +55,7 @@ CTRL_R = "\x12" # Reverse search
5555
 CTRL_S = "\x13"  # Forward search / Suspend output
5656
 CTRL_T = "\x14"  # Transpose characters
5757
 CTRL_U = "\x15"  # Kill to beginning of line
58
-CTRL_V = "\x16"  # Quoted insert
58
+CTRL_V = "\x16"  # Paste from clipboard / kill buffer
5959
 CTRL_W = "\x17"  # Kill word backward
6060
 CTRL_X = "\x18"  # Prefix
6161
 CTRL_Y = "\x19"  # Yank
@@ -154,6 +154,7 @@ KEYS = {
154154
     "C-s": CTRL_S,
155155
     "C-t": CTRL_T,
156156
     "C-u": CTRL_U,
157
+    "C-v": CTRL_V,
157158
     "C-w": CTRL_W,
158159
     "C-y": CTRL_Y,
159160
     "C-z": CTRL_Z,