You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix Writing Tools integration and fix up Services integration with texts
Apple "Intelligence" Writing Tools was previously not working correctly
with MacVim. When the user chooses to replace the original selection
with the updated texts, MacVim mistreats the input and treat them as
commands instead of raw texts. The reason was that even though this
service uses the NSServicesMenuRequestor API to obtain the selected
texts, it does not use it to send over the replacement. Instead, it uses
NSTextInput's `insertText:replacementRange` to do so instead, which we
never implemented properly. The reason behind this choice was probably
because Writing Tools first shows a UI with user interaction and has a
delay between obtaining the texts and replacing them, like a regular
Services menu. This means the selection may already be invalid by the
time it requests a replacement.
To fix this, add a new IPC API `replaceSelectedText` to replace the
selected texts and redirect `insertText:replacementRange` to use it if
the replacement range is non-empty. This isn't the most correct
implementation of the protocol but should work in most cases. We don't
have a way to implement it "correctly" as MacVim does not have easy
access to Vim's internal text storage. Also make sure the Service
menu uses this API (for things like "convert to full width" and
Traditional/Simplified Chinese conversions). The old method of simple
injecting a normal mode command `s` before the text was horribly buggy.
It also works with visual block selection properly now.
The implementation uses Vim's register put functionality because Vim
doesn't have an API to simply replace a block of text, and everything
has to go through registers. At the same time, replace the
implementation for the old `selectedText` IPC API to not do this,
because Vim *did* end an API to do so for obtaining texts (via
`getregion()`) and it's more stable to use this than to manually
cache/restore registers.
Related: vim/vim#16596 (fixes `setreg()` which this uses)
Fix#1512
/// Extracts the text currently selected in visual mode, and returns it.
1384
-
///
1385
-
/// @return the string representing the selected text, or NULL if failure.
1386
-
static char_u *extractSelectedText(void)
1387
-
{
1388
-
// Note: Most of the functionality in Vim that allows for extracting useful
1389
-
// text from a selection are in the register & clipboard utility functions.
1390
-
// Unfortunately, most of those functions would actually send the text to
1391
-
// the system clipboard, which we don't want (since we just want to extract
1392
-
// the text instead of polluting the system clipboard). We don't want to
1393
-
// refactor upstream Vim code too much to avoid merge pains later, so we
1394
-
// duplicate a fair bit of the code from the functions below.
1395
-
1396
-
if (!(VIsual_active && (State & MODE_NORMAL))) {
1397
-
// This only works when we are in visual mode and have stuff to select.
1398
-
returnNULL;
1399
-
}
1400
-
1401
-
// Step 1: Find a register to yank the selection to. If we don't do this we
1402
-
// have to duplicate a lot of code in op_yank(). We save it off to a backup
1403
-
// first so we can restore it later to avoid polluting the registers.
1404
-
1405
-
// Just use the yank / '0' register as it makes sense, but it doesn't
1406
-
// really matter.
1407
-
yankreg_T *target_reg = get_y_register(0);
1408
-
1409
-
// Move the contents to the backup without doing memory allocs.
1410
-
yankreg_T backup_reg = *target_reg;
1411
-
target_reg->y_array = NULL;
1412
-
target_reg->y_size = 0;
1413
-
1414
-
// Step 2: Preserve the local states, and then invoke yank.
1415
-
// Note: These were copied from clip_get_selection() in clipboard.c
1416
-
yankreg_T *old_y_previous, *old_y_current;
1417
-
pos_T old_cursor;
1418
-
pos_T old_visual;
1419
-
int old_visual_mode;
1420
-
colnr_T old_curswant;
1421
-
int old_set_curswant;
1422
-
pos_T old_op_start, old_op_end;
1423
-
oparg_T oa;
1424
-
cmdarg_T ca;
1425
-
1426
-
// Avoid triggering autocmds such as TextYankPost.
1427
-
block_autocmds();
1428
-
1429
-
// Yank the selected text into the target register.
1430
-
old_y_previous = get_y_previous();
1431
-
old_y_current = get_y_current();
1432
-
old_cursor = curwin->w_cursor;
1433
-
old_curswant = curwin->w_curswant;
1434
-
old_set_curswant = curwin->w_set_curswant;
1435
-
old_op_start = curbuf->b_op_start;
1436
-
old_op_end = curbuf->b_op_end;
1437
-
old_visual = VIsual;
1438
-
old_visual_mode = VIsual_mode;
1439
-
clear_oparg(&oa);
1440
-
oa.regname = '0'; // Use the '0' (yank) register. We will restore it later to avoid pollution.
1441
-
oa.op_type = OP_YANK;
1442
-
CLEAR_FIELD(ca);
1443
-
ca.oap = &oa;
1444
-
ca.cmdchar = 'y';
1445
-
ca.count1 = 1;
1446
-
ca.retval = CA_NO_ADJ_OP_END;
1447
-
do_pending_operator(&ca, 0, TRUE);
1448
-
1449
-
// Step 3: Extract the text from the yank ('0') register.
1450
-
char_u *str = get_reg_contents(0, 0);
1451
-
1452
-
// Step 4: Clean up the yank register, and restore it back.
1453
-
set_y_current(target_reg); // should not be necessary as it's done in do_pending_operator above (since regname was set to 0), but just to be safe and verbose in intention.
1454
-
free_yank_all();
1455
-
*target_reg = backup_reg;
1456
-
1457
-
// Step 5: Restore all the loose states that were modified during yank.
1458
-
// Note: These were copied from clip_get_selection() in clipboard.c
1459
-
set_y_previous(old_y_previous);
1460
-
set_y_current(old_y_current);
1461
-
curwin->w_cursor = old_cursor;
1462
-
changed_cline_bef_curs(); // need to update w_virtcol et al
1463
-
curwin->w_curswant = old_curswant;
1464
-
curwin->w_set_curswant = old_set_curswant;
1465
-
curbuf->b_op_start = old_op_start;
1466
-
curbuf->b_op_end = old_op_end;
1467
-
VIsual = old_visual;
1468
-
VIsual_mode = old_visual_mode;
1469
-
1470
-
unblock_autocmds();
1471
-
1472
-
return str;
1473
-
}
1474
-
1475
-
/// Extract the currently selected text (in visual mode) and send that to the
0 commit comments