Đọc chính tả sống sót được trong terminal

Dán lời đọc âm thầm thất bại trong terminal, SSH, tmux và bố cục khác QWERTY. Vì sao clipboard hỏng ở đó, và chế độ gõ mô phỏng làm gì thay thế?

Teodor Deleanu10 tháng 7, 20269 phút đọc

Các lập trình viên thử công cụ đọc chính tả thường gặp một kiểu hỏng có hình dạng rất đặc trưng. Công cụ chạy đẹp trong bản demo. Nó chạy trong Notes, trong Slack, trong trình duyệt. Rồi bạn focus vào một terminal, đọc một câu, và hoặc là chẳng có gì hiện ra, hoặc hiện ra thứ không phải điều bạn nói, hoặc một nửa hiện ra còn nửa kia thì bí ẩn nằm trong clipboard. Đôi khi nó chạy được ở máy cục bộ rồi chết ngay khoảnh khắc bạn SSH vào một máy khác.

Kiểu hỏng này lặp lại đủ nhất quán để tôi không nghĩ đó là lỗi của riêng sản phẩm nào. Nó là hệ quả của cách cả nhóm sản phẩm này chèn văn bản — và nó hỏng đúng ở những nơi mà một lập trình viên sống.

Chuyện đó giờ quan trọng hơn hai năm trước. Nếu bạn điều khiển Claude Code bằng giọng nói — quy trình tôi mô tả trong bài điều khiển Claude Code bằng giọng nói — thì terminal không phải một app trong số nhiều app. Nó là app. Đó là nơi prompt của bạn rơi xuống, nơi các agent chờ lệnh đổi hướng, nơi cả cái chuyện nhiều lane song song hoặc là chạy được hoặc là không. Với một vibecoder, một công cụ đọc chính tả chập chờn trong terminal là chập chờn ở đúng công việc duy nhất của nó.

Vì sao việc dán lại hỏng đúng nơi lập trình viên sống?

Đây là cơ chế ở tầm cả nhóm sản phẩm. Phần lớn công cụ đọc chính tả chèn văn bản theo cùng một cách: chúng đặt câu đã chuyển văn bản của bạn lên clipboard hệ thống, rồi mô phỏng một cú nhấn Cmd+V vào app đang focus. Đó là một mặc định hợp lý — dán thì tức thì, chạy được trong gần như mọi ô văn bản GUI, và gần như không cần công sức lập trình riêng cho từng app.

Vấn đề nằm ở mọi thứ mà giả định đó âm thầm dựa vào.

Nó dựa vào việc app đang focus hiểu Cmd+V là “dán”. Terminal thì thường không — nhiều cái dùng Cmd+V cho việc khác hoặc chẳng cho việc gì, tmux và vim có ý riêng của chúng về nghĩa của việc dán, và một phiên SSH từ xa có thể diễn giải một tràng văn bản được dán theo cách máy cục bộ không đoán trước được. Bracketed paste, copy-mode, insert-mode so với normal-mode: thế giới terminal đầy những trạng thái mà một cú dán mô phỏng rơi sai chỗ hoặc chẳng rơi vào đâu.

Nó dựa vào việc clipboard sẵn có và không bị canh giữ. Các trình quản lý clipboard ghi đè lên nó. Trình quản lý mật khẩu cố tình xóa hoặc bảo vệ nó — một tính năng bảo mật biến “dán bản đọc của tôi” thành “chẳng dán gì cả”, một cách âm thầm. Và ngay cả khi mọi thứ chạy đúng, công cụ vừa ghi đè lên thứ bạn đã copy. Cái commit SHA bạn đang mang qua lại giữa các cửa sổ đã mất, bị thay bằng câu nói của chính bạn. Với người đang tung hứng nhiều lane, đó không phải một vết xước; clipboard lúc đó đang làm một việc thật.

Và nó còn dựa vào — đây là điểm làm người ta bất ngờ — bố cục bàn phím của bạn. Khi một công cụ lùi về phương án mô phỏng phím nhấn, cách ngây thơ là gửi phím: vị trí phím vật lý. Mã phím ánh xạ sang ký tự thông qua bố cục của bạn. Trên QWERTY, mã của “V” cho ra chữ V. Trên Dvorak, đúng vị trí vật lý đó lại là chữ khác. Vậy nên một công cụ mô phỏng scancode trên bố cục Dvorak, AZERTY hay Colemak sẽ cho ra văn bản trông như đã đi qua một phép mã hóa thay thế. Người dùng báo là ra chữ vô nghĩa rồi cho rằng phần nhận dạng giọng nói đã hỏng. Không hề — phần nhận dạng hoàn hảo, chính khâu chèn văn bản mới làm nó rối tung.

Chẳng có gì trong số này là ác ý hay lười biếng của ai cả. Dán qua clipboard là mặc định đúng cho 90% trường hợp. Chỉ là lập trình viên dành cả ngày ở trong 10% còn lại.

“Gõ ra thay vì dán” thật sự nghĩa là gì

Keebye có một cài đặt tên là insert_mode với hai giá trị: paste, là mặc định, và type.

Chế độ gõ mô phỏng không dán. Trên macOS nó dùng CGEventKeyboardSetUnicodeString — một API gắn thẳng văn bản Unicode thật vào một sự kiện phím mô phỏng. Ký tự được mang theo trong chính sự kiện đó, chứ không phải tra ngược qua bố cục bàn phím của bạn. Điều đó khiến nó độc lập với bố cục ngay từ trong cấu tạo: Dvorak, AZERTY, Colemak, bạn gõ trên gì cũng được, văn bản đến nơi đúng là văn bản đã chuyển ra, vì chưa từng có phép dịch từ scancode sang ký tự nào để mà sai.

Tính chất thứ hai của chế độ gõ mô phỏng mới là thứ người dùng terminal quan tâm: nó không bao giờ đụng tới clipboard. Không một thao tác clipboard nào trên đường code đó. Nội dung clipboard của bạn vẫn là của bạn — cái SHA sống sót, trình quản lý mật khẩu chẳng có gì phải canh, trình quản lý clipboard chẳng có gì để ghi lại.

Và vì terminal cùng các phiên từ xa có thể nghẹn khi văn bản đến nhanh hơn tốc độ gõ của bất kỳ con người nào, chế độ gõ mô phỏng cố tình tự điều tiết nhịp: văn bản đi vào theo từng khối 16 ký tự với khoảng nghỉ 4 mili-giây giữa các khối. Đủ nhanh để một câu rơi xuống trong chưa đầy một giây; đủ chừng mực để một pane tmux qua SSH nhận được nó như những cú nhấn phím mà nó theo kịp, chứ không phải một khối dữ liệu phải ngồi diễn giải.

Chế độ dán vẫn còn đó, và vẫn là mặc định, vì nó thật sự nhanh hơn với những khối văn bản lớn trong các app GUI thông thường — một tin nhắn Slack ba đoạn đến nơi bằng một cú dán chứ không phải một dòng khối nối tiếp nhau. Dù vậy, ngay cả chế độ dán cũng học được bài học về bố cục: cú Cmd+V mô phỏng dùng mã phím V vật lý, nên bản thân việc dán không hỏng trên các bố cục không phải QWERTY theo kiểu mà những cách tra cứu ký tự có thể hỏng.

Thiết lập thực tế cho công việc với agent rất đơn giản: chuyển insert_mode sang type, focus vào terminal đang chạy Claude Code, giữ phím, nói lệnh đổi hướng, thả ra. Prompt đến nơi đúng như cách những cú nhấn phím sẽ đến, vì với terminal thì đó chính là những cú nhấn phím. Có một bản hướng dẫn từng bước cho thiết lập này, gồm cả phần chi tiết cho SSH và tmux, trong bài gõ bằng giọng nói trong terminal trên macOS.

Những giới hạn trung thực

Chế độ gõ mô phỏng chậm hơn dán với văn bản dài — đó là số học, không phải khiếm khuyết. Những cú nhấn phím chia khối kèm khoảng nghỉ mất nhiều thời gian hơn một sự kiện dán duy nhất, và nếu bạn đang đọc vài đoạn văn vào một tài liệu, chế độ dán sẽ cho cảm giác nhanh nhẹn hơn. Đây chính xác là lý do dán vẫn là mặc định còn chế độ gõ mô phỏng là thứ bạn tự bật trong phần cài đặt; chế độ đúng phụ thuộc vào nơi văn bản của bạn sẽ tới.

Một số ứng dụng giới hạn tốc độ hoặc lọc đầu vào mô phỏng, thường vì lý do bảo mật, và không chiến lược chèn văn bản nào thoát hoàn toàn khỏi điều đó — một app từ chối sự kiện mô phỏng thì từ chối chúng từ mọi công cụ đọc chính tả.

Và nói rõ bài viết này đang khẳng định gì và không khẳng định gì: chuyện dán-hỏng-trong-terminal là một kiểu lỗi chung của cả nhóm sản phẩm đọc chính tả, không phải khiếm khuyết riêng của đối thủ nào. Các công cụ khác có câu trả lời riêng và điểm mạnh riêng — chúng tôi đã viết những bài so sánh trung thực tại Keebye vs SuperwhisperKeebye vs Wispr Flow, gồm cả những chỗ mà mỗi bên có thể hợp với bạn hơn.

Chèn văn bản là nửa kém hào nhoáng của việc đọc chính tả

Nhận dạng giọng nói được chú ý hết — tên model, tuyên bố về độ chính xác, số ngôn ngữ. Nhưng một công cụ đọc chính tả có hai việc: nghe bạn cho đúng, rồi đưa văn bản tới đúng chỗ con trỏ của bạn mà không làm mất hay làm méo nó. Việc thứ hai nghe có vẻ tầm thường và lại chính là chỗ cả nhóm sản phẩm âm thầm phụ lòng lập trình viên, vì việc thứ hai thì dễ trong TextEdit và khó trong một pane tmux trên máy từ xa dưới bố cục Dvorak.

Nếu prompt của bạn rơi vào terminal — và nếu bạn đang điều khiển các agent lập trình thì chắc chắn là vậy — thì việc chèn văn bản không phải một dòng chú thích. Nó là khác biệt giữa một công cụ để đem đi demo và một công cụ để dùng. Nhân tiện, những kiểu hỏng liên quan cũng cùng một mùi vị: từ đầu tiên của một lượt đọc bị nuốt mất vì micro khởi động nguội là một lời than chung khác của cả ngành và cũng có lời giải thích cơ học, chúng tôi đã viết về nó trong bài vì sao các app đọc chính tả nuốt mất từ đầu tiên của bạn.

Keebye đang trong giai đoạn truy cập sớm cho macOS. Nếu bản đọc chính tả của bạn từng biến mất đâu đó giữa miệng bạn và một terminal, hãy bắt đầu bản dùng thử miễn phí bên dưới, bật chế độ gõ mô phỏng, và thử lại đúng prompt đó. Cái SHA bạn đã copy vẫn nằm trên clipboard trong lúc câu chữ đến nơi dưới dạng Unicode được gõ ra.

Thử đúng đường terminal khó nhất của bạn

Bắt đầu bản dùng thử miễn phí, bật chế độ gõ mô phỏng, và thử lại cái prompt SSH hay tmux vẫn hay làm hỏng thao tác dán.

Start free trial

Early access: we'll email you the moment the macOS build is ready — your 14 days start when you first sign in from the app.

Đọc tiếp