Skip to content

Commit

Permalink
Fix Shift+↑/↓ wifh hanging indent (close #1585)
Browse files Browse the repository at this point in the history
  • Loading branch information
1024jp committed Dec 13, 2024
1 parent 76e6269 commit 6aa85ee
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 36 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
5.0.7 (unreleased)
--------------------------

### Fixes

- Fix an issue that the end point of the selection shifted after the hanging indent of a wrapped line when the line endings are CRLF and the selection is expanded by using the `⇧↑` or `⇧↓` shortcuts.



5.0.6 (688)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ extension EditorTextView {
return super.moveLeftAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) {
self.layoutManager!.leftCharacterIndex(of: $0, baseWritingDirection: self.baseWritingDirection)
self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) { (cursor, _) in
self.layoutManager!.leftCharacterIndex(of: cursor, baseWritingDirection: self.baseWritingDirection)
}
}

Expand Down Expand Up @@ -90,8 +90,8 @@ extension EditorTextView {
return super.moveRightAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) {
self.layoutManager!.rightCharacterIndex(of: $0, baseWritingDirection: self.baseWritingDirection)
self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) { (cursor, _) in
self.layoutManager!.rightCharacterIndex(of: cursor, baseWritingDirection: self.baseWritingDirection)
}
}

Expand All @@ -116,8 +116,8 @@ extension EditorTextView {
return super.moveUpAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) {
self.upperInsertionLocation(of: $0)
self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) { (cursor, origin) in
self.upperInsertionLocation(of: cursor, origin: origin)
}
}

Expand All @@ -142,8 +142,8 @@ extension EditorTextView {
return super.moveDownAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: true, affinity: .downstream) {
self.lowerInsertionLocation(of: $0)
self.moveCursorsAndModifySelection(forward: true, affinity: .downstream) { (cursor, origin) in
self.lowerInsertionLocation(of: cursor, origin: origin)
}
}

Expand Down Expand Up @@ -171,8 +171,8 @@ extension EditorTextView {
return self.moveWordAndModifySelection(sender, left: true)
}

self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) {
self.textStorage!.nextWord(from: $0, forward: self.layoutManager!.isRTL(at: $0), delimiters: .additionalWordSeparators)
self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) { (cursor, _) in
self.textStorage!.nextWord(from: cursor, forward: self.layoutManager!.isRTL(at: cursor), delimiters: .additionalWordSeparators)
}
}

Expand All @@ -195,8 +195,8 @@ extension EditorTextView {
return self.moveWordAndModifySelection(sender, left: false)
}

self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) {
self.textStorage!.nextWord(from: $0, forward: !self.layoutManager!.isRTL(at: $0), delimiters: .additionalWordSeparators)
self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) { (cursor, _) in
self.textStorage!.nextWord(from: cursor, forward: !self.layoutManager!.isRTL(at: cursor), delimiters: .additionalWordSeparators)
}
}

Expand All @@ -208,8 +208,8 @@ extension EditorTextView {
return super.moveParagraphBackwardAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) {
(self.string as NSString).lineStartIndex(at: self.string.index(before: $0))
self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) { (cursor, _) in
(self.string as NSString).lineStartIndex(at: self.string.index(before: cursor))
}
}

Expand All @@ -221,8 +221,8 @@ extension EditorTextView {
return super.moveParagraphForwardAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) {
(self.string as NSString).lineContentsEndIndex(at: self.string.index(after: $0))
self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) { (cursor, _) in
(self.string as NSString).lineContentsEndIndex(at: self.string.index(after: cursor))
}
}

Expand Down Expand Up @@ -322,8 +322,8 @@ extension EditorTextView {
return
}

self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) {
self.locationOfBeginningOfLine(for: $0)
self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) { (cursor, _) in
self.locationOfBeginningOfLine(for: cursor)
}
}

Expand All @@ -350,8 +350,8 @@ extension EditorTextView {
}

let length = self.attributedString().length
self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) {
self.layoutManager?.lineFragmentRange(at: $0).upperBound ?? length
self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) { (cursor, _) in
self.layoutManager?.lineFragmentRange(at: cursor).upperBound ?? length
}
}

Expand Down Expand Up @@ -435,8 +435,8 @@ extension EditorTextView {
return super.moveToBeginningOfParagraphAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) {
(self.string as NSString).lineStartIndex(at: $0)
self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) { (cursor, _) in
(self.string as NSString).lineStartIndex(at: cursor)
}
}

Expand All @@ -463,8 +463,8 @@ extension EditorTextView {
return super.moveToEndOfParagraphAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) {
(self.string as NSString).lineContentsEndIndex(at: $0)
self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) { (cursor, _) in
(self.string as NSString).lineContentsEndIndex(at: cursor)
}
}

