aboutsummaryrefslogtreecommitdiff
path: root/modules/textadept
diff options
context:
space:
mode:
Diffstat (limited to 'modules/textadept')
-rw-r--r--modules/textadept/command_entry.lua3
-rw-r--r--modules/textadept/find.lua96
-rw-r--r--modules/textadept/keys.lua8
-rw-r--r--modules/textadept/macros.lua2
-rw-r--r--modules/textadept/menu.lua9
5 files changed, 35 insertions, 83 deletions
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},