From b754f39d890d63f263ffd449a037cfd36a7ca173 Mon Sep 17 00:00:00 2001 From: Beingpax Date: Thu, 4 Dec 2025 19:06:20 +0545 Subject: [PATCH] Remove text formatting during Paste operation --- VoiceInk/CursorPaster.swift | 5 +- .../Services/TextInsertionFormatter.swift | 175 ------------------ VoiceInk/Whisper/WhisperState.swift | 2 +- 3 files changed, 2 insertions(+), 180 deletions(-) delete mode 100644 VoiceInk/Services/TextInsertionFormatter.swift diff --git a/VoiceInk/CursorPaster.swift b/VoiceInk/CursorPaster.swift index e0cd5c8..a222bc7 100644 --- a/VoiceInk/CursorPaster.swift +++ b/VoiceInk/CursorPaster.swift @@ -7,9 +7,6 @@ class CursorPaster { let pasteboard = NSPasteboard.general let preserveTranscript = UserDefaults.standard.bool(forKey: "preserveTranscriptInClipboard") - let context = TextInsertionFormatter.getInsertionContext() - let textToInsert = TextInsertionFormatter.formatTextForInsertion(text, context: context) - var savedContents: [(NSPasteboard.PasteboardType, Data)] = [] // Only save clipboard contents if we plan to restore them @@ -25,7 +22,7 @@ class CursorPaster { } } - ClipboardManager.setClipboard(textToInsert, transient: !preserveTranscript) + ClipboardManager.setClipboard(text, transient: !preserveTranscript) DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { if UserDefaults.standard.bool(forKey: "UseAppleScriptPaste") { diff --git a/VoiceInk/Services/TextInsertionFormatter.swift b/VoiceInk/Services/TextInsertionFormatter.swift deleted file mode 100644 index 9ab1389..0000000 --- a/VoiceInk/Services/TextInsertionFormatter.swift +++ /dev/null @@ -1,175 +0,0 @@ -import Foundation -import AppKit - -class TextInsertionFormatter { - - struct InsertionContext { - let textBefore: String - let textAfter: String - let charBeforeCursor: Character? - let charAfterCursor: Character? - } - - static func getInsertionContext() -> InsertionContext? { - guard AXIsProcessTrusted() else { - return nil - } - - guard let focusedElement = getFocusedElement() else { - return nil - } - - var selectedRange: CFTypeRef? - let rangeResult = AXUIElementCopyAttributeValue(focusedElement, kAXSelectedTextRangeAttribute as CFString, &selectedRange) - - var textValue: CFTypeRef? - let textResult = AXUIElementCopyAttributeValue(focusedElement, kAXValueAttribute as CFString, &textValue) - - guard rangeResult == .success, - textResult == .success, - let range = selectedRange, - let text = textValue as? String else { - return nil - } - - var rangeValue = CFRange() - guard AXValueGetValue(range as! AXValue, .cfRange, &rangeValue) else { - return nil - } - - let cursorPosition = rangeValue.location - - guard let cursorUTF16Index = text.utf16.index(text.utf16.startIndex, offsetBy: cursorPosition, limitedBy: text.utf16.endIndex), - let cursorStringIndex = cursorUTF16Index.samePosition(in: text) else { - return nil - } - - let searchRangeLength = 100 - - let beforeStartIndex = text.index(cursorStringIndex, offsetBy: -searchRangeLength, limitedBy: text.startIndex) ?? text.startIndex - let textBefore = String(text[beforeStartIndex.. text.startIndex ? text[text.index(before: cursorStringIndex)] : nil - let charAfter = cursorStringIndex < text.endIndex ? text[cursorStringIndex] : nil - - return InsertionContext( - textBefore: textBefore, - textAfter: textAfter, - charBeforeCursor: charBefore, - charAfterCursor: charAfter - ) - } - - private static func getFocusedElement() -> AXUIElement? { - let systemWideElement = AXUIElementCreateSystemWide() - var focusedApp: CFTypeRef? - - guard AXUIElementCopyAttributeValue(systemWideElement, kAXFocusedApplicationAttribute as CFString, &focusedApp) == .success else { - return nil - } - - var focusedElement: CFTypeRef? - guard AXUIElementCopyAttributeValue(focusedApp as! AXUIElement, kAXFocusedUIElementAttribute as CFString, &focusedElement) == .success else { - return nil - } - - return (focusedElement as! AXUIElement) - } - - static func formatTextForInsertion(_ text: String, context: InsertionContext?) -> String { - guard let context = context else { - return text + " " - } - - var formattedText = text - formattedText = applySmartCapitalization(formattedText, context: context) - formattedText = applySmartSpacing(formattedText, context: context) - - return formattedText - } - - private static func applySmartSpacing(_ text: String, context: InsertionContext) -> String { - var result = text - - if shouldAddSpaceBefore(context: context) { - result = " " + result - } - - if let charAfter = context.charAfterCursor { - if !charAfter.isWhitespace && !charAfter.isPunctuation && !(result.last?.isWhitespace ?? false) { - result = result + " " - } - } else { - result = result + " " - } - - return result - } - - private static func shouldAddSpaceBefore(context: InsertionContext) -> Bool { - guard let charBefore = context.charBeforeCursor else { - return false - } - - if charBefore.isWhitespace { - return false - } - - if charBefore == "." || charBefore == "!" || charBefore == "?" { - return true - } - - if charBefore == "," || charBefore == ";" || charBefore == ":" || charBefore == "-" { - return true - } - - if charBefore.isLetter || charBefore.isNumber { - return true - } - - return false - } - - private static func applySmartCapitalization(_ text: String, context: InsertionContext) -> String { - guard !text.isEmpty else { return text } - - let shouldCapitalize = shouldCapitalizeFirstLetter(context: context) - - if shouldCapitalize { - return text.prefix(1).uppercased() + text.dropFirst() - } else { - let firstWord = text.prefix(while: { !$0.isWhitespace && !$0.isPunctuation }) - let isAcronymOrProper = firstWord.allSatisfy { $0.isUppercase || !$0.isLetter } - - if !isAcronymOrProper { - return text.prefix(1).lowercased() + text.dropFirst() - } - } - - return text - } - - private static func shouldCapitalizeFirstLetter(context: InsertionContext) -> Bool { - if context.textBefore.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - return true - } - - let trimmedBefore = context.textBefore.trimmingCharacters(in: .whitespaces) - - if trimmedBefore.isEmpty { - return true - } - - if let lastChar = trimmedBefore.last { - if lastChar == "." || lastChar == "!" || lastChar == "?" || lastChar == "\n" { - return true - } - } - - return false - } -} - diff --git a/VoiceInk/Whisper/WhisperState.swift b/VoiceInk/Whisper/WhisperState.swift index d8c364c..76b0f48 100644 --- a/VoiceInk/Whisper/WhisperState.swift +++ b/VoiceInk/Whisper/WhisperState.swift @@ -399,7 +399,7 @@ class WhisperState: NSObject, ObservableObject { } DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { - CursorPaster.pasteAtCursor(textToPaste) + CursorPaster.pasteAtCursor(textToPaste + " ") let powerMode = PowerModeManager.shared if let activeConfig = powerMode.currentActiveConfiguration, activeConfig.isAutoSendEnabled {