Skip to content

Commit fc24909

Browse files
committed
inline placeholder
1 parent c5f4970 commit fc24909

2 files changed

Lines changed: 90 additions & 45 deletions

File tree

SquirrelInputController.m

Lines changed: 83 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@
1010
@interface SquirrelInputController(Private)
1111
-(void)createSession;
1212
-(void)destroySession;
13-
-(void)rimeConsumeCommittedText;
13+
-(BOOL)rimeConsumeCommittedText;
1414
-(void)rimeUpdate;
1515
-(void)updateAppOptions;
1616
@end
1717

1818
const int N_KEY_ROLL_OVER = 50;
1919

2020
@implementation SquirrelInputController {
21-
id _currentClient;
22-
NSString *_preeditString;
21+
NSMutableAttributedString *_preeditString;
22+
NSAttributedString *_originalString;
23+
NSString *_composedString;
2324
NSRange _selRange;
2425
NSUInteger _caretPos;
2526
NSArray *_candidates;
@@ -29,6 +30,10 @@ @implementation SquirrelInputController {
2930
NSString *_schemaId;
3031
BOOL _inlinePreedit;
3132
BOOL _inlineCandidate;
33+
BOOL _isComposing;
34+
// app-specific bug fix
35+
BOOL _inlinePlaceHolder;
36+
BOOL _panellessCommitFix;
3237
// for chord-typing
3338
int _chordKeyCodes[N_KEY_ROLL_OVER];
3439
int _chordModifiers[N_KEY_ROLL_OVER];
@@ -49,9 +54,6 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender
4954
// Key processing will not continue in that case. In other words the
5055
// system will not deliver a key down event to the application.
5156
// Returning NO means the original key down will be passed on to the client.
52-
53-
_currentClient = sender;
54-
5557
NSUInteger modifiers = event.modifierFlags;
5658

5759
BOOL handled = NO;
@@ -64,7 +66,7 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender
6466
}
6567
}
6668

67-
NSString* app = [_currentClient bundleIdentifier];
69+
NSString* app = [sender bundleIdentifier];
6870

6971
if (![_currentApp isEqualToString:app]) {
7072
_currentApp = [app copy];
@@ -319,14 +321,15 @@ -(void)activateServer:(id)sender
319321
if (keyboardLayout) {
320322
[sender overrideKeyboardWithKeyboardNamed:keyboardLayout];
321323
}
322-
_preeditString = @"";
324+
_preeditString = nil;
325+
_originalString = nil;
326+
_composedString = nil;
323327
}
324328

