From 556e5bd6b4bcbd8f4d848b0f168724b86d468a46 Mon Sep 17 00:00:00 2001 From: hius07 <62179190+hius07@users.noreply.github.com> Date: Sat, 25 May 2024 19:51:44 +0300 Subject: [PATCH] VirtualKeyboard: delete word on backspace swipe west (#11843) Closes #11831. --- frontend/ui/widget/inputtext.lua | 71 +++++++++++++++----------- frontend/ui/widget/virtualkeyboard.lua | 14 ++++- 2 files changed, 55 insertions(+), 30 deletions(-) diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua index 861662a18..334730b03 100644 --- a/frontend/ui/widget/inputtext.lua +++ b/frontend/ui/widget/inputtext.lua @@ -213,7 +213,7 @@ local function initTouchEvents() text = _("Copy line"), callback = function() UIManager:close(clipboard_dialog) - local txt = table.concat(self.charlist, "", self:getStringPos({"\n", "\r"}, {"\n", "\r"})) + local txt = table.concat(self.charlist, "", self:getStringPos()) Device.input.setClipboardText(txt) UIManager:show(Notification:new{ text = _("Line copied to clipboard."), @@ -224,7 +224,7 @@ local function initTouchEvents() text = _("Copy word"), callback = function() UIManager:close(clipboard_dialog) - local txt = table.concat(self.charlist, "", self:getStringPos({"\n", "\r", " "}, {"\n", "\r", " "})) + local txt = table.concat(self.charlist, "", self:getStringPos(true)) Device.input.setClipboardText(txt) UIManager:show(Notification:new{ text = _("Word copied to clipboard."), @@ -763,39 +763,31 @@ function InputText:getLineCharPos(line_num) return char_pos end --- Get start and end positions of the substring --- delimited with the delimiters and containing char_pos. --- If char_pos not set, current charpos assumed. -function InputText:getStringPos(left_delimiter, right_delimiter, char_pos) - char_pos = char_pos and char_pos or self.charpos - local start_pos, end_pos = 1, #self.charlist - local done = false - if char_pos > 1 then - for i = char_pos, 2, -1 do - for j = 1, #left_delimiter do - if self.charlist[i-1] == left_delimiter[j] then - start_pos = i - done = true - break - end +-- Get start and end positions of a line (or a word) under the cursor. +function InputText:getStringPos(is_word, left_to_cursor) + local delimiter = is_word and "[\n\r%s.,;:!?–—―]" or "[\n\r]" + local start_pos, end_pos + if self.charpos > 1 then + for i = self.charpos - 1, 1, -1 do + if self.charlist[i]:find(delimiter) then + start_pos = i + 1 + break end - if done then break end end end - done = false - if char_pos < #self.charlist then - for i = char_pos, #self.charlist do - for j = 1, #right_delimiter do - if self.charlist[i] == right_delimiter[j] then + if left_to_cursor then + end_pos = self.charpos - 1 + else + if self.charpos <= #self.charlist then + for i = self.charpos, #self.charlist do + if self.charlist[i]:find(delimiter) then end_pos = i - 1 - done = true break end end - if done then break end end end - return start_pos, end_pos + return start_pos or 1, end_pos or #self.charlist end --- Return the character at the given offset. If is_absolute is truthy then the @@ -861,6 +853,27 @@ function InputText:delNextChar() self:initTextBox(table.concat(self.charlist)) end +function InputText:delWord(left_to_cursor) + if self.readonly or not self:isTextEditable(true) then + return + end + local start_pos, end_pos = self:getStringPos(true, left_to_cursor) + for i = end_pos, start_pos, -1 do + table.remove(self.charlist, i) + end + if #self.charlist > 0 then + local prev_pos = start_pos > 1 and start_pos - 1 or 1 + if not left_to_cursor and self.charlist[prev_pos]:find("[ \t]") then -- remove redundant space + table.remove(self.charlist, prev_pos) + self.charpos = prev_pos + else + self.charpos = start_pos + end + end + self.is_text_edited = true + self:initTextBox(table.concat(self.charlist)) +end + function InputText:delToStartOfLine() if self.readonly or not self:isTextEditable(true) then return @@ -906,14 +919,14 @@ function InputText:rightChar() end function InputText:goToStartOfLine() - local new_pos = select(1, self:getStringPos({"\n", "\r"}, {"\n", "\r"})) + local new_pos = self:getStringPos() self.text_widget:moveCursorToCharPos(new_pos) self:resyncPos() end function InputText:goToEndOfLine() - local new_pos = select(2, self:getStringPos({"\n", "\r"}, {"\n", "\r"})) + 1 - self.text_widget:moveCursorToCharPos(new_pos) + local _, new_pos = self:getStringPos() + self.text_widget:moveCursorToCharPos(new_pos + 1) self:resyncPos() end diff --git a/frontend/ui/widget/virtualkeyboard.lua b/frontend/ui/widget/virtualkeyboard.lua index 42957cf23..4eda75210 100644 --- a/frontend/ui/widget/virtualkeyboard.lua +++ b/frontend/ui/widget/virtualkeyboard.lua @@ -133,6 +133,13 @@ function VirtualKey:init() self.ignore_key_release = true -- don't have delChar called on release self.keyboard:delToStartOfLine() end + self.swipe_callback = function(ges) + if ges.direction == "west" then + self.keyboard:delWord(true) -- left to cursor + elseif ges.direction == "north" then + self.keyboard:delWord() + end + end --self.skiphold = true elseif self.label == "←" then self.callback = function() self.keyboard:leftChar() end @@ -1072,7 +1079,7 @@ function VirtualKeyboard:addKeys() width = key_width, height = key_height, } - if not virtual_key.key_chars then + if not virtual_key.key_chars and label ~= "" then virtual_key.swipe_callback = nil end table.insert(horizontal_group, virtual_key) @@ -1134,6 +1141,11 @@ function VirtualKeyboard:delChar() self.inputbox:delChar() end +function VirtualKeyboard:delWord(left_to_cursor) + logger.dbg("delete word") + self.inputbox:delWord(left_to_cursor) +end + function VirtualKeyboard:delToStartOfLine() logger.dbg("delete to start of line") self.inputbox:delToStartOfLine()