diff --git a/runtime/src/ceramic/EditText.hx b/runtime/src/ceramic/EditText.hx index 57337c3cc..28d157723 100644 --- a/runtime/src/ceramic/EditText.hx +++ b/runtime/src/ceramic/EditText.hx @@ -601,6 +601,28 @@ class EditText extends Entity implements Component implements TextInputDelegate emitUpdate(newText); }); + keyBindings.bind([CMD_OR_CTRL, KEY(KeyCode.LEFT)], function() { + // CMD/CTRL + LEFT Arrow Key + if (screen.focusedVisual != entity) + return; + + var pos = selectText.findPreviousWordBoundary(selectText.selectionStart); + + selectText.selectionStart = pos; + selectText.selectionEnd = pos; + }); + + keyBindings.bind([CMD_OR_CTRL, KEY(KeyCode.RIGHT)], function() { + // CMD/CTRL + RIGHT Arrow Key + if (screen.focusedVisual != entity) + return; + + var pos = selectText.findNextWordBoundary(selectText.selectionStart); + + selectText.selectionStart = pos; + selectText.selectionEnd = pos; + }); + onDestroy(keyBindings, function(_) { keyBindings.destroy(); keyBindings = null; diff --git a/runtime/src/ceramic/SelectText.hx b/runtime/src/ceramic/SelectText.hx index ce34d065b..292e64db8 100644 --- a/runtime/src/ceramic/SelectText.hx +++ b/runtime/src/ceramic/SelectText.hx @@ -147,6 +147,49 @@ class SelectText extends Entity implements Component implements Observable { } +/// Public apis + + public function findPreviousWordBoundary(fromPos:Int) { + var content = entity.content; + + if (fromPos <= 0) { + return 0; + } + + var leftPart = content.substring(0, fromPos); + var wordBoundaryRegex = ~/(\S+)\s*$/; + + if (wordBoundaryRegex.match(leftPart)) { + return wordBoundaryRegex.matchedPos().pos; + } + + return 0; + } + + public function findNextWordBoundary(fromPos:Int) { + var content = entity.content; + var contentLength = content.length; + + if (fromPos >= contentLength) { + return contentLength; + } + + var rightPart = content.substring(fromPos); + var nextWordRegex = ~/^\S*\s*(\S|$)/; + + if (nextWordRegex.match(rightPart)) { + var matchInfo = nextWordRegex.matchedPos(); + var pos = fromPos + matchInfo.pos + matchInfo.len - 1; + + if (pos > contentLength || rightPart.charAt(matchInfo.pos + matchInfo.len - 1) == '') { + pos = contentLength; + } + return pos; + } + + return contentLength; + } + function bindAsComponent() { entity.onGlyphQuadsChange(this, updateSelectionGraphics);