Skip to content

Commit 49a60c5

Browse files
committed
inline placeholder
1 parent c5f4970 commit 49a60c5

2 files changed

Lines changed: 88 additions & 45 deletions

File tree

SquirrelInputController.m

Lines changed: 81 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,9 @@ @implementation SquirrelInputController {
2930
NSString *_schemaId;
3031
BOOL _inlinePreedit;
3132
BOOL _inlineCandidate;
33+
// app-specific bug fix
34+
BOOL _inlinePlaceHolder;
35+
BOOL _panellessCommitFix;
3236
// for chord-typing
3337
int _chordKeyCodes[N_KEY_ROLL_OVER];
3438
int _chordModifiers[N_KEY_ROLL_OVER];
@@ -49,9 +53,6 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender
4953
// Key processing will not continue in that case. In other words the
5054
// system will not deliver a key down event to the application.
5155
// Returning NO means the original key down will be passed on to the client.
52-
53-
_currentClient = sender;
54-
5556
NSUInteger modifiers = event.modifierFlags;
5657

5758
BOOL handled = NO;
@@ -64,7 +65,7 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender
6465
}
6566
}
6667

67-
NSString* app = [_currentClient bundleIdentifier];
68+
NSString* app = [sender bundleIdentifier];
6869

6970
if (![_currentApp isEqualToString:app]) {
7071
_currentApp = [app copy];
@@ -319,14 +320,15 @@ -(void)activateServer:(id)sender
319320
if (keyboardLayout) {
320321
[sender overrideKeyboardWithKeyboardNamed:keyboardLayout];
321322
}
322-
_preeditString = @"";
323+
_preeditString = nil;
324+
_originalString = nil;
325+
_composedString = nil;
323326
}
324327

325328
-(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(id)inputClient
326329
{
327330
//NSLog(@"initWithServer:delegate:client:");
328331
if (self = [super initWithServer:server delegate:delegate client:inputClient]) {
329-
_currentClient = inputClient;
330332
[self createSession];
331333
}
332334
return self;
@@ -335,7 +337,6 @@ -(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(i
335337
-(void)deactivateServer:(id)sender
336338
{
337339
//NSLog(@"deactivateServer:");
338-
[NSApp.squirrelAppDelegate.panel hide];
339340
[self commitComposition:sender];
340341
}
341342

@@ -353,13 +354,9 @@ -(void)deactivateServer:(id)sender
353354
-(void)commitComposition:(id)sender
354355
{
355356
//NSLog(@"commitComposition:");
356-
// commit raw input
357357
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-
}
358+
[self commitString:[self composedString:sender]];
359+
rime_get_api()->clear_composition(_session);
363360
}
364361
}
365362

@@ -402,54 +399,85 @@ -(NSArray*)candidates:(id)sender
402399
return _candidates;
403400
}
404401

405-
-(void)dealloc
402+
- (void)hidePalettes
403+
{
404+
[NSApp.squirrelAppDelegate.panel hide];
405+
}
406+
407+
- (void)dealloc
406408
{
407409
[self destroySession];
408410
}
409411

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

416-
_preeditString = @"";
429+
_composedString = nil;
430+
_originalString = nil;
431+
_preeditString = nil;
432+
}
417433

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

421447
-(void)showPreeditString:(NSString*)preedit
422448
selRange:(NSRange)range
423449
caretPos:(NSUInteger)pos
424450
{
425451
//NSLog(@"showPreeditString: '%@'", preedit);
426-
427-
if ([_preeditString isEqualToString:preedit] &&
428-
_caretPos == pos && _selRange.location == range.location && _selRange.length == range.length)
452+
if ([preedit isEqualToString:_preeditString.string] &&
453+
NSEqualRanges(range, _selRange) && pos == _caretPos) {
454+
if (_inlinePlaceHolder) {
455+
[self updateComposition];
456+
}
429457
return;
430-
431-
_preeditString = preedit;
458+
}
432459
_selRange = range;
433460
_caretPos = pos;
434461

435462
//NSLog(@"selRange.location = %ld, selRange.length = %ld; caretPos = %ld",
436463
// range.location, range.length, pos);
437-
NSDictionary* attrs;
438-
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:preedit];
464+
NSDictionary *attrs;
465+
_preeditString = [[NSMutableAttributedString alloc] initWithString:preedit];
439466
if (range.location > 0) {
440467
NSRange convertedRange = NSMakeRange(0, range.location);
441468
attrs = [self markForStyle:kTSMHiliteConvertedText atRange:convertedRange];
442-
[attrString setAttributes:attrs range:convertedRange];
469+
[_preeditString addAttributes:attrs range:convertedRange];
443470
}
444-
{
445-
NSRange remainingRange = NSMakeRange(range.location, preedit.length - range.location);
446-
attrs = [self markForStyle:kTSMHiliteSelectedRawText atRange:remainingRange];
447-
[attrString setAttributes:attrs range:remainingRange];
471+
if (range.location < pos) {
472+
attrs = [self markForStyle:kTSMHiliteSelectedConvertedText atRange:range];
473+
[_preeditString addAttributes:attrs range:range];
448474
}
449-
[_currentClient setMarkedText:attrString
450-
selectionRange:NSMakeRange(pos, 0)
451-
replacementRange:NSMakeRange(NSNotFound, 0)];
452-
475+
if (MIN(NSMaxRange(range), pos) < preedit.length) {
476+
NSRange rawRange = NSMakeRange(MIN(NSMaxRange(range), pos), preedit.length - MIN(NSMaxRange(range), pos));
477+
attrs = [self markForStyle:kTSMHiliteSelectedRawText atRange:rawRange];
478+
[_preeditString addAttributes:attrs range:rawRange];
479+
}
480+
[self updateComposition];
453481
}
454482

