如何告诉 NSTextView 在哪一侧扩展选择?

How to tell NSTextView which side to extend selection on?

如果我有一个 NSTextView 处于这种状态:

我如何告诉 textview,如果用户按下 shift+right,而不是向右延伸到 'o',而是取消选择 'e'?我虽然这与 affinity 有关,但我尝试通过以下代码将其设置为 NSSelectionAffinityUpstreamNSSelectionAffinityDownstream

[self setSelectionRange: NSMakeRange(9,6)
               affinity: x
         stillSelecting: NO];

但这并没有什么不同。按 shift+right 仍然选择 'o'.

NSTextView 知道如何以某种方式执行此操作,因为如果您将光标定位在 'w' 和 'o' 之间,然后按 shift+left直到它匹配屏幕截图,然后点击 shift+right,它匹配我提到的行为。

我可以覆盖 shift+arrow 代码并自己滚动,但我宁愿让 NSTextView 做它自己的事情。有人知道我是否遗漏了什么吗?

我不确定您要做什么,因为这是默认的文本 movement/selection 修改行为。您是否试图覆盖它以始终做这件事,或者您是否试图添加另一个覆盖此行为的键盘快捷键?在任何一种情况下,一些背景:

选择亲和力并不像听起来的那样有效(这让我在刚刚研究之后感到惊讶)。事实上,亲和力与对应于运动和 select 离子修饰的继承 NSResponder 动作之间似乎存在脱节。我稍后会讲到。

您要查看的是 -moveBackwardAndModifySelection:-moveWordBackwardAndModifySelection: 等响应者操作。根据文档,对此类 selection 修改移动操作的第一次调用确定了 selection 的 "end",随后将修改 selection 中的 selection任一方向。这意味着,如果您的第一个操作是 select 向前 (-moveForwardAndModifySelection:),则 "forward end"(从左到右语言的右端;从右到左的左端,自动) 是从那时起将要修改的内容,无论您调用 -moveForward... 还是 -moveBackward....

我通过查看 open source Cocoatron version of NSTextView 发现了 affinity 和 -move...AndModifySelection: 之间的脱节。似乎在任何 move-and-select 方法中都没有参考内部 _affinity 属性。它根据_selectionOrigin确定select离子范围变化应该是"upstream"还是"downstream",一个私有的属性,当select离子范围被修改(通过 -setSelectedRange(s)... 方法或鼠标向下/拖动)。我觉得亲和力属性就在那里供大家参考。将其覆盖为始终 return 一个值或另一个值不会改变任何行为,它只会向外界误报。 _selectionOrigin 似乎只能通过 -setSelectedRanges... 方法修改 如果 selection 是零长度(即,只是光标放置)。

因此,考虑到所有这些,您可能需要在手动 selection 修改中添加一个步骤:首先设置一个空的 selection,并在其中放置您想要的位置select离子原点(如果你想要向后亲和力则为前端;如果你想要向前亲和力则为后端),然后设置一个非零长度select具有所需亲和力的离子。

迂回和荒谬,我知道,但我认为这是必须的,考虑到 CocoaTron 源代码。