325329
-(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(id)inputClient
326330
{
327331
//NSLog(@"initWithServer:delegate:client:");
328332
if (self = [super initWithServer:server delegate:delegate client:inputClient]) {
329-
_currentClient = inputClient;
330333
[self createSession];
331334
}
332335
return self;
@@ -335,7 +338,6 @@ -(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(i
335338
-(void)deactivateServer:(id)sender
336339
{
337340
//NSLog(@"deactivateServer:");
338-
[NSApp.squirrelAppDelegate.panel hide];
339341
[self commitComposition:sender];
340342
}
341343

@@ -353,13 +355,9 @@ -(void)deactivateServer:(id)sender
353355
-(void)commitComposition:(id)sender
354356
{
355357
//NSLog(@"commitComposition:");
356-
// commit raw input
357358
if (_session) {
358-
const char* raw_input = rime_get_api()->get_input(_session);
359-
if (raw_input) {
360-
[self commitString: @(raw_input)];
361-
rime_get_api()->clear_composition(_session);
362-
}
359+
[self commitString:[self composedString:sender]];
360+
rime_get_api()->clear_composition(_session);
363361
}
364362
}
365363

@@ -402,54 +400,85 @@ -(NSArray*)candidates:(id)sender
402400
return _candidates;
403401
}
404402

405-
-(void)dealloc
403+
- (void)hidePalettes
404+
{
405+
[NSApp.squirrelAppDelegate.panel hide];
406+
}
407+
408+
- (void)dealloc
406409
{
407410
[self destroySession];
408411
}
409412

410-
-(void)commitString:(NSString*)string
413+
- (NSRange)selectionRange
414+
{
415+
return NSMakeRange(_caretPos, 0);
416+
}
417+
418+
- (NSRange)replacementRange
419+
{
420+
return _isComposing ? self.client.selectedRange : NSMakeRange(NSNotFound, NSNotFound);
421+
}
422+
423+
- (void)commitString:(id)string
411424
{
412425
//NSLog(@"commitString:");
413-
[_currentClient insertText:string
414-
replacementRange:NSMakeRange(NSNotFound, 0)];
426+
[self.client insertText:string
427+
replacementRange:self.replacementRange];
428+
[self hidePalettes];
415429

416-
_preeditString = @"";
430+
_composedString = nil;
431+
_originalString = nil;
432+
_preeditString = nil;
433+
}
417434

418-
[NSApp.squirrelAppDelegate.panel hide];
435+
- (void)cancelComposition
436+
{
437+
[self commitString:[self originalString:self.client]];
438+
rime_get_api()->clear_composition(_session);
439+
}
440+
441+
- (void)updateComposition
442+
{
443+
[self.client setMarkedText:_preeditString
444+
selectionRange:self.selectionRange
445+
replacementRange:self.replacementRange];
419446
}
420447

421448
-(void)showPreeditString:(NSString*)preedit
422449
selRange:(NSRange)range
423450
caretPos:(NSUInteger)pos
424451
{
425452
//NSLog(@"showPreeditString: '%@'", preedit);
426-
427-
if ([_preeditString isEqualToString:preedit] &&
428-
_caretPos == pos && _selRange.location == range.location && _selRange.length == range.length)
453+
if ([preedit isEqualToString:_preeditString.string] &&
454+
NSEqualRanges(range, _selRange) && pos == _caretPos) {
455+
if (_inlinePlaceHolder) {
456+
[self updateComposition];
457+
}
429458
return;
430-
431-
_preeditString = preedit;
459+
}
432460
_selRange = range;
433461
_caretPos = pos;
434462

435463
//NSLog(@"selRange.location = %ld, selRange.length = %ld; caretPos = %ld",
436464
// range.location, range.length, pos);
437-
NSDictionary* attrs;
438-
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:preedit];
465+
NSDictionary *attrs;
466+
_preeditString = [[NSMutableAttributedString alloc] initWithString:preedit];
439467
if (range.location > 0) {
440468
NSRange convertedRange = NSMakeRange(0, range.location);
441469
attrs = [self markForStyle:kTSMHiliteConvertedText atRange:convertedRange];
442-
[attrString setAttributes:attrs range:convertedRange];
470+
[_preeditString addAttributes:attrs range:convertedRange];
443471
}
444-
{
445-
NSRange remainingRange = NSMakeRange(range.location, preedit.length - range.location);
446-
attrs = [self markForStyle:kTSMHiliteSelectedRawText atRange:remainingRange];
447-
[attrString setAttributes:attrs range:remainingRange];
472+
if (range.location < pos) {
473+
attrs = [self markForStyle:kTSMHiliteSelectedConvertedText atRange:range];
474+
[_preeditString addAttributes:attrs range:range];
448475
}
449-
[_currentClient setMarkedText:attrString
450-
selectionRange:NSMakeRange(pos, 0)
451-
replacementRange:NSMakeRange(NSNotFound, 0)];
452-
476+
if (MIN(NSMaxRange(range), pos) < preedit.length) {
477+
NSRange rawRange = NSMakeRange(MIN(NSMaxRange(range), pos), preedit.length - MIN(NSMaxRange(range), pos));
478+
attrs = [self markForStyle:kTSMHiliteSelectedRawText atRange:rawRange];
479+
[_preeditString addAttributes:attrs range:rawRange];
480+
}
481+
[self updateComposition];
453482
}
454483

455484
-(void)showPanelWithPreedit:(NSString*)preedit
@@ -463,7 +492,7 @@ -(void)showPanelWithPreedit:(NSString*)preedit
463492
//NSLog(@"showPanelWithPreedit:...:");
464493
_candidates = candidates;
465494
NSRect inputPos;
466-
[_currentClient attributesForCharacterIndex:0 lineHeightRectangle:&inputPos];
495+
[self.client attributesForCharacterIndex:0 lineHeightRectangle:&inputPos];
467496
SquirrelPanel* panel = NSApp.squirrelAppDelegate.panel;
468497
panel.position = inputPos;
469498
panel.inputController = self;
@@ -485,7 +514,7 @@ @implementation SquirrelInputController(Private)
485514

486515
-(void)createSession
487516
{
488-
NSString* app = [_currentClient bundleIdentifier];
517+
NSString* app = [self.client bundleIdentifier];
489518
NSLog(@"createSession: %@", app);
490519
_currentApp = [app copy];
491520
_session = rime_get_api()->create_session();
@@ -508,6 +537,8 @@ -(void)updateAppOptions
508537
NSLog(@"set app option: %@ = %d", key, value);
509538
rime_get_api()->set_option(_session, key.UTF8String, value);
510539
}
540+
_panellessCommitFix = (appOptions[@"panelless_commit_fix"] ? : @(NO)).boolValue;
541+
_inlinePlaceHolder = (appOptions[@"inline_placeholder"] ? : @(NO)).boolValue;
511542
}
512543
}
513544

@@ -521,15 +552,19 @@ -(void)destroySession
521552
[self clearChord];
522553
}
523554

