diff options
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | core/events.lua | 10 | ||||
-rw-r--r-- | modules/textadept/command_entry.lua | 3 | ||||
-rw-r--r-- | modules/textadept/find.lua | 96 | ||||
-rw-r--r-- | modules/textadept/keys.lua | 8 | ||||
-rw-r--r-- | modules/textadept/macros.lua | 2 | ||||
-rw-r--r-- | modules/textadept/menu.lua | 9 | ||||
-rw-r--r-- | src/textadept.c | 60 | ||||
-rw-r--r-- | test/test.lua | 82 |
9 files changed, 121 insertions, 152 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 041312e9..7b14eaa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -246,7 +246,7 @@ Changes: terminal version. * Replaced `ui.command_entry.enter_mode()` and `ui.command_entry.finish_mode()` with simplified [`ui.command_entry.run()`][]. -* Added [`ui.find.find_incremental_keys`][] table of key bindings during "Find +* Added `ui.find.find_incremental_keys` table of key bindings during "Find Incremental" searches. * Replaced `textadept.macros.start_recording()` and `textadept.macros.stop_recording()` with [`textadept.macros.record()`][]. @@ -268,7 +268,6 @@ Changes: [Scintilla]: http://scintilla.org [`textadept.editing.paste_reindent()`]: api.html#textadept.editing.paste_reindent [`ui.command_entry.run()`]: api.html#ui.command_entry.run -[`ui.find.find_incremental_keys`]: api.html#ui.find.find_incremental_keys [`textadept.macros.record()`]: api.html#textadept.macros.record ## 10.6 (01 Sep 2019) diff --git a/core/events.lua b/core/events.lua index 34943e1d..eb60c99b 100644 --- a/core/events.lua +++ b/core/events.lua @@ -133,6 +133,10 @@ local M = {} -- -- * _`text`_: The text to search for. -- * _`next`_: Whether or not to search forward. +-- @field FIND_TEXT_CHANGED (string) +-- Emitted when the text in the "Find" field of the Find & Replace Pane +-- changes. +-- `ui.find.find_entry_text` contains the current text. -- @field FOCUS (string) -- Emitted when Textadept receives focus. -- This event is never emitted when Textadept is running in the terminal. @@ -391,9 +395,9 @@ end) for _, v in pairs(_SCINTILLA.events) do M[v[1]:upper()] = v[1] end local textadept_events = { -- defined in C 'appleevent_odoc', 'buffer_after_switch', 'buffer_before_switch', - 'buffer_deleted', 'buffer_new', 'csi', 'error', 'find', 'focus', - 'initialized', 'keypress', 'menu_clicked', 'mouse', 'quit', 'replace', - 'replace_all', 'reset_after', 'reset_before', 'resume', 'suspend', + 'buffer_deleted', 'buffer_new', 'csi', 'error', 'find', 'find_text_changed', + 'focus', 'initialized', 'keypress', 'menu_clicked', 'mouse', 'quit', + 'replace', 'replace_all', 'reset_after', 'reset_before', 'resume', 'suspend', 'tab_clicked', 'view_after_switch', 'view_before_switch', 'view_new' } for _, v in pairs(textadept_events) do M[v:upper()] = v end diff --git a/modules/textadept/command_entry.lua b/modules/textadept/command_entry.lua index eda71b94..b1227c27 100644 --- a/modules/textadept/command_entry.lua +++ b/modules/textadept/command_entry.lua @@ -7,8 +7,7 @@ local M = ui.command_entry --- -- Textadept's Command Entry. -- It supports multiple modes that each have their own functionality (such as --- running Lua code, searching for text incrementally, and filtering text --- through shell commands) and history. +-- running Lua code and filtering text through shell commands) and history. -- @field height (number) -- The height in pixels of the command entry. module('ui.command_entry')]] diff --git a/modules/textadept/find.lua b/modules/textadept/find.lua index 75de0dee..f221f642 100644 --- a/modules/textadept/find.lua +++ b/modules/textadept/find.lua @@ -22,6 +22,9 @@ local M = ui.find -- @field in_files (bool) -- Find search text in a list of files. -- The default value is `false`. +-- @field incremental (bool) +-- Find search text incrementally as it is typed. +-- The default value is `false`. -- @field find_label_text (string, Write-only) -- The text of the "Find" label. -- This is primarily used for localization. @@ -97,7 +100,9 @@ M.find_in_files_filters = {} -- Keep track of find text and found text so that "replace all" works as -- expected during a find session ("replace all" with selected text normally --- does "replace in selection"). +-- does "replace in selection"). Also track find text for incremental find (if +-- text has changed, the user is still typing; if text is the same, the user +-- clicked "Find Next" or "Find Prev"). local find_text, found_text -- Returns a bit-mask of search flags to use in Scintilla search functions based @@ -142,6 +147,18 @@ local function find(text, next, flags, no_wrap, wrapped) if flags >= 1 << 31 then M.find_in_files() return end -- not performed here local first_visible_line = view.first_visible_line -- for 'no results found' + if M.incremental and not wrapped then + if type(M.incremental) == 'boolean' then + -- Starting a new incremental search, anchor at current pos. + M.incremental = buffer.current_pos + elseif text == find_text then + -- "Find Next" or "Find Prev" clicked, anchor at new current pos. + M.incremental = buffer:position_relative( + buffer.current_pos, next and 1 or -1) + end + buffer:goto_pos(M.incremental or 1) + end + -- If text is selected, assume it is from the current search and move the -- caret appropriately for the next search. buffer:goto_pos(next and buffer.selection_end or buffer.selection_start) @@ -152,7 +169,8 @@ local function find(text, next, flags, no_wrap, wrapped) local pos = f(buffer, flags, text) view:ensure_visible_enforce_policy(buffer:line_from_position(pos)) view:scroll_range(buffer.anchor, buffer.current_pos) - find_text, found_text = text, buffer:get_sel_text() -- track for "replace all" + -- Track find text and found text for "replace all" and incremental find. + find_text, found_text = text, buffer:get_sel_text() -- If nothing was found, wrap the search. if pos == -1 and not no_wrap then @@ -190,78 +208,14 @@ local function find(text, next, flags, no_wrap, wrapped) return pos end events.connect(events.FIND, find) +events.connect(events.FIND_TEXT_CHANGED, function() + if not M.incremental then return end + events.emit(events.FIND, M.find_entry_text, true) + return true -- redraw in CURSES +end) events.connect( events.FIND_WRAPPED, function() ui.statusbar_text = _L['Search wrapped'] end) -local incremental_start - --- Finds and selects text incrementally in the current buffer from a starting --- position. --- Flags other than `FIND_MATCHCASE` are ignored. --- @param text The text to find. --- @param next Flag indicating whether or not the search direction is forward. --- @param anchor Flag indicating whether or not to search from the current --- position. -local function find_incremental(text, next, anchor) - local orig_pos = buffer.current_pos - if anchor then - incremental_start = buffer:position_relative(orig_pos, next and 1 or -1) - end - buffer:goto_pos(incremental_start or 1) - -- Note: even though `events.FIND` does not support a flags parameter, the - -- default handler has one, so make use of it. - events.emit( - events.FIND, text, next, M.match_case and buffer.FIND_MATCHCASE or 0) - if buffer.selection_empty and anchor then buffer:goto_pos(orig_pos) end -end - ---- --- Begins an incremental search using the command entry if *text* is `nil`. --- Otherwise, continues an incremental search by searching for the next or --- previous instance of string *text*, depending on boolean *next*. --- *anchor* indicates whether or not to search for *text* starting from the --- caret position instead of the position where the incremental search began. --- Only the `match_case` find option is recognized. Normal command entry --- functionality is unavailable until the search is finished or by pressing --- `Esc`. --- @param text The text to incrementally search for, or `nil` to begin an --- incremental search. --- @param next Flag indicating whether or not the search direction is forward. --- Only applicable when *text* is not `nil`. --- @param anchor Optional flag indicating whether or not to start searching from --- the caret position. The default value is `false`. --- @name find_incremental -function M.find_incremental(text, next, anchor) - assert_type(text, 'string/nil', 1) - if text then find_incremental(text, next, anchor) return end - incremental_start = buffer.current_pos - ui.command_entry:set_text('') - ui.command_entry.run(nil, M.find_incremental_keys) -end - ---- --- Table of key bindings used when searching for text incrementally. --- @class table --- @name find_incremental_keys -M.find_incremental_keys = setmetatable({ - ['\n'] = function() - M.find_entry_text = ui.command_entry:get_text() -- save - M.find_incremental(ui.command_entry:get_text(), true, true) - end, - ['\b'] = function() - local e = ui.command_entry:position_before(ui.command_entry.length + 1) - M.find_incremental(ui.command_entry:text_range(1, e), true) - return false -- propagate - end -}, {__index = function(_, k) - -- Add the character for any key pressed without modifiers to incremental - -- find. - if #k == 1 or not k:find('ctrl%+') and not k:find('alt%+') and - not k:find('meta%+') and not k:find('shift%+') then - M.find_incremental(ui.command_entry:get_text() .. k, true) - end -end}) - --- -- Searches directory *dir* or the user-specified directory for files that match -- search text and search options (subject to optional filter *filter*), and diff --git a/modules/textadept/keys.lua b/modules/textadept/keys.lua index 90cb2000..e105d57b 100644 --- a/modules/textadept/keys.lua +++ b/modules/textadept/keys.lua @@ -349,7 +349,8 @@ local bindings = { -- Find Prev is ap when find pane is focused in GUI. -- Replace is ar when find pane is focused in GUI. -- Replace All is aa when find pane is focused in GUI. - [ui.find.find_incremental] = {'ctrl+alt+f', 'ctrl+cmd+f', 'ctrl+meta+f'}, + [m_search[_L['Find Incremental']][2]] = + {'ctrl+alt+f', 'ctrl+cmd+f', 'ctrl+meta+f'}, [m_search[_L['Find in Files']][2]] = {'ctrl+F', 'cmd+F', nil}, -- Find in Files is ai when find pane is focused in GUI. [m_search[_L['Goto Next File Found']][2]] = {'ctrl+alt+g', 'ctrl+cmd+g', nil}, @@ -529,9 +530,4 @@ end -- not propagate it. if OSX then keys.fn = function() return true end end --- Reverse incremental find. -ui.find.find_incremental_keys['ctrl+r'] = function() - ui.find.find_incremental(ui.command_entry:get_text(), false, true) -end - return M diff --git a/modules/textadept/macros.lua b/modules/textadept/macros.lua index a3636e6f..ff802475 100644 --- a/modules/textadept/macros.lua +++ b/modules/textadept/macros.lua @@ -18,7 +18,7 @@ events.connect(events.INITIALIZED, function() local m_tools = textadept.menu.menubar[_L['Tools']] ignore = { textadept.menu.menubar[_L['Search']][_L['Find']][2], - ui.find.find_incremental, + textadept.menu.menubar[_L['Search']][_L['Find Incremental']][2], m_tools[_L['Select Command']][2], m_tools[_L['Macros']][_L['Start/Stop Recording']][2] } diff --git a/modules/textadept/menu.lua b/modules/textadept/menu.lua index 98f0f1cc..14efd40f 100644 --- a/modules/textadept/menu.lua +++ b/modules/textadept/menu.lua @@ -139,17 +139,20 @@ local default_menubar = { { title = _L['Search'], {_L['Find'], function() - ui.find.in_files = false + ui.find.in_files, ui.find.incremental = false, false ui.find.focus() end}, {_L['Find Next'], ui.find.find_next}, {_L['Find Previous'], ui.find.find_prev}, {_L['Replace'], ui.find.replace}, {_L['Replace All'], ui.find.replace_all}, - {_L['Find Incremental'], ui.find.find_incremental}, + {_L['Find Incremental'], function() + ui.find.in_files, ui.find.incremental = false, true + ui.find.focus() + end}, SEPARATOR, {_L['Find in Files'], function() - ui.find.in_files = true + ui.find.in_files, ui.find.incremental = true, false ui.find.focus() end}, {_L['Goto Next File Found'], function() ui.find.goto_file_found(true) end}, diff --git a/src/textadept.c b/src/textadept.c index 41569a4e..9a3ae33e 100644 --- a/src/textadept.c +++ b/src/textadept.c @@ -151,7 +151,7 @@ TermKey *ta_tk; // global for CDK use // curses find & replace pane. static CDKSCREEN *findbox; static CDKENTRY *find_entry, *repl_entry, *focused_entry; -static char *find_text, *repl_text, *find_label, *repl_label; +static char *find_text, *repl_text, *find_label, *repl_label, *prev_text; #define set_entry_text(entry, text) copyfree(&entry, text) typedef enum {find_next, replace, find_prev, replace_all} FindButton; static int find_options[4]; @@ -342,21 +342,43 @@ static int click_replace_all(lua_State *L) { #if CURSES /** + * Redraws an entire pane and its children. + * @param pane The pane to redraw. + */ +static void refresh_pane(Pane *pane) { + if (pane->type == VSPLIT) { + mvwvline(pane->win, 0, 0, 0, pane->rows), wrefresh(pane->win); + refresh_pane(pane->child1), refresh_pane(pane->child2); + } else if (pane->type == HSPLIT) { + mvwhline(pane->win, 0, 0, 0, pane->cols), wrefresh(pane->win); + refresh_pane(pane->child1), refresh_pane(pane->child2); + } else scintilla_noutrefresh(pane->view); +} + +/** Refreshes the entire screen. */ +static void refresh_all() { + refresh_pane(pane); + if (command_entry_focused) scintilla_noutrefresh(command_entry); + refresh(); +} + +/** * Signal for Find/Replace entry keypress. * For tab keys, toggle through find/replace buttons. * For ^N and ^P keys, cycle through find/replace history. * For F1-F4 keys, toggle the respective search option. * For up and down keys, toggle entry focus. + * Otherwise, emit events for entry text changes. */ static int find_keypress(EObjectType _, void *object, void *data, chtype key) { CDKENTRY *entry = (CDKENTRY *)object; + char *text = getCDKEntryValue(entry); if (key == KEY_TAB || key == KEY_BTAB) injectCDKButtonbox((CDKBUTTONBOX *)data, key); else if (key == CDK_PREV || key == CDK_NEXT) { ListStore *store = entry == find_entry ? find_history : repl_history; int i; - for (i = 9; i >= 0; i--) - if (store[i] && strcmp(store[i], getCDKEntryValue(entry)) == 0) break; + for (i = 9; i >= 0; i--) if (store[i] && strcmp(store[i], text) == 0) break; key == CDK_PREV ? i++ : i--; if (i >= 0 && i <= 9 && store[i]) setCDKEntryValue(entry, store[i]), drawCDKEntry(entry, FALSE); @@ -373,30 +395,12 @@ static int find_keypress(EObjectType _, void *object, void *data, chtype key) { } else if (key == KEY_UP || key == KEY_DOWN) { focused_entry = entry == find_entry ? repl_entry : find_entry; injectCDKEntry(entry, KEY_ENTER); // exit this entry + } else if ((!prev_text || strcmp(prev_text, text) != 0)) { + if (emit(lua, "find_text_changed", -1)) refresh_all(); + copyfree(&prev_text, text); } return TRUE; } - -/** - * Redraws an entire pane and its children. - * @param pane The pane to redraw. - */ -static void refresh_pane(Pane *pane) { - if (pane->type == VSPLIT) { - mvwvline(pane->win, 0, 0, 0, pane->rows), wrefresh(pane->win); - refresh_pane(pane->child1), refresh_pane(pane->child2); - } else if (pane->type == HSPLIT) { - mvwhline(pane->win, 0, 0, 0, pane->cols), wrefresh(pane->win); - refresh_pane(pane->child1), refresh_pane(pane->child2); - } else scintilla_noutrefresh(pane->view); -} - -/** Refreshes the entire screen. */ -static void refresh_all() { - refresh_pane(pane); - if (command_entry_focused) scintilla_noutrefresh(command_entry); - refresh(); -} #endif /** `find.focus()` Lua function. */ @@ -438,6 +442,7 @@ static int focus_find(lua_State *L) { bind(KEY_DOWN, NULL), bind(KEY_UP, NULL); setCDKEntryValue(find_entry, find_text); setCDKEntryValue(repl_entry, repl_text); + setCDKEntryPostProcess(find_entry, find_keypress, NULL), prev_text = NULL; char *clipboard = scintilla_get_clipboard(focused_view, NULL); GPasteBuffer = copyChar(clipboard); // set the CDK paste buffer curs_set(1); @@ -2169,6 +2174,11 @@ static GtkWidget *new_combo(GtkWidget **label, GtkWidget **entry, ListStore **hi return combo; } +/** Signal for a Find entry keypress. */ +static void find_changed(GtkEditable *_, void *L) { + emit(L, "find_text_changed", -1); +} + /** Creates and returns a new button for the findbox. */ static GtkWidget *new_button() { GtkWidget *button = gtk_button_new_with_mnemonic(""); // localized via Lua @@ -2190,6 +2200,8 @@ static GtkWidget *new_findbox() { GtkWidget *find_combo = new_combo(&find_label, &find_entry, &find_history), *replace_combo = new_combo(&repl_label, &repl_entry, &repl_history); + g_signal_connect( + GTK_EDITABLE(find_entry), "changed", G_CALLBACK(find_changed), lua); find_next = new_button(), find_prev = new_button(), replace = new_button(), replace_all = new_button(), match_case = new_option(), whole_word = new_option(), regex = new_option(), in_files = new_option(); diff --git a/test/test.lua b/test/test.lua index d2be6516..505382a8 100644 --- a/test/test.lua +++ b/test/test.lua @@ -1814,6 +1814,10 @@ function test_ui_highlight_word() assert(mask & bit > 0, 'no indicator on line %d', buffer:line_from_position(pos)) end end + local function update() + ui.update() + if CURSES then events.emit(events.UPDATE_UI, buffer.UPDATE_SELECTION) end + end local highlight = ui.highlight_words ui.highlight_words = ui.HIGHLIGHT_SELECTED @@ -1835,7 +1839,7 @@ function test_ui_highlight_word() } end textadept.editing.select_word() - ui.update() + update() verify_foo() events.emit(events.KEYPRESS, not CURSES and 0xFF1B or 7) -- esc local pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 1) @@ -1843,7 +1847,7 @@ function test_ui_highlight_word() -- Verify turning off word highlighting. ui.highlight_words = ui.HIGHLIGHT_NONE textadept.editing.select_word() - ui.update() + update() pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) assert_equal(pos, 1) -- no highlights ui.highlight_words = ui.HIGHLIGHT_SELECTED -- reset @@ -1859,19 +1863,19 @@ function test_ui_highlight_word() -- Verify current word highlighting. ui.highlight_words = ui.HIGHLIGHT_CURRENT buffer:goto_pos(1) - ui.update() + update() verify_foo() buffer:line_down() - ui.update() + update() verify{buffer:position_from_line(LINE(2))} buffer:line_down() - ui.update() + update() verify{buffer:position_from_line(LINE(3)), buffer:position_from_line(LINE(4)) + 9} buffer:word_right() - ui.update() + update() verify_foo() buffer:char_left() - ui.update() + update() pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) assert_equal(pos, 1) -- no highlights buffer:close(true) @@ -2101,7 +2105,7 @@ end function test_ui_find_highlight_results() local function assert_indics(indics) - local bit = 1 << ui.INDIC_HIGHLIGHT - 1 + local bit = 1 << ui.find.INDIC_FIND - 1 for _, pos in ipairs(indics) do local mask = buffer:indicator_all_on_for(pos) assert(mask & bit > 0, 'no indicator on line %d', buffer:line_from_position(pos)) @@ -2140,21 +2144,20 @@ function test_ui_find_highlight_results() -- Do not highlight short searches (potential performance issue). ui.find.find_entry_text = 'f' ui.find.find_next() - local pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) + local pos = buffer:indicator_end(ui.find.INDIC_FIND, 2) assert_equal(pos, 1) + -- Verify turning off match highlighting works. + ui.find.highlight_all_matches = false + ui.find.find_entry_text = 'foo' + ui.find.find_next() + pos = buffer:indicator_end(ui.find.INDIC_FIND, 2) + assert_equal(pos, 1) + ui.find.highlight_all_matches = true -- reset ui.find.find_entry_text = '' -- reset buffer:close(true) end function test_ui_find_incremental() - if not rawget(ui.find.find_incremental_keys, '\n') then - -- Overwritten in _USERHOME. - ui.find.find_incremental_keys['\n'] = function() - ui.find.find_entry_text = ui.command_entry:get_text() -- save - ui.find.find_incremental(ui.command_entry:get_text(), true, true) - end - end - buffer.new() buffer:set_text(table.concat({ ' foo', @@ -2163,40 +2166,38 @@ function test_ui_find_incremental() 'FOOquux' }, '\n')) assert_equal(buffer.current_pos, POS(1)) - ui.find.find_incremental() - events.emit(events.KEYPRESS, string.byte('f')) - ui.command_entry:add_text('f') -- simulate keypress + ui.find.incremental = true + ui.find.find_entry_text = 'f' -- simulate 'f' keypress + if CURSES then events.emit(events.FIND_TEXT_CHANGED) end -- simulate assert_equal(buffer.selection_start, POS(1) + 1) assert_equal(buffer.selection_end, buffer.selection_start + 1) - events.emit(events.KEYPRESS, string.byte('o')) - ui.command_entry:add_text('o') -- simulate keypress - events.emit(events.KEYPRESS, string.byte('o')) - ui.command_entry:add_text('o') -- simulate keypress + ui.find.find_entry_text = 'fo' -- simulate 'o' keypress + ui.find.find_entry_text = 'foo' -- simulate 'o' keypress + if CURSES then events.emit(events.FIND, ui.find.find_entry_text, true) end assert_equal(buffer.selection_start, POS(1) + 1) assert_equal(buffer.selection_end, buffer.selection_start + 3) - events.emit(events.KEYPRESS, not CURSES and 0xFF0D or 343) -- \n + if CURSES then events.emit(events.FIND_TEXT_CHANGED) end -- simulate assert_equal(buffer.selection_start, buffer:position_from_line(LINE(2))) assert_equal(buffer.selection_end, buffer.selection_start + 3) - events.emit(events.KEYPRESS, string.byte('q')) - ui.command_entry:add_text('q') -- simulate keypress + ui.find.find_entry_text = 'fooq' -- simulate 'q' keypress + if CURSES then events.emit(events.FIND_TEXT_CHANGED) end -- simulate assert_equal(buffer.selection_start, buffer:position_from_line(LINE(4))) assert_equal(buffer.selection_end, buffer.selection_start + 4) - events.emit(events.KEYPRESS, not CURSES and 0xFF08 or 263) -- \b - ui.command_entry:delete_back() -- simulate keypress + ui.find.find_entry_text = 'foo' -- simulate backspace + if CURSES then events.emit(events.FIND_TEXT_CHANGED) end -- simulate assert_equal(buffer.selection_start, buffer:position_from_line(LINE(2))) assert_equal(buffer.selection_end, buffer.selection_start + 3) - events.emit(events.KEYPRESS, not CURSES and 0xFF0D or 343) -- \n + events.emit(events.FIND, ui.find.find_entry_text, true) -- simulate Find Next assert_equal(buffer.selection_start, buffer:position_from_line(LINE(3))) assert_equal(buffer.selection_end, buffer.selection_start + 3) ui.find.match_case = true - events.emit(events.KEYPRESS, not CURSES and 0xFF0D or 343) -- \n, wrap + events.emit(events.FIND, ui.find.find_entry_text, true) -- simulate Find Next, wrap assert_equal(buffer.selection_start, POS(1) + 1) assert_equal(buffer.selection_end, buffer.selection_start + 3) ui.find.match_case = false ui.find.find_entry_text = '' -- reset + ui.find.incremental = false -- reset buffer:close(true) - - assert_raises(function() ui.find.find_incremental(1) end, 'string/nil expected, got number') end function test_ui_find_incremental_highlight() @@ -2207,25 +2208,26 @@ function test_ui_find_incremental_highlight() 'FOObaz', 'FOOquux' }, '\n')) - ui.find.find_incremental() - events.emit(events.KEYPRESS, string.byte('f')) - ui.command_entry:add_text('f') -- simulate keypress - local pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) + ui.find.incremental = true + ui.find.find_entry_text = 'f' -- simulate 'f' keypress + if CURSES then events.emit(events.FIND_TEXT_CHANGED) end -- simulate + local pos = buffer:indicator_end(ui.find.INDIC_FIND, 2) assert_equal(pos, 1) -- too short - events.emit(events.KEYPRESS, string.byte('o')) - ui.command_entry:add_text('o') -- simulate keypress + ui.find.find_entry_text = 'fo' -- simulate 'o' keypress + if CURSES then events.emit(events.FIND_TEXT_CHANGED) end -- simulate local indics = { buffer:position_from_line(LINE(1)) + 1, buffer:position_from_line(LINE(2)), buffer:position_from_line(LINE(3)), buffer:position_from_line(LINE(4)) } - local bit = 1 << ui.INDIC_HIGHLIGHT - 1 + local bit = 1 << ui.find.INDIC_FIND - 1 for _, pos in ipairs(indics) do local mask = buffer:indicator_all_on_for(pos) assert(mask & bit > 0, 'no indicator on line %d', buffer:line_from_position(pos)) end ui.find.find_entry_text = '' -- reset + ui.find.incremental = false -- reset buffer:close(true) end |