From f3fe643d81dedb7123d249e10c5a7ed2d6313361 Mon Sep 17 00:00:00 2001 From: hius07 <62179190+hius07@users.noreply.github.com> Date: Wed, 19 May 2021 19:05:16 +0300 Subject: [PATCH] InputDialog: add search (#7701) Searches for a string in the edited text. Available in the Text editor and other input dialogs with the navigation bar enabled. Find first searches from the beginning of the text. Find next searches from the next to cursor position, used for continious search. By now, the Search input window is closed after the search. You need to press the Find button again for continious search, the search string is kept in the input. Is it better to keep the dialog open for the comfortable continious search? And close it with the Cancel only? Case insensitive. Cursor jumps to the beginning of the found string. Notifications are shown for better results visibility. Unfortunately, violated our standartization to "search", couldn't invent better short wordings. --- frontend/ui/widget/inputdialog.lua | 67 +++++++++++++++++++++++++++++- frontend/ui/widget/inputtext.lua | 23 ++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index b018d049b..fd252fe5c 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -724,8 +724,73 @@ function InputDialog:_addScrollButtons(nav_bar) end, }) end - -- Add a button to go to the line by its number in the file if self.fullscreen then + -- Add a button to search for a string in the edited text + table.insert(row, { + text = _("Find"), + callback = function() + local input_dialog + input_dialog = InputDialog:new{ + title = _("Enter text to search for"), + stop_events_propagation = true, -- avoid interactions with upper InputDialog + input = self.search_value, + buttons = { + { + { + text = _("Cancel"), + callback = function() + UIManager:close(input_dialog) + end, + }, + { + text = _("Find first"), + callback = function() + self.search_value = input_dialog:getInputText() + if self.search_value ~= "" then + UIManager:close(input_dialog) + local msg + local char_pos = self._input_widget:searchString(self.search_value, 1) + if char_pos > 0 then + self._input_widget:moveCursorToCharPos(char_pos) + msg = T(_("Found in line %1"), self._input_widget:getLineNums()) + else + msg = _("Not found") + end + UIManager:show(Notification:new{ + text = msg, + }) + end + end, + }, + { + text = _("Find next"), + is_enter_default = true, + callback = function() + self.search_value = input_dialog:getInputText() + if self.search_value ~= "" then + UIManager:close(input_dialog) + local msg + local char_pos = self._input_widget:searchString(self.search_value) + if char_pos > 0 then + self._input_widget:moveCursorToCharPos(char_pos) + msg = T(_("Found in line %1."), self._input_widget:getLineNums()) + else + msg = _("Not found.") + end + UIManager:show(Notification:new{ + text = msg, + }) + end + end, + }, + }, + }, + } + UIManager:show(input_dialog) + input_dialog:onShowKeyboard() + end, + }) + -- Add a button to go to the line by its number in the file table.insert(row, { text = _("Go"), callback = function() diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua index 5e60fdb38..444e9168d 100644 --- a/frontend/ui/widget/inputtext.lua +++ b/frontend/ui/widget/inputtext.lua @@ -533,6 +533,29 @@ function InputText:getLineCharPos(line_num) return char_pos end +--- Search for a string. +-- if start_pos not set, starts a search from the next to cursor position +-- returns first found position or 0 if not found +function InputText:searchString(str, start_pos) + local str_len = string.len(str) + local char_pos, found = 0, 0 + start_pos = start_pos and (start_pos - 1) or self.charpos + for i = start_pos, #self.charlist - str_len do + for j = 1, str_len do + if string.lower(self.charlist[i + j]) ~= string.lower(string.sub(str, j, j)) then + found = 0 + break + end + found = found + 1 + end + if found == str_len then + char_pos = i + 1 + break + end + end + return char_pos +end + function InputText:addChars(chars) if not chars then -- VirtualKeyboard:addChar(key) gave us 'nil' once (?!)