gpt4 book ai didi

objective-c - 如何通过双击使 NSTextView 平衡分隔符?

转载 作者:行者123 更新时间:2023-12-03 17:49:16 27 4
gpt4 key购买 nike

通常有一个用于代码或其他结构化内容的文本编辑器来平衡某种分隔符;当您双击 { 时,它会选择匹配的 },或者类似地选择 ( ) 对、[ ] 对等。我如何在 Cocoa/Obj-C 的 NSTextView 中实现此行为?

(我将立即发布答案,因为我在 SO 上没有找到任何关于此问题的信息,并且今天花了一些时间实现解决方案。欢迎更好的答案。)

附录:

这与 this question 不同,这是关于 NSTextField 的,主要涉及 NSTextField 和字段编辑器问题。 如果通过将自定义 NSTextView 子类替换到字段编辑器中来解决该问题,那么该自定义子类当然可以使用此处给出的解决方案;但是可能还有很多其他方法可以解决 NSTextField 的问题,并且将自定义的 NSTextView 子类替换到字段编辑器中显然不是该问题的正确解决方案,并且在无论如何,关心 NSTextView 中分隔符平衡(这可能是更常见的问题)的程序员可能不太关心所有这些 NSTextField 和字段编辑器问题。所以这是一个不同的问题 - 尽管我会添加从该问题到此问题的链接,作为它可能的发展方向。

这也与this question不同。 ,这实际上是在双击时更改 NSTextView 中“单词”的定义。根据Apple's documentation ,这些是不同的问题,有不同的解决方案;对于分隔符平衡(这个问题)Apple 特别建议使用 NSTextViewselectionRangeForProfusedRange:grinarity: 方法,而对于更改单词的定义(这个问题)Apple特别指出,不应使用selectionRangeForProposedRange:capsularity: 方法。

最佳答案

在他们的 Cocoa Text Architecture Guide ( https://developer.apple.com/library/prerelease/mac/documentation/TextFonts/Conceptual/CocoaTextArchitecture/TextEditing/TextEditing.html ) 中,Apple 建议子类化 NSTextView 并覆盖 selectionRangeForProposedRange:capsularity: 来实现此类事情;他们甚至说“例如,在代码编辑器中,您可以提供一个委托(delegate),将大括号或括号字符上的双击扩展到其匹配的分隔符。”但是,目前尚不清楚如何实现这一点,因为您希望分隔符匹配仅在简单双击分隔符之后发生,而不是在双击拖动甚至双击按住释放之后发生.

我能想到的最佳解决方案还包括覆盖mouseDown:,并对事态进行一些记录。也许有更简单的方法。我省略了实际计算分隔符匹配的代码核心部分;这取决于您要匹配的分隔符、可能存在的语法复杂性(字符串、注释)等等。在我的代码中,我实际上调用了标记生成器来获取标记流,然后使用它来查找匹配的分隔符。 YMMV。所以,这就是我所得到的:

在您的 NSTextView 子类接口(interface)(或类扩展,更好)中:

// these are used in selectionRangeForProposedRange:granularity:
// to balance delimiters properly
BOOL inEligibleDoubleClick;
NSTimeInterval doubleDownTime;

在您的 NSTextView 子类实现中:

- (void)mouseDown:(NSEvent *)theEvent
{
// Start out willing to work with a double-click for delimiter-balancing;
// see selectionRangeForProposedRange:proposedCharRange granularity: below
inEligibleDoubleClick = YES;

[super mouseDown:theEvent];
}

- (NSRange)selectionRangeForProposedRange:(NSRange)proposedCharRange
granularity:(NSSelectionGranularity)granularity
{
if ((granularity == NSSelectByWord) && inEligibleDoubleClick)
{
// The proposed range has to be zero-length to qualify
if (proposedCharRange.length == 0)
{
NSEvent *event = [NSApp currentEvent];
NSEventType eventType = [event type];
NSTimeInterval eventTime = [event timestamp];

if (eventType == NSLeftMouseDown)
{
// This is the mouseDown of the double-click; we do not want
// to modify the selection here, just log the time
doubleDownTime = eventTime;
}
else if (eventType == NSLeftMouseUp)
{
// After the double-click interval since the second mouseDown,
// the mouseUp is no longer eligible
if (eventTime - doubleDownTime <= [NSEvent doubleClickInterval])
{
NSString *scriptString = [[self textStorage] string];

...insert delimiter-finding code here...
...return the matched range, or NSBeep()...
}
else
{
inEligibleDoubleClick = false;
}
}
else
{
inEligibleDoubleClick = false;
}
}
else
{
inEligibleDoubleClick = false;
}
}

return [super selectionRangeForProposedRange:proposedCharRange
granularity:granularity];
}

它有点脆弱,因为它依赖于 NSTextView 的跟踪以特定方式工作并以特定方式调用 selectionRangeForProposedRange:grinarity:,但是假设并不大;我认为它非常强大。

关于objective-c - 如何通过双击使 NSTextView 平衡分隔符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32673991/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com