Выбор в NSTextView - PullRequest
       89

Выбор в NSTextView

0 голосов
/ 17 апреля 2020

Я хочу реализовать следующую функцию: в моем подклассе NSTextView я слушаю опцию + стрелка вверх и опция + стрелка вниз. Всякий раз, когда эти ярлыки запускаются, выбор текстовых представлений должен расширяться / сворачиваться следующим образом:

  • Курсор
  • Текущее слово под курсором
  • Текст под курсором до пробела
  • Текущее предложение под курсором
  • Текущий абзац под курсором
  • Весь текст TextView

Однако моя реализация работает, когда бы я ни расширял выбор, я «перезаписать» позицию курсора, и поэтому я не могу снова правильно свернуть выделение. Вот пример того, чего я хочу достичь: https://caret.io/feat/feat-extend.gif

Мое текущее решение основано на поиске следующего большего выбора из текущего выбора и выглядит так:

private func selectNextTextBlock() {
        let location = insertionLocation ?? selectedRange().location
        let wr = wordRange(at: location)
        let wgr = wordGroupRange(at: location)
        let sr = sentenceRange(at: location)
        let pr = paragraphRange(at: location)

        if self.selectedRange().length == 0 {
            self.setSelectedRangesWithUndo([wr])
        } else if self.selectedRange().length >= wr.length && self.selectedRange().length < wgr.length {
            self.setSelectedRangesWithUndo([wgr])
        } else if self.selectedRange().length >= wgr.length && self.selectedRange().length < sr.length {
            self.setSelectedRangesWithUndo([sr])
        } else if self.selectedRange().length >= sr.length && self.selectedRange().length < pr.length {
            setSelectedRangesWithUndo([pr])
        } else {
            setSelectedRangesWithUndo([NSRange(location: 0, length: string.count)])
        }
    }

    private func selectPreviousTextBlock() {
        #warning("implement?")
    }

    private func wordRange(at location: Int) -> NSRange {
        let proposedWordRange = super.selectionRange(forProposedRange: NSRange(location: location, length: 0), granularity: .selectByWord)
        guard proposedWordRange.contains(location) else { return proposedWordRange }
        // treat `.` and `:` as word delimiter
        return (self.string as NSString).rangeOfCharacter(until: CharacterSet(charactersIn: ".:"), at: location, range: proposedWordRange)
    }

    private func wordGroupRange(at location: Int) -> NSRange {
        let proposedWordRange = super.selectionRange(forProposedRange: NSRange(location: location, length: 0), granularity: .selectByParagraph)
        guard proposedWordRange.contains(location) else { return proposedWordRange }
        // treat `whitespaces and newlines` as word delimiter
        return (self.string as NSString).rangeOfCharacter(until: CharacterSet.whitespacesAndNewlines, at: location, range: proposedWordRange)
    }

    private func sentenceRange(at location: Int) -> NSRange {
        let proposedWordRange = super.selectionRange(forProposedRange: NSRange(location: location, length: 0), granularity: .selectByParagraph)
        guard proposedWordRange.contains(location) else { return proposedWordRange }
        // treat `.` and `:` as paragraph delimiter
        var range = (self.string as NSString).rangeOfCharacter(until: CharacterSet(charactersIn: ".:"), at: location, range: proposedWordRange)
        range.length += 1
        return range
    }

    private func paragraphRange(at location: Int) -> NSRange {
        return super.selectionRange(forProposedRange: NSRange(location: location, length: 0), granularity: .selectByParagraph)
    }

Есть какие-нибудь подсказки для меня о том, как реализовать selectPreviousTextBlock? Поскольку пользователь может изменить позицию курсора вручную, я не могу гарантировать сохранение правильной последней позиции курсора в selectNextTextBlock

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...