455483
-(void)showPanelWithPreedit:(NSString*)preedit
@@ -463,7 +491,7 @@ -(void)showPanelWithPreedit:(NSString*)preedit
463491
//NSLog(@"showPanelWithPreedit:...:");
464492
_candidates = candidates;
465493
NSRect inputPos;
466-
[_currentClient attributesForCharacterIndex:0 lineHeightRectangle:&inputPos];
494+
[self.client attributesForCharacterIndex:0 lineHeightRectangle:&inputPos];
467495
SquirrelPanel* panel = NSApp.squirrelAppDelegate.panel;
468496
panel.position = inputPos;
469497
panel.inputController = self;
@@ -485,7 +513,7 @@ @implementation SquirrelInputController(Private)
485513

486514
-(void)createSession
487515
{
488-
NSString* app = [_currentClient bundleIdentifier];
516+
NSString* app = [self.client bundleIdentifier];
489517
NSLog(@"createSession: %@", app);
490518
_currentApp = [app copy];
491519
_session = rime_get_api()->create_session();
@@ -508,6 +536,8 @@ -(void)updateAppOptions
508536
NSLog(@"set app option: %@ = %d", key, value);
509537
rime_get_api()->set_option(_session, key.UTF8String, value);
510538
}
539+
_panellessCommitFix = (appOptions[@"panelless_commit_fix"] ? : @(NO)).boolValue;
540+
_inlinePlaceHolder = (appOptions[@"inline_placeholder"] ? : @(NO)).boolValue;
511541
}
512542
}
513543

@@ -521,15 +551,19 @@ -(void)destroySession
521551
[self clearChord];
522552
}
523553

524-
-(void)rimeConsumeCommittedText
554+
-(BOOL)rimeConsumeCommittedText
525555
{
526556
RIME_STRUCT(RimeCommit, commit);
527557
if (rime_get_api()->get_commit(_session, &commit)) {
528558
NSString *commitText = @(commit.text);
529-
[self showPreeditString:@" " selRange:NSMakeRange(0, 0) caretPos:0];
559+
if (_preeditString.length == 0 && _panellessCommitFix) {
560+
[self showPreeditString:@" " selRange:NSMakeRange(0, 0) caretPos:0];
561+
}
530562
[self commitString:commitText];
531563
rime_get_api()->free_commit(&commit);
564+
return YES;
532565
}
566+
return NO;
533567
}
534568

535569
NSString *substr(const char *str, int length) {
@@ -542,7 +576,9 @@ -(void)rimeConsumeCommittedText
542576
-(void)rimeUpdate
543577
{
544578
//NSLog(@"rimeUpdate");
545-
[self rimeConsumeCommittedText];
579+
if ([self rimeConsumeCommittedText]) {
580+
return;
581+
}
546582

547583
RIME_STRUCT(RimeStatus, status);
548584
if (rime_get_api()->get_status(_session, &status)) {
@@ -592,11 +628,11 @@ -(void)rimeUpdate
592628
if (_inlinePreedit) {
593629
[self showPreeditString:preeditText selRange:selRange caretPos:caretPos];
594630
} else {
595-
NSRange empty = {0, 0};
596631
// TRICKY: display a non-empty string to prevent iTerm2 from echoing each character in preedit.
597632
// note this is a full-shape space U+3000; using half shape characters like "..." will result in
598633
// an unstable baseline when composing Chinese characters.
599-
[self showPreeditString:(preedit ? @" " : @"") selRange:empty caretPos:0];
634+
[self showPreeditString:(preedit && _inlinePlaceHolder ? @" " : @"")
635+
selRange:NSMakeRange(0, 0) caretPos:0];
600636
}
601637
}
602638
// 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)