524-
-(void)rimeConsumeCommittedText
555+
-(BOOL)rimeConsumeCommittedText
525556
{
526557
RIME_STRUCT(RimeCommit, commit);
527558
if (rime_get_api()->get_commit(_session, &commit)) {
528559
NSString *commitText = @(commit.text);
529-
[self showPreeditString:@" " selRange:NSMakeRange(0, 0) caretPos:0];
560+
if (_preeditString.length == 0 && _panellessCommitFix) {
561+
[self showPreeditString:@" " selRange:NSMakeRange(0, 0) caretPos:0];
562+
}
530563
[self commitString:commitText];
531564
rime_get_api()->free_commit(&commit);
565+
return YES;
532566
}
567+
return NO;
533568
}
534569

535570
NSString *substr(const char *str, int length) {
@@ -542,7 +577,9 @@ -(void)rimeConsumeCommittedText
542577
-(void)rimeUpdate
543578
{
544579
//NSLog(@"rimeUpdate");
545-
[self rimeConsumeCommittedText];
580+
if ([self rimeConsumeCommittedText]) {
581+
return;
582+
}
546583

547584
RIME_STRUCT(RimeStatus, status);
548585
if (rime_get_api()->get_status(_session, &status)) {
@@ -558,6 +595,7 @@ -(void)rimeUpdate
558595
!rime_get_api()->get_option(_session, "no_inline"));
559596
// if not inline, embed soft cursor in preedit string
560597
rime_get_api()->set_option(_session, "soft_cursor", !_inlinePreedit);
598+
_isComposing = status.is_composing;
561599
}
562600
rime_get_api()->free_status(&status);
563601
}
@@ -592,11 +630,11 @@ -(void)rimeUpdate
592630
if (_inlinePreedit) {
593631
[self showPreeditString:preeditText selRange:selRange caretPos:caretPos];
594632
} else {
595-
NSRange empty = {0, 0};
596633
// TRICKY: display a non-empty string to prevent iTerm2 from echoing each character in preedit.
597634
// note this is a full-shape space U+3000; using half shape characters like "..." will result in
598635
// an unstable baseline when composing Chinese characters.
599-
[self showPreeditString:(preedit ? @" " : @"") selRange:empty caretPos:0];
636+
[self showPreeditString:(preedit && _inlinePlaceHolder ? @" " : @"")
637+
selRange:NSMakeRange(0, 0) caretPos:0];
600638
}
601639
}
602640
// update candidates

data/squirrel.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ app_options:
341341
com.apple.Terminal:
342342
ascii_mode: true
343343
no_inline: true
344+
inline_placeholder: true
344345
com.googlecode.iterm2:
345346
ascii_mode: true
346347
no_inline: true
@@ -350,6 +351,7 @@ app_options:
350351
vim_mode: true # 退出VIM插入模式自動切換輸入法狀態
351352
com.apple.dt.Xcode:
352353
ascii_mode: true
354+
no_inline: true
353355
com.barebones.textwrangler:
354356
ascii_mode: true
355357
com.macromates.TextMate.preview:
@@ -367,9 +369,14 @@ app_options:
367369
no_inline: true
368370
co.zeit.hyper:
369371
ascii_mode: true
372+
org.alacritty:
373+
ascii_mode: true
374+
vim_mode: true
375+
panelless_commit_fix: true
370376
com.google.Chrome:
371377
# 規避 https://github.com/rime/squirrel/issues/435
372378
inline: true
379+
inline_placeholder: true
373380
ru.keepcoder.Telegram:
374381
# 規避 https://github.com/rime/squirrel/issues/475
375382
inline: true

0 commit comments

Comments
 (0)