Generic keyboard IME bump: supports auto seperation when code is unique

reviewable/pr9631/r1
weijiuqiao 2 years ago committed by poire-z
parent e424fcf5de
commit 6a5a13dfc8

@ -1,6 +1,6 @@
-----------------------------------------
-- General Chinese input method engine --
-----------------------------------------
---------------------------------
-- Generic input method engine --
---------------------------------
local logger = require("logger")
local util = require("util")
@ -54,9 +54,10 @@ local IME = {
iter_map = nil, -- next code when using wildcard
iter_map_last_key = nil,
show_candi_callback = function() end,
switch_char = "下一字", -- default
separator = "分隔", -- default
use_space_as_separator = true,
switch_char = "SWITCH",
separator = "SEPARATOR",
partial_separators = { " " }, -- when in state act as separator, otherwise input itself
auto_separate_callback = function() return false end,
local_del = "", -- default
W = nil -- default no wildcard
}
@ -102,6 +103,7 @@ function IME:clear_stack()
self.last_key = ""
self.last_index = 0
self.hint_char_count = 0
self.on_stage_char_count = 0
end
function IME:reset_status()
@ -109,6 +111,31 @@ function IME:reset_status()
self.last_index = 0
end
function IME:uniqueMap(code)
-- Here we find out if given code has only one candidate and no other code
-- starts with the given one, so that auto separation can take place.
if not code then return true end
if self.W and code:find(self.W) then
return false -- with wildcard, we just return false even if its unique
else
if type(self.code_map[code]) == "table" then
return false
end
local idx = binarysearch(self.sorted_codes, code, function(v) return v end)
if idx == #self.sorted_codes then
return true
elseif not idx then
idx = binarysearch(self.sorted_codes, code, function(v) return string.sub(v or "", 1, #code) end )
if not idx or idx == #self.sorted_codes then
return true
end
end
local next_code = self.sorted_codes[idx+1]
local unique = next_code:sub(1, #code) ~= code
return unique
end
end
function IME:searchStartWith(code)
local result = binarysearch(self.sorted_codes, code, function(v) return string.sub(v or "", 1, #code) end)
if result then
@ -197,13 +224,21 @@ function IME:delHintChars(inputbox)
end
end
function IME:delOnStageAndHintChars(inputbox)
self:delHintChars(inputbox)
for i=1, self.on_stage_char_count do
inputbox.delChar:raw_method_call()
end
end
function IME:getHintChars()
self.hint_char_count = 0
self.on_stage_char_count = 0
local hint_chars = ""
for i=1, #_stack do
hint_chars = hint_chars .. _stack[i].char
if _stack[i].char ~= "" then
self.hint_char_count = self.hint_char_count + #util.splitToChars(_stack[i].char)
self.on_stage_char_count = self.on_stage_char_count + #util.splitToChars(_stack[i].char)
end
end
local imex = _stack[#_stack]
@ -244,21 +279,17 @@ function IME:getHintChars()
end
function IME:refreshHintChars(inpuxbox)
self:delHintChars(inpuxbox)
self:delOnStageAndHintChars(inpuxbox)
inpuxbox.addChars:raw_method_call(self:getHintChars())
end
function IME:wrappedSeparate(inputbox)
local imex = _stack[#_stack]
if self:show_candi_callback() and ( #imex.candi > 1 or self.W and imex.code:find(self.W) ) then
imex.candi = {}
self:refreshHintChars(inputbox)
function IME:separate(inputbox)
if self.hint_char_count then
self:delHintChars(inputbox)
end
self:clear_stack()
end
function IME:wrappedDelChar(inputbox)
local imex = _stack[#_stack]
-- stepped deletion
@ -275,7 +306,7 @@ function IME:wrappedDelChar(inputbox)
self:refreshHintChars(inputbox)
elseif #imex.code == 1 then
-- one char with one stroke
self:delHintChars(inputbox)
self:delOnStageAndHintChars(inputbox)
self:clear_stack()
else
inputbox.delChar:raw_method_call()
@ -304,11 +335,9 @@ function IME:wrappedAddChars(inputbox, char)
end
self:refreshHintChars(inputbox)
elseif char == self.separator or
self.use_space_as_separator and char == " " and _stack[1].code ~= "" then
imex.candi = {}
self:refreshHintChars(inputbox)
self:clear_stack()
return
_stack[1].code ~= "" and self.partial_separators and util.arrayContains(self.partial_separators, char) then
self:separate(inputbox)
return
elseif char == self.local_del then
if #imex.code > 0 then
imex.candi = {}
@ -335,17 +364,23 @@ function IME:wrappedAddChars(inputbox, char)
imex.char = new_candi[1]
imex.candi = new_candi
self:refreshHintChars(inputbox)
if self.auto_separate_callback() and self:uniqueMap(imex.code) then
self:separate(inputbox)
end
else
if self.auto_separate_callback() then -- flush current stack
self:separate(inputbox)
end
new_candi,imex.last_candi = self:getCandidates(key) or {},nil -- single stroke
table.insert(_stack, {code=key, index=1, char=new_candi[1], candi=new_candi})
if self.auto_separate_callback() then
_stack[1] = { code=key, index=1, char=new_candi[1] or "", candi=new_candi }
else
table.insert(_stack, {code=key, index=1, char=new_candi[1] or "", candi=new_candi} )
end
self:refreshHintChars(inputbox)
end
else
if #imex.candi > 1 then
imex.candi = {}
self:refreshHintChars(inputbox)
end
self:clear_stack()
self:separate(inputbox)
inputbox.addChars:raw_method_call(char)
end
end

@ -15,7 +15,7 @@ rf. https://en.wikipedia.org/wiki/Stroke_count_method
--]]
local IME = require("frontend/ui/data/keyboardlayouts/zh_ime")
local IME = require("frontend/ui/data/keyboardlayouts/generic_ime")
local util = require("util")
local JA = require("ui/data/keyboardlayouts/ja_keyboard_keys")
local _ = require("gettext")
@ -95,6 +95,8 @@ local ime = IME:new{
show_candi_callback = function()
return G_reader_settings:nilOrTrue(SHOW_CANDI_KEY)
end,
separator = "分隔",
switch_char = "下一字",
W = W -- has wildcard function
}
@ -102,8 +104,8 @@ local wrappedAddChars = function(inputbox, char)
ime:wrappedAddChars(inputbox, char)
end
local function wrappedSeparate(inputbox)
ime:wrappedSeparate(inputbox)
local function seperate(inputbox)
ime:separate(inputbox)
end
local function wrappedDelChar(inputbox)
@ -128,19 +130,19 @@ local wrapInputBox = function(inputbox)
table.insert(wrappers, util.wrapMethod(inputbox, "delToStartOfLine", nil, clear_stack))
table.insert(wrappers, util.wrapMethod(inputbox, "clear", nil, clear_stack))
-- -- Navigation.
table.insert(wrappers, util.wrapMethod(inputbox, "leftChar", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "rightChar", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "upLine", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "downLine", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "leftChar", nil, seperate))
table.insert(wrappers, util.wrapMethod(inputbox, "rightChar", nil, seperate))
table.insert(wrappers, util.wrapMethod(inputbox, "upLine", nil, seperate))
table.insert(wrappers, util.wrapMethod(inputbox, "downLine", nil, seperate))
-- -- Move to other input box.
table.insert(wrappers, util.wrapMethod(inputbox, "unfocus", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "onCloseKeyboard", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "unfocus", nil, seperate))
table.insert(wrappers, util.wrapMethod(inputbox, "onCloseKeyboard", nil, seperate))
-- -- Gestures to move cursor.
table.insert(wrappers, util.wrapMethod(inputbox, "onTapTextBox", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "onHoldTextBox", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "onSwipeTextBox", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "onTapTextBox", nil, seperate))
table.insert(wrappers, util.wrapMethod(inputbox, "onHoldTextBox", nil, seperate))
table.insert(wrappers, util.wrapMethod(inputbox, "onSwipeTextBox", nil, seperate))
-- -- Others
table.insert(wrappers, util.wrapMethod(inputbox, "onSwitchingKeyboardLayout", nil, wrappedSeparate))
table.insert(wrappers, util.wrapMethod(inputbox, "onSwitchingKeyboardLayout", nil, seperate))
-- addChars is the only method we need a more complicated wrapper for.
table.insert(wrappers, util.wrapMethod(inputbox, "addChars", wrappedAddChars, nil))

Loading…
Cancel
Save