Adds emacs-style hotkeys.
This commit is contained in:
parent
232a944953
commit
9cd2306313
|
@ -104,6 +104,16 @@ enum {
|
||||||
kDeleteKeyCode = 117
|
kDeleteKeyCode = 117
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, McBpomofoEmacsKey) {
|
||||||
|
McBpomofoEmacsKeyNone,
|
||||||
|
McBpomofoEmacsKeyForward,
|
||||||
|
McBpomofoEmacsKeyBackward,
|
||||||
|
McBpomofoEmacsKeyHome,
|
||||||
|
McBpomofoEmacsKeyEnd,
|
||||||
|
McBpomofoEmacsKeyDelete,
|
||||||
|
McBpomofoEmacsKeyNextPage,
|
||||||
|
};
|
||||||
|
|
||||||
VTCandidateController *gCurrentCandidateController = nil;
|
VTCandidateController *gCurrentCandidateController = nil;
|
||||||
|
|
||||||
// if DEBUG is defined, a DOT file (GraphViz format) will be written to the
|
// if DEBUG is defined, a DOT file (GraphViz format) will be written to the
|
||||||
|
@ -567,7 +577,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
NSBeep();
|
NSBeep();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (string)currentLayout
|
- (string)_currentLayout
|
||||||
{
|
{
|
||||||
string layout = string("Standard_");;
|
string layout = string("Standard_");;
|
||||||
NSInteger keyboardLayout = [[NSUserDefaults standardUserDefaults] integerForKey:kKeyboardLayoutPreferenceKey];
|
NSInteger keyboardLayout = [[NSUserDefaults standardUserDefaults] integerForKey:kKeyboardLayoutPreferenceKey];
|
||||||
|
@ -636,6 +646,33 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return [LanguageModelManager writeUserPhrase:currentMarkedPhrase];
|
return [LanguageModelManager writeUserPhrase:currentMarkedPhrase];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (McBpomofoEmacsKey)detectEmacsKeyFromCharCode:(UniChar)charCode modifiers:(NSUInteger)flags
|
||||||
|
{
|
||||||
|
if (flags & NSControlKeyMask) {
|
||||||
|
char c = charCode + 'a' - 1;
|
||||||
|
if (c == 'a') {
|
||||||
|
return McBpomofoEmacsKeyHome;
|
||||||
|
}
|
||||||
|
else if (c == 'e') {
|
||||||
|
return McBpomofoEmacsKeyEnd;
|
||||||
|
}
|
||||||
|
else if (c == 'f') {
|
||||||
|
return McBpomofoEmacsKeyForward;
|
||||||
|
}
|
||||||
|
else if (c == 'b') {
|
||||||
|
return McBpomofoEmacsKeyBackward;
|
||||||
|
}
|
||||||
|
else if (c == 'd') {
|
||||||
|
return McBpomofoEmacsKeyDelete;
|
||||||
|
}
|
||||||
|
else if (c == 'v') {
|
||||||
|
return McBpomofoEmacsKeyNextPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return McBpomofoEmacsKeyNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)handleInputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInteger)flags client:(id)client
|
- (BOOL)handleInputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInteger)flags client:(id)client
|
||||||
{
|
{
|
||||||
NSRect textFrame = NSZeroRect;
|
NSRect textFrame = NSZeroRect;
|
||||||
|
@ -661,6 +698,8 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
// get the unicode character code
|
// get the unicode character code
|
||||||
UniChar charCode = [inputText length] ? [inputText characterAtIndex:0] : 0;
|
UniChar charCode = [inputText length] ? [inputText characterAtIndex:0] : 0;
|
||||||
|
|
||||||
|
McBpomofoEmacsKey emacsKey = [self detectEmacsKeyFromCharCode:charCode modifiers:flags];
|
||||||
|
|
||||||
if ([[client bundleIdentifier] isEqualToString:@"com.apple.Terminal"] && [NSStringFromClass([client class]) isEqualToString:@"IPMDServerClientWrapper"]) {
|
if ([[client bundleIdentifier] isEqualToString:@"com.apple.Terminal"] && [NSStringFromClass([client class]) isEqualToString:@"IPMDServerClientWrapper"]) {
|
||||||
// special handling for com.apple.Terminal
|
// special handling for com.apple.Terminal
|
||||||
_currentDeferredClient = client;
|
_currentDeferredClient = client;
|
||||||
|
@ -672,7 +711,9 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the composing buffer is empty and there's no reading, and there is some function key combination, we ignore it
|
// if the composing buffer is empty and there's no reading, and there is some function key combination, we ignore it
|
||||||
if (![_composingBuffer length] && _bpmfReadingBuffer->isEmpty() && ((flags & NSCommandKeyMask) || (flags & NSControlKeyMask) || (flags & NSAlternateKeyMask) || (flags & NSNumericPadKeyMask))) {
|
if (![_composingBuffer length] &&
|
||||||
|
_bpmfReadingBuffer->isEmpty() &&
|
||||||
|
((flags & NSCommandKeyMask) || (flags & NSControlKeyMask) || (flags & NSAlternateKeyMask) || (flags & NSNumericPadKeyMask))) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,7 +757,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
|
|
||||||
// if we have candidate, it means we need to pass the event to the candidate handler
|
// if we have candidate, it means we need to pass the event to the candidate handler
|
||||||
if ([_candidates count]) {
|
if ([_candidates count]) {
|
||||||
return [self handleCandidateEventWithInputText:inputText charCode:charCode keyCode:keyCode];
|
return [self _handleCandidateEventWithInputText:inputText charCode:charCode keyCode:keyCode emacsKey:(McBpomofoEmacsKey)emacsKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have marker index.
|
// If we have marker index.
|
||||||
|
@ -739,7 +780,8 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
// Shift + left
|
// Shift + left
|
||||||
if (keyCode == cursorBackwardKey && (flags & NSShiftKeyMask)) {
|
if ((keyCode == cursorBackwardKey || emacsKey == McBpomofoEmacsKeyBackward)
|
||||||
|
&& (flags & NSShiftKeyMask)) {
|
||||||
if (_builder->markerCursorIndex() > 0) {
|
if (_builder->markerCursorIndex() > 0) {
|
||||||
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() - 1);
|
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() - 1);
|
||||||
}
|
}
|
||||||
|
@ -750,7 +792,8 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
// Shift + Right
|
// Shift + Right
|
||||||
if (keyCode == cursorForwardKey && (flags & NSShiftKeyMask)) {
|
if ((keyCode == cursorForwardKey || emacsKey == McBpomofoEmacsKeyForward)
|
||||||
|
&& (flags & NSShiftKeyMask)) {
|
||||||
if (_builder->markerCursorIndex() < _builder->length()) {
|
if (_builder->markerCursorIndex() < _builder->length()) {
|
||||||
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() + 1);
|
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() + 1);
|
||||||
}
|
}
|
||||||
|
@ -883,7 +926,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle cursor backward
|
// handle cursor backward
|
||||||
if (keyCode == cursorBackwardKey) {
|
if (keyCode == cursorBackwardKey || emacsKey == McBpomofoEmacsKeyBackward) {
|
||||||
if (!_bpmfReadingBuffer->isEmpty()) {
|
if (!_bpmfReadingBuffer->isEmpty()) {
|
||||||
[self beep];
|
[self beep];
|
||||||
}
|
}
|
||||||
|
@ -915,7 +958,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle cursor forward
|
// handle cursor forward
|
||||||
if (keyCode == cursorForwardKey) {
|
if (keyCode == cursorForwardKey || emacsKey == McBpomofoEmacsKeyForward) {
|
||||||
if (!_bpmfReadingBuffer->isEmpty()) {
|
if (!_bpmfReadingBuffer->isEmpty()) {
|
||||||
[self beep];
|
[self beep];
|
||||||
}
|
}
|
||||||
|
@ -945,7 +988,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyCode == kHomeKeyCode) {
|
if (keyCode == kHomeKeyCode || emacsKey == McBpomofoEmacsKeyHome) {
|
||||||
if (!_bpmfReadingBuffer->isEmpty()) {
|
if (!_bpmfReadingBuffer->isEmpty()) {
|
||||||
[self beep];
|
[self beep];
|
||||||
}
|
}
|
||||||
|
@ -966,7 +1009,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyCode == kEndKeyCode) {
|
if (keyCode == kEndKeyCode || emacsKey == McBpomofoEmacsKeyEnd) {
|
||||||
if (!_bpmfReadingBuffer->isEmpty()) {
|
if (!_bpmfReadingBuffer->isEmpty()) {
|
||||||
[self beep];
|
[self beep];
|
||||||
}
|
}
|
||||||
|
@ -1019,7 +1062,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
if (keyCode == kDeleteKeyCode) {
|
if (keyCode == kDeleteKeyCode || emacsKey == McBpomofoEmacsKeyDelete) {
|
||||||
if (_bpmfReadingBuffer->isEmpty()) {
|
if (_bpmfReadingBuffer->isEmpty()) {
|
||||||
if (![_composingBuffer length]) {
|
if (![_composingBuffer length]) {
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -1041,7 +1084,6 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Enter
|
// Enter
|
||||||
if (charCode == 13) {
|
if (charCode == 13) {
|
||||||
if (![_composingBuffer length]) {
|
if (![_composingBuffer length]) {
|
||||||
|
@ -1069,16 +1111,16 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// if nothing is matched, see if it's a punctuation key for current layout.
|
// if nothing is matched, see if it's a punctuation key for current layout.
|
||||||
string layout = [self currentLayout];
|
string layout = [self _currentLayout];
|
||||||
string punctuationNamePrefix = (_halfSizePunctuationEnabled ? string("_half_punctuation_"): string("_punctuation_"));
|
string punctuationNamePrefix = (_halfSizePunctuationEnabled ? string("_half_punctuation_"): string("_punctuation_"));
|
||||||
string customPunctuation = punctuationNamePrefix + layout + string(1, (char)charCode);
|
string customPunctuation = punctuationNamePrefix + layout + string(1, (char)charCode);
|
||||||
if ([self handlePunctuation:customPunctuation usingVerticalMode:useVerticalMode client:client]) {
|
if ([self _handlePunctuation:customPunctuation usingVerticalMode:useVerticalMode client:client]) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if nothing is matched, see if it's a punctuation key.
|
// if nothing is matched, see if it's a punctuation key.
|
||||||
string punctuation = punctuationNamePrefix + string(1, (char)charCode);
|
string punctuation = punctuationNamePrefix + string(1, (char)charCode);
|
||||||
if ([self handlePunctuation:punctuation usingVerticalMode:useVerticalMode client:client]) {
|
if ([self _handlePunctuation:punctuation usingVerticalMode:useVerticalMode client:client]) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1094,7 +1136,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)handlePunctuation:(string)customPunctuation usingVerticalMode:(BOOL)useVerticalMode client:(id)client
|
- (BOOL)_handlePunctuation:(string)customPunctuation usingVerticalMode:(BOOL)useVerticalMode client:(id)client
|
||||||
{
|
{
|
||||||
if (_languageModel->hasUnigramsForKey(customPunctuation)) {
|
if (_languageModel->hasUnigramsForKey(customPunctuation)) {
|
||||||
if (_bpmfReadingBuffer->isEmpty()) {
|
if (_bpmfReadingBuffer->isEmpty()) {
|
||||||
|
@ -1120,7 +1162,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)handleCandidateEventWithInputText:(NSString *)inputText charCode:(UniChar)charCode keyCode:(NSUInteger)keyCode
|
- (BOOL)_handleCandidateEventWithInputText:(NSString *)inputText charCode:(UniChar)charCode keyCode:(NSUInteger)keyCode emacsKey:(McBpomofoEmacsKey)emacsKey
|
||||||
{
|
{
|
||||||
BOOL cancelCandidateKey =
|
BOOL cancelCandidateKey =
|
||||||
(charCode == 27) ||
|
(charCode == 27) ||
|
||||||
|
@ -1143,7 +1185,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
[self candidateController:gCurrentCandidateController didSelectCandidateAtIndex:gCurrentCandidateController.selectedCandidateIndex];
|
[self candidateController:gCurrentCandidateController didSelectCandidateAtIndex:gCurrentCandidateController.selectedCandidateIndex];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
else if (charCode == 32 || keyCode == kPageDownKeyCode) {
|
else if (charCode == 32 || keyCode == kPageDownKeyCode || emacsKey == McBpomofoEmacsKeyNextPage) {
|
||||||
BOOL updated = [gCurrentCandidateController showNextPage];
|
BOOL updated = [gCurrentCandidateController showNextPage];
|
||||||
if (!updated) {
|
if (!updated) {
|
||||||
[self beep];
|
[self beep];
|
||||||
|
@ -1177,6 +1219,14 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (emacsKey == McBpomofoEmacsKeyBackward) {
|
||||||
|
BOOL updated = [gCurrentCandidateController highlightPreviousCandidate];
|
||||||
|
if (!updated) {
|
||||||
|
[self beep];
|
||||||
|
}
|
||||||
|
[self updateClientComposingBuffer:_currentCandidateClient];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
else if (keyCode == kRightKeyCode) {
|
else if (keyCode == kRightKeyCode) {
|
||||||
if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
|
if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
|
||||||
BOOL updated = [gCurrentCandidateController highlightNextCandidate];
|
BOOL updated = [gCurrentCandidateController highlightNextCandidate];
|
||||||
|
@ -1195,6 +1245,14 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (emacsKey == McBpomofoEmacsKeyForward) {
|
||||||
|
BOOL updated = [gCurrentCandidateController highlightNextCandidate];
|
||||||
|
if (!updated) {
|
||||||
|
[self beep];
|
||||||
|
}
|
||||||
|
[self updateClientComposingBuffer:_currentCandidateClient];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
else if (keyCode == kUpKeyCode) {
|
else if (keyCode == kUpKeyCode) {
|
||||||
if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
|
if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) {
|
||||||
BOOL updated = [gCurrentCandidateController showPreviousPage];
|
BOOL updated = [gCurrentCandidateController showPreviousPage];
|
||||||
|
@ -1231,7 +1289,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (keyCode == kHomeKeyCode) {
|
else if (keyCode == kHomeKeyCode || emacsKey == McBpomofoEmacsKeyHome) {
|
||||||
if (gCurrentCandidateController.selectedCandidateIndex == 0) {
|
if (gCurrentCandidateController.selectedCandidateIndex == 0) {
|
||||||
[self beep];
|
[self beep];
|
||||||
|
|
||||||
|
@ -1243,7 +1301,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
[self updateClientComposingBuffer:_currentCandidateClient];
|
[self updateClientComposingBuffer:_currentCandidateClient];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
else if (keyCode == kEndKeyCode && [_candidates count] > 0) {
|
else if ((keyCode == kEndKeyCode || emacsKey == McBpomofoEmacsKeyEnd) && [_candidates count] > 0) {
|
||||||
if (gCurrentCandidateController.selectedCandidateIndex == [_candidates count] - 1) {
|
if (gCurrentCandidateController.selectedCandidateIndex == [_candidates count] - 1) {
|
||||||
[self beep];
|
[self beep];
|
||||||
}
|
}
|
||||||
|
@ -1273,7 +1331,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_inputMode == kPlainBopomofoModeIdentifier) {
|
if (_inputMode == kPlainBopomofoModeIdentifier) {
|
||||||
string layout = [self currentLayout];
|
string layout = [self _currentLayout];
|
||||||
string customPunctuation = string("_punctuation_") + layout + string(1, (char)charCode);
|
string customPunctuation = string("_punctuation_") + layout + string(1, (char)charCode);
|
||||||
string punctuation = string("_punctuation_") + string(1, (char)charCode);
|
string punctuation = string("_punctuation_") + string(1, (char)charCode);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue