-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Toggle comment for current line via CMD + / (#241)
This change implements the functionality of <kbd>⌘</kbd> <kbd>/</kbd> for single line comments. It allows you to toggle between commented and uncommented for the line the cursor is currently on when you press <kbd>⌘</kbd> <kbd>/</kbd>. To do so, I implemented a `keyDown` event recognizer, which listens for when the relevant keys are pressed. If <kbd>⌘</kbd> <kbd>/</kbd> is pressed, it calls a method called `commandSlashCalled()`, which decides which toggle is supposed to happen depending on if the line is already commented or not. It also addresses the situation of special cases of languages like HTML, which need a comment at the beginning and end of the line (essentially a `rangeComment`) to comment a single line. ### Related Issues - #38 This PR accomplishes part of #38. I talked with some of the project leads (@FastestMolasses) and they said it makes sense to break #38 into a couple different issues (I.e. single-line vs highlighted chunks, etc). Single-line comment toggling is completed as of this PR but commenting highlighted code still needs to be completed. ### Checklist - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots <img width="626" alt="Screenshot 2024-04-19 at 5 44 24 PM" src="https://github.com/CodeEditApp/CodeEditSourceEditor/assets/143217945/1200a5c1-d8ea-48a4-9704-70db7aa23fc7"> --------- Co-authored-by: Abe <[email protected]>
- Loading branch information
1 parent
0c741c2
commit dae56c8
Showing
3 changed files
with
105 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
Sources/CodeEditSourceEditor/Controller/TextViewController+Shortcuts.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// | ||
// TextViewController+Shortcuts.swift | ||
// CodeEditSourceEditor | ||
// | ||
// Created by Sophia Hooley on 4/21/24. | ||
// | ||
|
||
import CodeEditTextView | ||
import AppKit | ||
|
||
extension TextViewController { | ||
/// Method called when CMD + / key sequence recognized, comments cursor's current line of code | ||
public func commandSlashCalled() { | ||
guard let cursorPosition = cursorPositions.first else { | ||
print("There is no cursor \(#function)") | ||
return | ||
} | ||
// Many languages require a character sequence at the beginning of the line to comment the line. | ||
// (ex. python #, C++ //) | ||
// If such a sequence exists, we will insert that sequence at the beginning of the line | ||
if !language.lineCommentString.isEmpty { | ||
toggleCharsAtBeginningOfLine(chars: language.lineCommentString, lineNumber: cursorPosition.line) | ||
} | ||
// In other cases, languages require a character sequence at beginning and end of a line, aka a range comment | ||
// (Ex. HTML <!--line here -->) | ||
// We treat the line as a one-line range to comment it out using rangeCommentStrings on both sides of the line | ||
else { | ||
let (openComment, closeComment) = language.rangeCommentStrings | ||
toggleCharsAtEndOfLine(chars: closeComment, lineNumber: cursorPosition.line) | ||
toggleCharsAtBeginningOfLine(chars: openComment, lineNumber: cursorPosition.line) | ||
} | ||
} | ||
|
||
/// Toggles comment string at the beginning of a specified line (lineNumber is 1-indexed) | ||
private func toggleCharsAtBeginningOfLine(chars: String, lineNumber: Int) { | ||
guard let lineInfo = textView.layoutManager.textLineForIndex(lineNumber - 1) else { | ||
print("There are no characters/lineInfo \(#function)") | ||
return | ||
} | ||
guard let lineString = textView.textStorage.substring(from: lineInfo.range) else { | ||
print("There are no characters/lineString \(#function)") | ||
return | ||
} | ||
let firstNonWhiteSpaceCharIndex = lineString.firstIndex(where: {!$0.isWhitespace}) ?? lineString.startIndex | ||
let numWhitespaceChars = lineString.distance(from: lineString.startIndex, to: firstNonWhiteSpaceCharIndex) | ||
let firstCharsInLine = lineString.suffix(from: firstNonWhiteSpaceCharIndex).prefix(chars.count) | ||
// toggle comment off | ||
if firstCharsInLine == chars { | ||
textView.replaceCharacters(in: NSRange( | ||
location: lineInfo.range.location + numWhitespaceChars, | ||
length: chars.count | ||
), with: "") | ||
} | ||
// toggle comment on | ||
else { | ||
textView.replaceCharacters(in: NSRange( | ||
location: lineInfo.range.location + numWhitespaceChars, | ||
length: 0 | ||
), with: chars) | ||
} | ||
} | ||
|
||
/// Toggles a specific string of characters at the end of a specified line. (lineNumber is 1-indexed) | ||
private func toggleCharsAtEndOfLine(chars: String, lineNumber: Int) { | ||
guard let lineInfo = textView.layoutManager.textLineForIndex(lineNumber - 1) else { | ||
print("There are no characters/lineInfo \(#function)") | ||
return | ||
} | ||
guard let lineString = textView.textStorage.substring(from: lineInfo.range) else { | ||
print("There are no characters/lineString \(#function)") | ||
return | ||
} | ||
let lineLastCharIndex = lineInfo.range.location + lineInfo.range.length - 1 | ||
let closeCommentLength = chars.count | ||
let closeCommentRange = NSRange( | ||
location: lineLastCharIndex - closeCommentLength, | ||
length: closeCommentLength | ||
) | ||
let lastCharsInLine = textView.textStorage.substring(from: closeCommentRange) | ||
// toggle comment off | ||
if lastCharsInLine == chars { | ||
textView.replaceCharacters(in: NSRange( | ||
location: lineLastCharIndex - closeCommentLength, | ||
length: closeCommentLength | ||
), with: "") | ||
} | ||
// toggle comment on | ||
else { | ||
textView.replaceCharacters(in: NSRange(location: lineLastCharIndex, length: 0), with: chars) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters