the notorious
snacky

<- Quay về trang chủ

Nhật ký phát triển GõKey - Tuần 3

Tuần này vừa ăn Tết vừa ăn luôn con covid, không làm được gì nhiều cả 😔

Ngày 21/01/2023

Thay đổi cơ chế lưu input buffer

Cụ thể là, với cách implement cũ, bộ gõ sẽ luôn cập nhật input buffer thành nội dung của từ vừa được engine trả về, ví dụ:

input_buffer  = [d,d,a]   ->   engine_output = "đa"
input_buffer  = [đ,a]

Việc này đi ngược với thiết kế của thuật toán mà engine sử dụng, vốn chỉ hoạt động trên buffer chứa toàn bộ các phím được nhấn chứ không phải với các kí tự tiếng Việt.

Cách implement mới của bộ gõ sẽ chia ra làm 2 nội dung để track: input_buffer chứa toàn bộ các phím trong một từ đang được gõ, và display_buffer chứa nội dung của từ tiếng Việt hoàn chỉnh đang được gõ. Việc tính toán số lượng phím Backspace cần gửi sẽ dùng display_buffer.

input_buffer  = [d,d,a]   ->   engine_output = "đa"
input_buffer  = [d,d,a]   &&   display_buffer = "đa"

Tuy nhiên vẫn còn một lỗi nhỏ với cách implement trên: Khi nhấn phím backspace để xoá một kí tự, nếu đó là kí tự tiếng Việt thì việc xoá sẽ bị sót, và input buffer sẽ bị sai, ví dụ:

input_buffer = [d,d,a,a]  &&  display_buffer = "đâ"

* user nhấn Backspace

input_buffer = [d,d,a]  &&  display_buffer = "đ"

Ngày 22/01/2023

Fix lỗi tracking phím khi hoạt động trên Vim

Một lỗi khó chịu xảy ra trên Vim khi bộ gõ vẫn đang được bật, thì toàn bộ các phím di chuyển trong Normal mode của Vim vẫn được track, khi đó input buffer sẽ chứa nội dung kiểu như:

input_buffer = [k,k,j,j,j,j,j,j,j,j]

Khi bộ gõ truyền buffer này vào cho engine thì việc phản hồi sẽ trở nên rất chậm, gây ra hiện tượng lag khi gõ.

Lỗi này có thể được fix từ phía engine, tuy nhiên bộ gõ vẫn sẽ tiếp tục track và gửi sang engine liên tục, một sự lãng phí không đáng có. Nên mình quyết định fix từ phía bộ gõ.

Nếu phát hiện ra một dãy các phím trùng lặp liền kề (tạm thời cho là 4 kys tự) thì bộ gõ sẽ dừng việc tracking.

pub fn should_stop_tracking(&mut self) -> bool {
    let len = self.buffer.len();
    if len >= MAX_DUPLICATE_LENGTH {
        let buf = &self.buffer[len-MAX_DUPLICATE_LENGTH..];
        let first = buf.chars().nth(0).unwrap();
        return buf.chars().all(|c| c == first);
    }
    return false;
}

Ngày 24/01/2023

vi-rs implement thuật toán kiểm tra chính tả

Hôm nay @zerox-dg vừa update phiên bản mới v0.3.2 cho engine tiếng Việt vi-rs. Implement thuật toán kiểm tra chính tả giúp nhận biết từ đang gõ có phải là tiếng Việt hay không. Và việc này giúp cho bộ gõ trở nên ổn định hơn rất nhiều.

Với cải tiến này thì mình nghĩ ngày release GõKey bản v0.1 chắc không còn xa :D

Fix lỗi khi gõ một từ kèm dấu ngoặc

Một bug khác là khi gõ một từ đi liền kề sau một kí tự đặc biệt, ví dụ như các dấu ngoặc tròn hoặc vuông (, ), [, ],... thì bộ gõ không thêm dấu được, ví dụ:

User gõ:   "(ngayf"
Bộ gõ gửi: "9ngayf"

Nguyên nhân vì bộ gõ đang track luôn cả các kí tự đặc biệt cho từ đang gõ, việc này là không cần thiết.

Trên các bàn phím thông dụng, các kí tự đặc biệt này được tạo ra khi nhấn giữ phím Shift kèm theo một phím số, ngoài ra có các trường hợp phím riêng lẽ có chứa kí tự đặc biệt như -, =, \\, ', /,... Thế nên để kiểm tra thì mình chia làm 2 trường hợp:

  1. User có đang nhấn giữ Shift kèm một phím số không?
  2. Kí tự vừa được nhấn có nằm trong danh sách các kí tự đặc biệt được định nghĩa trước không

Nếu một trong 2 trường hợp trên xảy ra thì ta chỉ việc xoá input buffer:

if "()[]{}<>/\\\\!@#$%^&*-_=+|~`'\\"".contains(c)
   || (c.is_numeric() && modifiers.is_shift())
{
    // If special characters are detected
    // dismiss the current tracking word
    INPUT_STATE.new_word();
} else {
    // Otherwise, process the character
    return process_character(handle, c, modifiers);
}

Ngày 27/01/2023

Sửa lỗi xoá kí tự bằng phím Backspace

Một lỗi xảy ra sau khi bộ gõ chuyển qua chế độ tracking từng phím được nhấn thay vì track theo kí tự tiếng Việt như đã đề cập ở trên, đó là: Khi thực hiện xoá một kí tự trong từ đang được gõ, thì bộ gõ không thể biết chính xác cần xoá bao nhiêu kí tự.

Ví dụ trong trường hợp sau:

Input Buffer: ddaa
Trên màn hình: đâ
User gõ: <backspace>

Expected:
    Input Buffer: dda
    Trên màn hình: đa

Thực tế:
    Input Buffer: dda
    Trên màn hình: đ

Nguyên nhân của lỗi này là, hiện tại, khi phím Backspace được nhấn, bộ gõ sẽ xoá đồng thời kí tự cuối cùng của input buffer, và display buffer (buffer dùng để track từ đang hiển thị trên màn hình). Nếu kí tự đang được xoá là một nguyên âm có dấu, thì ở display buffer, toàn bộ nguyên âm đó bị xoá, còn ở input buffer thì chỉ một phần của nguyên âm bị xoá.

Ban đầu thì mình nghĩ sẽ fix lỗi này theo hướng khá phức tạp: khi xoá một kí tự, chúng ta sẽ convert toàn bộ từ đang được gõ thành từng kí tự nhập, ví dụ: "đấy" sẽ được convert thành "ddaays", xong rồi xoá kí tự "s" đi. Nhưng sau khi discuss thì @unrealhoang mới suggest thêm một behavior chính xác hơn, đó là, khi xoá một nguyên âm có dấu, thì nguyên âm đó nên được chuyển về dạng không dấu, ví dụ: "ấ<backspace>" thì sẽ thành "â", và khi xoá tiếp "â<backspace>" thì sẽ thành "a".

Fix theo hướng này thì khá đơn giản, chỉ cần gọi lại hàm transform của engine tiếng Việt khi nhấn backspace. Nên kết quả là chúng ta có commit này: 2782e3

đấy<backspace>  = đấ
đấ<backspace>   = đâ
đâ<backspace>   = đa
đa<backspace>   = đ
đ<backspace>    = d

Ngày 28/01/2023

Bắt đầu implement thêm icon cho GõKey trên system tray. Trước đây khi làm UI trên Windows, dùng Visual Basic, thì những cái trò này dễ như ăn kẹo, thế mà bây giờ trên macOS, dùng Rút thì nó lại trở thành vấn đề…

Vấn đề đầu tiên là không có nhiều thư viện để làm system tray (hỗ trợ đa hệ điều hành) trên Rust, 2 crates phổ biến nhất là:

Tạm thời mình chọn dùng tray-item, một điểm khá thú vị là có thể sử dụng text thay cho icon được luôn:

Tuy nhiên phát sinh một vấn đề đó là tray-item phải được khởi động ở main thread của ứng dụng. Hiện tại main thread đang được dùng để handle phần UI chính (dùng Druid), khổ một cái là UI chính cũng bắt buộc phải chạy từ main thread 😂 Bản thân Druid (là UI framework mình đang xài) thì hoàn toàn không có dự định support system tray.

Cho nên chức năng system tray tạm thời đang bị block, có thể mình sẽ chuyển qua sử dụng một thư viện khác, hoặc tìm cách viết custom binding, hoặc là tìm cách fork Druid ra để add thêm chức năng hỗ trợ system tray =))) thôi thì tính sau.


Các bạn có thể tham khảo mã nguồn của GõKey tại link sau https://github.com/huytd/goxkey

Hiện tại GõKey vẫn đang trong quá trình phát triển nên mình chưa cung cấp bản build chính thức, tuy nhiên các bạn có thể tự compile và dùng thử. Hoặc nếu phát hiện lỗi, các bạn có thể tham gia contribute cho bộ gõ nhé :D

Tags: rustgokey