Expand All @@ -489,8 +489,8 @@ extension EditorTextView {
return super.moveWordBackwardAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) {
self.textStorage!.nextWord(from: $0, forward: false, delimiters: .additionalWordSeparators)
self.moveCursorsAndModifySelection(forward: false, affinity: .downstream) { (cursor, _) in
self.textStorage!.nextWord(from: cursor, forward: false, delimiters: .additionalWordSeparators)
}
}

Expand All @@ -515,8 +515,8 @@ extension EditorTextView {
return super.moveWordForwardAndModifySelection(sender)
}

self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) {
self.textStorage!.nextWord(from: $0, forward: true, delimiters: .additionalWordSeparators)
self.moveCursorsAndModifySelection(forward: true, affinity: .upstream) { (cursor, _) in
self.textStorage!.nextWord(from: cursor, forward: true, delimiters: .additionalWordSeparators)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ extension MultiCursorEditing {
/// - affinity: The selection affinity for the movement.
/// - block: The block that describes the rule how to move the cursor.
/// - cursor: The character index of the cursor to move.
func moveCursorsAndModifySelection(forward: Bool, affinity: NSSelectionAffinity, using block: (_ cursor: Int) -> Int) {
/// - origin: The character index of the selection origin.
func moveCursorsAndModifySelection(forward: Bool, affinity: NSSelectionAffinity, using block: (_ cursor: Int, _ origin: Int) -> Int) {

var origins = self.selectionOrigins
var newOrigins: [Int] = []
Expand All @@ -304,7 +305,7 @@ extension MultiCursorEditing {
case (true, _): (range.upperBound, range.lowerBound)
}

let newCursor = block(cursor)
let newCursor = block(cursor, newOrigin)

newOrigins.append(origin ?? newOrigin)

Expand Down Expand Up @@ -484,9 +485,11 @@ extension NSTextView {
///
/// - Note: This API requires TextKit 1.
///
/// - Parameter index: The character index of the reference insertion point.
/// - Parameters:
/// - index: The character index of the reference insertion point.
/// - origin: The character index of the reference for the column location, or `nil` if `index` is also used to refer to the column.
/// - Returns: The character index of the objective insertion point location or `0` if cannot move.
final func upperInsertionLocation(of index: Int) -> Int {
final func upperInsertionLocation(of index: Int, origin: Int? = nil) -> Int {

guard
let layoutManager = self.layoutManager,
Expand All @@ -495,8 +498,17 @@ extension NSTextView {

let glyphIndex = layoutManager.glyphIndexForCharacter(at: index)
let rect = layoutManager.boundingRect(forGlyphRange: NSRange(location: glyphIndex, length: 0), in: textContainer)

let x: CGFloat
if let origin {
let glyphIndex = layoutManager.glyphIndexForCharacter(at: origin)
x = layoutManager.location(forGlyphAt: glyphIndex).x
} else {
x = rect.minX
}

let point = NSPoint(x: x, y: rect.minY - 1)
.offset(by: self.textContainerOrigin)
let point = NSPoint(x: rect.minX, y: rect.minY - 1)

return self.characterIndexForInsertion(at: point)
}
Expand All @@ -506,9 +518,11 @@ extension NSTextView {
///
/// - Note: This API requires TextKit 1.
///
/// - Parameter index: The character index of the reference insertion point.
/// - Parameters:
/// - index: The character index of the reference insertion point.
/// - origin: The character index of the reference for the column location, or `nil` if `index` is also used to refer to the column.
/// - Returns: The character index of the objective insertion point location or end of the document if cannot move.
final func lowerInsertionLocation(of index: Int) -> Int {
final func lowerInsertionLocation(of index: Int, origin: Int? = nil) -> Int {

guard
let layoutManager = self.layoutManager,
Expand All @@ -517,8 +531,17 @@ extension NSTextView {

let glyphIndex = layoutManager.glyphIndexForCharacter(at: index)
let rect = layoutManager.boundingRect(forGlyphRange: NSRange(location: glyphIndex, length: 0), in: textContainer)

let x: CGFloat
if let origin {
let glyphIndex = layoutManager.glyphIndexForCharacter(at: origin)
x = layoutManager.location(forGlyphAt: glyphIndex).x
} else {
x = rect.minX
}

let point = NSPoint(x: x, y: rect.maxY + 1)
.offset(by: self.textContainerOrigin)
let point = NSPoint(x: rect.minX, y: rect.maxY + 1)

return self.characterIndexForInsertion(at: point)
}
Expand Down

0 comments on commit 6aa85ee

Please sign in to comment.