diff options
-rw-r--r-- | core/ui.lua | 56 | ||||
-rw-r--r-- | modules/textadept/find.lua | 2 | ||||
-rw-r--r-- | test/test.lua | 54 |
3 files changed, 77 insertions, 35 deletions
diff --git a/core/ui.lua b/core/ui.lua index ce7aeb84..7aa15070 100644 --- a/core/ui.lua +++ b/core/ui.lua @@ -33,16 +33,25 @@ local ui = ui -- with a group of [`ui.print()`]() and [`ui._print()`]() function calls. -- The default value is `false`, and focuses buffers when messages are printed -- to them. --- @field highlight_words (bool) --- Whether or not to automatically highlight all instances of the selected --- word. --- The default value is `true` except in the terminal version. +-- @field highlight_words (number) +-- The word highlight mode. +-- +-- * `ui.HIGHLIGHT_CURRENT` +-- Automatically highlight all instances of the current word. +-- * `ui.HIGHLIGHT_SELECTED` +-- Automatically highlight all instances of the selected word. +-- * `ui.HIGHLIGHT_NONE` +-- Do not automatically highlight words. +-- +-- The default value is `ui.HIGHLIGHT_SELECTED` except in the terminal +-- version, where it is `ui.HIGHLIGHT_NONE`. -- @field INDIC_HIGHLIGHT (number) -- The word highlight indicator number. module('ui')]] ui.silent_print = false -ui.highlight_words = not CURSES +ui.HIGHLIGHT_NONE, ui.HIGHLIGHT_CURRENT, ui.HIGHLIGHT_SELECTED = 1, 2, 3 +ui.highlight_words = not CURSES and ui.HIGHLIGHT_SELECTED or ui.HIGHLIGHT_NONE ui.INDIC_HIGHLIGHT = _SCINTILLA.next_indic_number() -- Helper function for printing messages to buffers. @@ -300,21 +309,30 @@ events_connect(events.KEYPRESS, function(code) if keys.KEYSYMS[code] == 'esc' then clear_highlighted_words() end end, 1) --- Highlight all instances of the selected word. +-- Highlight all instances of the current or selected word. events_connect(events.UPDATE_UI, function(updated) - if updated and updated & buffer.UPDATE_SELECTION > 0 and - ui.highlight_words and not buffer.selection_empty and - buffer:is_range_word(buffer.selection_start, buffer.selection_end) and - buffer:get_sel_text():find('^%S+$') then - clear_highlighted_words() - local word = buffer:text_range(buffer.selection_start, buffer.selection_end) - buffer.search_flags = buffer.FIND_MATCHCASE | buffer.FIND_WHOLEWORD - buffer:target_whole_document() - while buffer:search_in_target(word) ~= -1 do - buffer:indicator_fill_range( - buffer.target_start, buffer.target_end - buffer.target_start) - buffer:set_target_range(buffer.target_end, buffer.length + 1) - end + if not updated or updated & buffer.UPDATE_SELECTION == 0 then return end + local word + if ui.highlight_words == ui.HIGHLIGHT_CURRENT then + local s = buffer:word_start_position(buffer.current_pos, true) + local e = buffer:word_end_position(buffer.current_pos, true) + if s == e then clear_highlighted_words() return end + word = buffer:text_range(s, e) + elseif ui.highlight_words == ui.HIGHLIGHT_SELECTED then + local s, e = buffer.selection_start, buffer.selection_end + if not buffer:is_range_word(s, e) then return end + word = buffer:get_sel_text() + if not word:find('^%S+$') then return end + else + return + end + clear_highlighted_words() + buffer.search_flags = buffer.FIND_MATCHCASE | buffer.FIND_WHOLEWORD + buffer:target_whole_document() + while buffer:search_in_target(word) ~= -1 do + buffer:indicator_fill_range( + buffer.target_start, buffer.target_end - buffer.target_start) + buffer:set_target_range(buffer.target_end, buffer.length + 1) end end) diff --git a/modules/textadept/find.lua b/modules/textadept/find.lua index 7442276f..2a107b7c 100644 --- a/modules/textadept/find.lua +++ b/modules/textadept/find.lua @@ -127,7 +127,7 @@ local function find(text, next, flags, no_wrap, wrapped) -- Highlight all occurrences first, otherwise regex tags will be overwritten. buffer.indicator_current = ui.INDIC_HIGHLIGHT buffer:indicator_clear_range(1, buffer.length) - if ui.highlight_words and #text > 1 then + if ui.highlight_words ~= ui.HIGHLIGHT_NONE and #text > 1 then buffer.search_flags = flags buffer:target_whole_document() while buffer:search_in_target(text) ~= -1 do diff --git a/test/test.lua b/test/test.lua index c3c58f92..d2be6516 100644 --- a/test/test.lua +++ b/test/test.lua @@ -1807,40 +1807,46 @@ function test_editing_convert_indentation() end function test_ui_highlight_word() + local function verify(indics) + local bit = 1 << ui.INDIC_HIGHLIGHT - 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 + end + local highlight = ui.highlight_words - ui.highlight_words = true + ui.highlight_words = ui.HIGHLIGHT_SELECTED buffer.new() buffer:append_text(table.concat({ 'foo', 'foobar', - 'bar foo', + 'bar foo', 'baz foo bar', 'fooquux', 'foo' }, '\n')) + local function verify_foo() + verify{ + buffer:position_from_line(LINE(1)), + buffer:position_from_line(LINE(3)) + 5, + buffer:position_from_line(LINE(4)) + 4, + buffer:position_from_line(LINE(6)) + } + end textadept.editing.select_word() ui.update() - local indics = { - buffer:position_from_line(LINE(1)), - buffer:position_from_line(LINE(3)) + 4, - buffer:position_from_line(LINE(4)) + 4, - buffer:position_from_line(LINE(6)) - } - local bit = 1 << ui.INDIC_HIGHLIGHT - 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 + verify_foo() events.emit(events.KEYPRESS, not CURSES and 0xFF1B or 7) -- esc local pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 1) assert_equal(pos, 1) -- highlights cleared -- Verify turning off word highlighting. - ui.highlight_words = false + ui.highlight_words = ui.HIGHLIGHT_NONE textadept.editing.select_word() ui.update() pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) assert_equal(pos, 1) -- no highlights - ui.highlight_words = true -- reset + ui.highlight_words = ui.HIGHLIGHT_SELECTED -- reset -- Verify partial word selections do not highlight words. buffer:set_sel(1, 3) pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) @@ -1850,6 +1856,24 @@ function test_ui_highlight_word() assert(buffer:is_range_word(buffer.selection_start, buffer.selection_end)) pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) assert_equal(pos, 1) -- no highlights + -- Verify current word highlighting. + ui.highlight_words = ui.HIGHLIGHT_CURRENT + buffer:goto_pos(1) + ui.update() + verify_foo() + buffer:line_down() + ui.update() + verify{buffer:position_from_line(LINE(2))} + buffer:line_down() + ui.update() + verify{buffer:position_from_line(LINE(3)), buffer:position_from_line(LINE(4)) + 9} + buffer:word_right() + ui.update() + verify_foo() + buffer:char_left() + ui.update() + pos = buffer:indicator_end(ui.INDIC_HIGHLIGHT, 2) + assert_equal(pos, 1) -- no highlights buffer:close(true) ui.highlight_words = highlight -- reset end |