Added support for comma-separated words for word replacement.
This commit is contained in:
parent
8334f75360
commit
f1fb2168c2
@ -15,12 +15,10 @@ class WordReplacementService {
|
||||
|
||||
// Apply replacements (case-insensitive)
|
||||
for (original, replacement) in replacements {
|
||||
let isPhrase = original.contains(" ") || original.trimmingCharacters(in: .whitespacesAndNewlines) != original
|
||||
let usesBoundaries = usesWordBoundaries(for: original)
|
||||
|
||||
if isPhrase || !usesWordBoundaries(for: original) {
|
||||
modifiedText = modifiedText.replacingOccurrences(of: original, with: replacement, options: .caseInsensitive)
|
||||
} else {
|
||||
// Use word boundaries for spaced languages
|
||||
if usesBoundaries {
|
||||
// Word-boundary regex for full original string
|
||||
let pattern = "\\b\(NSRegularExpression.escapedPattern(for: original))\\b"
|
||||
if let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) {
|
||||
let range = NSRange(modifiedText.startIndex..., in: modifiedText)
|
||||
@ -31,6 +29,9 @@ class WordReplacementService {
|
||||
withTemplate: replacement
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Fallback substring replace for non-spaced scripts
|
||||
modifiedText = modifiedText.replacingOccurrences(of: original, with: replacement, options: .caseInsensitive)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
import SwiftUI
|
||||
|
||||
/// A reusable sheet for editing an existing word replacement entry.
|
||||
/// Mirrors the UI of `AddReplacementSheet` for consistency while pre-populating
|
||||
/// the fields with the existing values.
|
||||
// Edit existing word replacement entry
|
||||
struct EditReplacementSheet: View {
|
||||
@ObservedObject var manager: WordReplacementManager
|
||||
let originalKey: String
|
||||
@ -84,8 +81,9 @@ struct EditReplacementSheet: View {
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
TextField("Enter word or phrase to replace", text: $originalWord)
|
||||
TextField("Enter word or phrase to replace (use commas for multiple)", text: $originalWord)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
}
|
||||
.padding(.horizontal)
|
||||
|
||||
@ -117,7 +115,12 @@ struct EditReplacementSheet: View {
|
||||
private func saveChanges() {
|
||||
let newOriginal = originalWord.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let newReplacement = replacementWord.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !newOriginal.isEmpty, !newReplacement.isEmpty else { return }
|
||||
// Ensure at least one non-empty token
|
||||
let tokens = newOriginal
|
||||
.split(separator: ",")
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
guard !tokens.isEmpty, !newReplacement.isEmpty else { return }
|
||||
|
||||
manager.updateReplacement(oldOriginal: originalKey, newOriginal: newOriginal, newReplacement: newReplacement)
|
||||
dismiss()
|
||||
|
||||
@ -23,7 +23,15 @@ class WordReplacementManager: ObservableObject {
|
||||
}
|
||||
|
||||
func addReplacement(original: String, replacement: String) {
|
||||
replacements[original] = replacement
|
||||
// Support comma-separated originals mapping to the same replacement
|
||||
let tokens = original
|
||||
.split(separator: ",")
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
guard !tokens.isEmpty else { return }
|
||||
for token in tokens {
|
||||
replacements[token] = replacement
|
||||
}
|
||||
}
|
||||
|
||||
func removeReplacement(original: String) {
|
||||
@ -31,12 +39,18 @@ class WordReplacementManager: ObservableObject {
|
||||
}
|
||||
|
||||
func updateReplacement(oldOriginal: String, newOriginal: String, newReplacement: String) {
|
||||
// Remove the old key if the original text has changed
|
||||
if oldOriginal != newOriginal {
|
||||
replacements.removeValue(forKey: oldOriginal)
|
||||
// Always remove the old key being edited
|
||||
replacements.removeValue(forKey: oldOriginal)
|
||||
|
||||
// Add one or more new keys (comma-separated) pointing to the same replacement
|
||||
let tokens = newOriginal
|
||||
.split(separator: ",")
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
guard !tokens.isEmpty else { return }
|
||||
for token in tokens {
|
||||
replacements[token] = newReplacement
|
||||
}
|
||||
// Update (or insert) the new key/value pair
|
||||
replacements[newOriginal] = newReplacement
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +156,7 @@ struct EmptyStateView: View {
|
||||
Text("No Replacements")
|
||||
.font(.headline)
|
||||
|
||||
Text("Add word replacements to automatically replace text during AI enhancement.")
|
||||
Text("Add word replacements to automatically replace text.")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
@ -221,9 +235,12 @@ struct AddReplacementSheet: View {
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
TextField("Enter word or phrase to replace", text: $originalWord)
|
||||
TextField("Enter word or phrase to replace (use commas for multiple)", text: $originalWord)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.font(.body)
|
||||
Text("Separate multiple originals with commas, e.g. Voicing, Voice ink, Voiceing")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
|
||||
@ -297,7 +314,12 @@ struct AddReplacementSheet: View {
|
||||
let original = originalWord
|
||||
let replacement = replacementWord
|
||||
|
||||
guard !original.isEmpty && !replacement.isEmpty else { return }
|
||||
// Validate that at least one non-empty token exists
|
||||
let tokens = original
|
||||
.split(separator: ",")
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
guard !tokens.isEmpty && !replacement.isEmpty else { return }
|
||||
|
||||
manager.addReplacement(original: original, replacement: replacement)
|
||||
dismiss()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user