Remove influence of .commentsAtLineHead on uncommenting (#924)

This commit is contained in:
1024jp 2022-07-03 19:37:42 +09:00
parent 81b7e6990b
commit ce599e1c9f
4 changed files with 23 additions and 33 deletions

View File

@ -14,6 +14,7 @@ Change Log
- Change the system requirement to __macOS 12 Moneterey and later__.
- Improve the algorithm to parse numbers in the Sort by Parttern command.
- Improve the algorithm of uncommenting.
- [trivial] Improve the Basic Regular Expression Syntax reference.
- [non-AppStore ver.] Update Sparkle to 2.2.0.

View File

@ -48,7 +48,7 @@ extension EditorTextView: Commenting {
@IBAction func toggleComment(_ sender: Any?) {
if self.canUncomment(partly: false) {
self.uncomment(fromLineHead: self.commentsAtLineHead)
self.uncomment()
} else {
self.commentOut(types: .both, fromLineHead: self.commentsAtLineHead)
}
@ -79,7 +79,7 @@ extension EditorTextView: Commenting {
/// uncomment selection removing comment delimiters
@IBAction func uncomment(_ sender: Any?) {
self.uncomment(fromLineHead: false)
self.uncomment()
}
}
@ -122,11 +122,14 @@ extension Commenting {
guard
self.blockCommentDelimiters != nil || self.inlineCommentDelimiter != nil,
let targetRanges = self.commentingRanges(fromLineHead: fromLineHead)
let selectedRanges = self.rangesForUserTextChange?.map(\.rangeValue)
else { return }
let items: [NSRange.InsertionItem] = {
let spacer = self.appendsCommentSpacer ? " " : ""
let targetRanges = selectedRanges
.map { fromLineHead ? self.string.lineContentsRange(for: $0) : $0 }
.unique
if types.contains(.inline), let delimiter = self.inlineCommentDelimiter {
return self.string.inlineCommentOut(delimiter: delimiter, spacer: spacer, ranges: targetRanges)
@ -141,8 +144,7 @@ extension Commenting {
let newStrings = items.map(\.string)
let replacementRanges = items.map { NSRange(location: $0.location, length: 0) }
let newSelectedRanges = (self.rangesForUserTextChange ?? self.selectedRanges)
.map { $0.rangeValue.inserted(items: items) }
let newSelectedRanges = selectedRanges.map { $0.inserted(items: items) }
self.replace(with: newStrings, ranges: replacementRanges, selectedRanges: newSelectedRanges,
actionName: "Comment Out".localized)
@ -150,25 +152,24 @@ extension Commenting {
/// Uncomment selections by removing comment delimiters.
///
/// - Parameters:
/// - fromLineHead: When `true`, the receiver uncomments from the beginning of the line.
func uncomment(fromLineHead: Bool) {
func uncomment() {
guard
self.blockCommentDelimiters != nil || self.inlineCommentDelimiter != nil,
let targetRanges = self.commentingRanges(fromLineHead: fromLineHead)
let selectedRanges = self.rangesForUserTextChange?.map(\.rangeValue)
else { return }
let deletionRanges: [NSRange] = {
let spacer = self.appendsCommentSpacer ? " " : ""
if let delimiters = self.blockCommentDelimiters {
let targetRanges = selectedRanges.map { $0.isEmpty ? self.string.lineContentsRange(for: $0) : $0 }.unique
if let ranges = self.string.rangesOfBlockDelimiters(delimiters, spacer: spacer, ranges: targetRanges) {
return ranges
}
}
if let delimiter = self.inlineCommentDelimiter {
let targetRanges = selectedRanges.map { self.string.lineContentsRange(for: $0) }.unique
if let ranges = self.string.rangesOfInlineDelimiter(delimiter, spacer: spacer, ranges: targetRanges) {
return ranges
}
@ -179,8 +180,7 @@ extension Commenting {
guard !deletionRanges.isEmpty else { return }
let newStrings = [String](repeating: "", count: deletionRanges.count)
let newSelectedRanges = (self.rangesForUserTextChange ?? self.selectedRanges)
.map { $0.rangeValue.deleted(ranges: deletionRanges) }
let newSelectedRanges = selectedRanges.map { $0.deleted(ranges: deletionRanges) }
self.replace(with: newStrings, ranges: deletionRanges, selectedRanges: newSelectedRanges,
actionName: "Uncomment".localized)
@ -196,17 +196,19 @@ extension Commenting {
guard
self.blockCommentDelimiters != nil || self.inlineCommentDelimiter != nil,
let targetRanges = self.commentingRanges(fromLineHead: self.commentsAtLineHead),
let selectedRanges = self.rangesForUserTextChange?.map(\.rangeValue),
targetRanges.contains(where: { !$0.isEmpty })
else { return false }
if let delimiters = self.blockCommentDelimiters {
let targetRanges = selectedRanges.map { $0.isEmpty ? self.string.lineContentsRange(for: $0) : $0 }.unique
if let ranges = self.string.rangesOfBlockDelimiters(delimiters, spacer: "", ranges: targetRanges) {
return partly ? true : (ranges.count == (2 * targetRanges.count))
}
}
if let delimiter = self.inlineCommentDelimiter {
let targetRanges = selectedRanges.map { self.string.lineContentsRange(for: $0) }.unique
if let ranges = self.string.rangesOfInlineDelimiter(delimiter, spacer: "", ranges: targetRanges) {
let lineRanges = targetRanges.flatMap { self.string.lineContentsRanges(for: $0) }.unique
return partly ? true : (ranges.count == lineRanges.count)
@ -216,19 +218,6 @@ extension Commenting {
return false
}
// MARK: Private Methods
/// return commenting target range
private func commentingRanges(fromLineHead: Bool) -> [NSRange]? {
self.rangesForUserTextChange?
.map(\.rangeValue)
.map { fromLineHead ? self.string.lineContentsRange(for: $0) : $0 }
.unique
}
}

View File

@ -242,7 +242,7 @@ final class TextSelection: NSObject {
/// swap selected lines with the line just below
@objc func handleUncomment(_ command: NSScriptCommand) {
self.textView?.uncomment(fromLineHead: false)
self.textView?.uncomment()
}

View File

@ -150,7 +150,7 @@ final class StringCommentingTests: XCTestCase {
XCTAssertEqual(textView.string, "// foo\n// bar")
XCTAssertEqual(textView.selectedRanges, [NSRange(0..<6), NSRange(7..<13)] as [NSValue])
XCTAssertTrue(textView.canUncomment(partly: false))
textView.uncomment(fromLineHead: true)
textView.uncomment()
XCTAssertEqual(textView.string, "foo\nbar")
XCTAssertEqual(textView.selectedRanges, [NSRange(0..<3), NSRange(4..<7)] as [NSValue])
@ -159,8 +159,8 @@ final class StringCommentingTests: XCTestCase {
textView.commentOut(types: .inline, fromLineHead: true)
XCTAssertEqual(textView.string, "// foo\n// bar")
XCTAssertEqual(textView.rangesForUserTextChange, [NSRange(4..<4), NSRange(11..<11)] as [NSValue])
XCTAssertFalse(textView.canUncomment(partly: false))
textView.uncomment(fromLineHead: true)
XCTAssert(textView.canUncomment(partly: false))
textView.uncomment()
XCTAssertEqual(textView.string, "foo\nbar")
XCTAssertEqual(textView.rangesForUserTextChange, [NSRange(1..<1), NSRange(5..<5)] as [NSValue])
}
@ -176,7 +176,7 @@ final class StringCommentingTests: XCTestCase {
XCTAssertEqual(textView.string, "<- foo ->\n<- bar ->")
XCTAssertEqual(textView.selectedRanges, [NSRange(0..<9), NSRange(10..<19)] as [NSValue])
XCTAssertTrue(textView.canUncomment(partly: false))
textView.uncomment(fromLineHead: true)
textView.uncomment()
XCTAssertEqual(textView.string, "foo\nbar")
XCTAssertEqual(textView.selectedRanges, [NSRange(0..<3), NSRange(4..<7)] as [NSValue])
@ -185,8 +185,8 @@ final class StringCommentingTests: XCTestCase {
textView.commentOut(types: .block, fromLineHead: true)
XCTAssertEqual(textView.string, "<- foo ->\n<- bar ->")
XCTAssertEqual(textView.rangesForUserTextChange, [NSRange(4..<4), NSRange(14..<14)] as [NSValue])
XCTAssertFalse(textView.canUncomment(partly: false))
textView.uncomment(fromLineHead: true)
XCTAssert(textView.canUncomment(partly: false))
textView.uncomment()
XCTAssertEqual(textView.string, "foo\nbar")
XCTAssertEqual(textView.rangesForUserTextChange, [NSRange(1..<1), NSRange(5..<5)] as [NSValue])
}