krz/keycask

Password manager: Swift core library, CLI for macOS/Linux/Windows, iOS/macOS app. cli password-manager swift

Commit bd8d5569eb

bd8d5569ebc36c1598199eca5d20f8f157ccffd4

parent: ba62721654

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-18 01:23 UTC

Strip trailing newline from clipboard reads

Layout: unified · split

Sources/keycask/Clipboard.swift +10 −1
@@ -59,11 +59,20 @@ enum Clipboard {
5959 return nil
6060 }
6161
62 /// Removes exactly one trailing line break, which some paste tools add.
63 static func stripTrailingNewline(_ s: String) -> String {
64 var scalars = s.unicodeScalars
65 guard scalars.last == "\n" else { return s }
66 scalars.removeLast()
67 if scalars.last == "\r" { scalars.removeLast() }
68 return String(scalars)
69 }
70
6271 static func read() throws -> String {
6372 let tool = try requireTool()
6473 let (status, output) = try runTool(tool.paste, input: nil)
6574 guard status == 0 else { return "" }
66 return output
75 return stripTrailingNewline(output)
6776 }
6877
6978 static func write(_ text: String) throws {
Tests/KeycaskCLITests/ClipboardTests.swift +7
@@ -16,6 +16,13 @@ import Testing
1616 #expect(try JSONDecoder().decode(Clipboard.Handoff.self, from: data) == h)
1717 }
1818
19 @Test func stripsOneTrailingNewline() {
20 #expect(Clipboard.stripTrailingNewline("s\r\n") == "s")
21 #expect(Clipboard.stripTrailingNewline("s\n") == "s")
22 #expect(Clipboard.stripTrailingNewline("s") == "s")
23 #expect(Clipboard.stripTrailingNewline("s\n\n") == "s\n")
24 }
25
1926 @Test func findToolScansPathInOrder() throws {
2027 let dir = FileManager.default.temporaryDirectory
2128 .appendingPathComponent("keycask-clip-\(UUID().uuidString)")