aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--core/.ui.dialogs.luadoc26
-rw-r--r--core/locale.conf4
-rw-r--r--core/locales/locale.ar.conf4
-rw-r--r--core/locales/locale.de.conf4
-rw-r--r--core/locales/locale.es.conf4
-rw-r--r--core/locales/locale.fr.conf4
-rw-r--r--core/locales/locale.it.conf4
-rw-r--r--core/locales/locale.pl.conf4
-rw-r--r--core/locales/locale.ru.conf4
-rw-r--r--core/locales/locale.sv.conf4
-rw-r--r--core/locales/locale.zh.conf4
-rw-r--r--core/ui.lua8
-rw-r--r--doc/manual.md37
-rw-r--r--modules/textadept/find.lua84
-rw-r--r--src/Makefile6
-rw-r--r--src/textadept.c31
-rw-r--r--test/test.lua27
17 files changed, 147 insertions, 112 deletions
diff --git a/core/.ui.dialogs.luadoc b/core/.ui.dialogs.luadoc
index 0a6579d1..08a810d1 100644
--- a/core/.ui.dialogs.luadoc
+++ b/core/.ui.dialogs.luadoc
@@ -325,6 +325,32 @@ function filesave(options) end
function textbox(options) end
---
+-- Displays a progressbar dialog defined by dialog options table *options* and
+-- updates from function *f*.
+-- Returns "stopped" if *options*.`stoppable` is `true` and the user clicked the
+-- "Stop" button. Otherwise, returns `nil`.
+-- @param options Table of key-value option pairs for the progressbar dialog.
+--
+-- * `title`: The dialog's title text.
+-- * `percent`: The initial progressbar percentage between 0 and 100.
+-- * `text`: The initial progressbar display text (GTK only).
+-- * `indeterminate`: Show the progress bar as "busy", with no percentage
+-- updates.
+-- * `stoppable`: Show the "Stop" button.
+-- * `width`: The dialog's pixel width.
+-- * `height`: The dialog's pixel height.
+-- @param f Function repeatedly called to do work and provide progress updates.
+-- The function is called without arguments and must return either `nil`,
+-- which indicates work is complete, or a progress percentage number in the
+-- range 0-100 and optional string text to display (GTK only). If the text
+-- is either "stop disable" or "stop enable" and *options*.`stoppable` is
+-- `true`, the "Stop" button is disabled or enabled, respectively.
+-- @return nil or "stopped"
+-- @usage ui.dialogs.progressbar({stoppable = true},
+-- function() if work() then return percent, status else return nil end end)
+function progressbar(options, f) end
+
+---
-- Prompts the user with a drop-down item selection dialog defined by dialog
-- options table *options*, returning the selected button's index along with the
-- index of the selected item.
diff --git a/core/locale.conf b/core/locale.conf
index bdeb6a84..ea100822 100644
--- a/core/locale.conf
+++ b/core/locale.conf
@@ -121,10 +121,6 @@ Select Directory = Select Directory
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Binary file matches.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Continue?
-Still searching in files... Continue waiting? = Still searching in files... Continue waiting?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Find in Files aborted
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.ar.conf b/core/locales/locale.ar.conf
index e8a1b9fa..32a82f20 100644
--- a/core/locales/locale.ar.conf
+++ b/core/locales/locale.ar.conf
@@ -121,10 +121,6 @@ Select Directory = ابحث في الملفات
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Binary file matches.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Continue?
-Still searching in files... Continue waiting? = Still searching in files... Continue waiting?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Find in Files aborted
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.de.conf b/core/locales/locale.de.conf
index 84e79bb0..2207fe6e 100644
--- a/core/locales/locale.de.conf
+++ b/core/locales/locale.de.conf
@@ -121,10 +121,6 @@ Select Directory = In Dateien suchen
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Übereinstimmungen in Binärdatei.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Fortsetzen?
-Still searching in files... Continue waiting? = Suche noch in Dateien ... Weiter warten?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Suche in Dateien abgebrochen
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.es.conf b/core/locales/locale.es.conf
index 895a99c1..68de3735 100644
--- a/core/locales/locale.es.conf
+++ b/core/locales/locale.es.conf
@@ -121,10 +121,6 @@ Select Directory = Buscar en ficheros
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Coincidencia en fichero binario.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Continue?
-Still searching in files... Continue waiting? = Still searching in files... Continue waiting?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Find in Files aborted
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.fr.conf b/core/locales/locale.fr.conf
index ae8e826b..ec72f531 100644
--- a/core/locales/locale.fr.conf
+++ b/core/locales/locale.fr.conf
@@ -122,10 +122,6 @@ Select Directory = Rechercher dans les fichiers
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Correspondances dans un fichier binaire
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Continue?
-Still searching in files... Continue waiting? = Still searching in files... Continue waiting?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Find in Files aborted
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.it.conf b/core/locales/locale.it.conf
index dc14be61..1faf8045 100644
--- a/core/locales/locale.it.conf
+++ b/core/locales/locale.it.conf
@@ -121,10 +121,6 @@ Select Directory = Trova nei file
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Corrispondenze in un file binario.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Continue?
-Still searching in files... Continue waiting? = Still searching in files... Continue waiting?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Find in Files aborted
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.pl.conf b/core/locales/locale.pl.conf
index f48bd677..dbae0312 100644
--- a/core/locales/locale.pl.conf
+++ b/core/locales/locale.pl.conf
@@ -122,10 +122,6 @@ Select Directory = Znajdź w plikach
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Znalezione w pliku binarnym.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Kontynuować?
-Still searching in files... Continue waiting? = Wciąż trwa szukanie w plikach... Kontynuować czekanie?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Szukanie w plikach przerwane
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.ru.conf b/core/locales/locale.ru.conf
index 20218cee..a1ad36ab 100644
--- a/core/locales/locale.ru.conf
+++ b/core/locales/locale.ru.conf
@@ -121,10 +121,6 @@ Select Directory = Найти в файлах
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Соответствие в двоичном файле.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Continue?
-Still searching in files... Continue waiting? = Still searching in files... Continue waiting?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Find in Files aborted
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.sv.conf b/core/locales/locale.sv.conf
index 0d4b5d89..691dce71 100644
--- a/core/locales/locale.sv.conf
+++ b/core/locales/locale.sv.conf
@@ -121,10 +121,6 @@ Select Directory = Sök i filer
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = Binär fil matchar.
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = Continue?
-Still searching in files... Continue waiting? = Still searching in files... Continue waiting?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = Find in Files aborted
# The statusbar text shown after performing a "Replace All".
diff --git a/core/locales/locale.zh.conf b/core/locales/locale.zh.conf
index cd1f7ed0..d38fb2fb 100644
--- a/core/locales/locale.zh.conf
+++ b/core/locales/locale.zh.conf
@@ -121,10 +121,6 @@ Select Directory = 在文件中查找
# The "Find in Files" result for text found in a binary file. This result is
# shown in place of binary buffer text.
Binary file matches. = 二进制文件匹配。
-# The text displayed in a dialog when the user is prompted to continue a "Find
-# in Files" search that has taken longer than X seconds to complete.
-Continue? = 继续吗?
-Still searching in files... Continue waiting? = 仍在搜索文件... 继续等待?
# The message displayed when a "Find in Files" search is aborted by the user.
Find in Files aborted = 在文件中查找已中止
# The statusbar text shown after performing a "Replace All".
diff --git a/core/ui.lua b/core/ui.lua
index 5adbc758..21217609 100644
--- a/core/ui.lua
+++ b/core/ui.lua
@@ -99,8 +99,9 @@ ui.dialogs = setmetatable({}, {__index = function(_, k)
-- a set of command line arguments and transforming the resulting standard
-- output into Lua objects.
-- @param options Table of key-value command line options for gtdialog.
+ -- @param f Work function for progressbar dialogs.
-- @return Lua objects depending on the dialog kind
- return function(options)
+ return function(options, f)
if not options.button1 then options.button1 = _L['OK'] end
if k == 'filteredlist' and not options.width then
options.width = ui.size[1] - 2 * (CURSES and 1 or 100)
@@ -129,6 +130,9 @@ ui.dialogs = setmetatable({}, {__index = function(_, k)
if type(value) ~= 'boolean' then args[#args + 1] = value end
end
end
+ if k == 'progressbar' then
+ args[#args + 1] = assert_type(f, 'function', 2)
+ end
-- Call gtdialog, stripping any trailing newline in the standard output.
local result = ui.dialog(
k:gsub('_', '-'), table.unpack(args)):match('^(.-)\n?$')
@@ -161,7 +165,7 @@ ui.dialogs = setmetatable({}, {__index = function(_, k)
local r, g, b = result:match('^#(%x%x)(%x%x)(%x%x)$')
local bgr = r and g and b and string.format('0x%s%s%s', b, g, r) or nil
return tonumber(bgr)
- elseif k == 'fontselect' then
+ elseif k == 'fontselect' or k == 'progressbar' then
return result ~= '' and result or nil
elseif not options.string_output then
local i, value = result:match('^(%-?%d+)\n?(.*)$')
diff --git a/doc/manual.md b/doc/manual.md
index 91cb0f8b..96f588ff 100644
--- a/doc/manual.md
+++ b/doc/manual.md
@@ -720,15 +720,10 @@ cycling through results. Textadept does not support replacing in files directly.
You must "Find in Files" first, and then "Replace All" for each file containing
a result. The "Match Case", "Whole Word", and "Regex" flags still apply.
-_Warning_: currently, the [find API][] provides the only means to specify a
+_Note_: currently, the [find API][] provides the only means to specify a
file-type filter. While the default filter excludes many common binary files
and version control folders from searches, Find in Files could still scan
-unrecognized binary files or large, unwanted sub-directories. Searches also
-block Textadept from receiving additional input, making the interface
-temporarily unresponsive. By default, every 10 seconds or so, Textadept will
-prompt you to continue a "Find in Files" search, allowing you to cancel one that
-is taking too long. You can change this timeout in your
-[preferences](#Module.Preferences).
+unrecognized binary files or large, unwanted sub-directories.
![Find in Files](images/findinfiles.png)
@@ -1023,13 +1018,11 @@ curses) or by reading the [buffer API documentation][].
Many of Textadept's default modules come with configurable settings that can be
changed from your *~/.textadept/init.lua* (which is executed after those modules
are loaded). Each module's [API documentation][] lists any configurable settings
-it has. For example, in order to always hide the tab bar, shorten the "Find in
-Files" timeout prompt, disable character autopairing with typeover, strip
-trailing whitespace on save, and use C99-style line comments in C code, add the
-following to *~/.textadept/init.lua*:
+it has. For example, in order to always hide the tab bar, disable character
+autopairing with typeover, strip trailing whitespace on save, and use C99-style
+line comments in C code, add the following to *~/.textadept/init.lua*:
ui.tabs = false
- ui.find.find_in_files_timeout = 5
textadept.editing.auto_pairs = nil
textadept.editing.typeover_chars = nil
textadept.editing.strip_trailing_spaces = true
@@ -1778,16 +1771,15 @@ made to CDK are in *src/cdk.patch* and listed as follows:
* Excluded the following source files: *alphalist.c*, *button.c*, *calendar.c*,
*cdk_compat.{c,h}*, *cdk_params.c*, *cdk_test.h*, *debug.c*, *dialog.c*,
- *{d,f}scale.{c,h}*, *fslider.{c,h}*, *gen-{scale,slider}.{c,h}*,
- *get_index.c*, *get_string.c*, *graph.c*, *histogram.c*, *marquee.c*,
- *matrix.c*, *menu.c*, *popup_dialog.c*, *position.c*, *radio.c*,
- *scale.{c,h}*, *slider.{c,h}*, *swindow.c*, *template.c*,
- *u{scale,slider}.{c,h}*, *view_{file,info}.c*, and *viewer.c*.
+ *{d,f}scale.{c,h}*, *fslider.{c,h}*, *gen-scale.{c,h}*, *get_index.c*,
+ *get_string.c*, *graph.c*, *histogram.c*, *marquee.c*, *matrix.c*, *menu.c*,
+ *popup_dialog.c*, *position.c*, *radio.c*, *scale.{c,h}*, *swindow.c*,
+ *template.c*, *u{scale,slider}.{c,h}*, *view_{file,info}.c*, and *viewer.c*.
* *binding.c* utilizes libtermkey for universal input.
* *cdk.h* does not `#include` "matrix.h", "viewer.h", and any headers labeled
- "Generated headers" due to their machine-dependence. It also `#define`s
- `boolean` as `CDKboolean` on Windows platforms since the former is already
- `typedef`ed.
+ "Generated headers" due to their machine-dependence, except for "slider.h". It
+ also `#define`s `boolean` as `CDKboolean` on Windows platforms since the
+ former is already `typedef`ed.
* *cdk_config.h* no longer defines `HAVE_SETLOCALE` since Textadept handles
locale settings, no longer defines `HAVE_NCURSES_H` and `NCURSES` since
Textadept supports multiple curses implementations (not just ncurses),
@@ -2033,6 +2025,8 @@ lexers |Removed |N/A<sup>a</sup>
\_cancel_current() |Renamed |[cancel_current()][]
\_select() |Renamed |[select()][]
\_paths |Renamed |[paths][]
+**ui.find** | |
+find\_in\_files\_timeout|Removed |N/A
<sup>a</sup>Use `for name in buffer:private_lexer_call(_SCINTILLA.functions.property_names[1]):gmatch('[^\n]+') do ... end`.
@@ -2185,7 +2179,7 @@ goto\_view(n, relative) |Changed |[goto\_view][](view)
**ui.find** | |
FILTER |Renamed |[find\_in\_files\_filter][]
find\_in\_files(dir) |Changed |[find\_in\_files][](dir, filter)
-N/A |Added |[find\_in\_files\_timeout][]
+N/A |Added |find\_in\_files\_timeout
lua |Changed |[regex][]
lua\_pattern\_label\_text |Changed |[regex\_label\_text][]
**view** | |
@@ -2230,7 +2224,6 @@ MAX\_RECENT\_FILES |Renamed |max\_recent\_files
[goto\_view]: api.html#ui.goto_view
[find\_in\_files\_filter]: api.html#ui.find.find_in_files_filter
[find\_in\_files]: api.html#ui.find.find_in_files
-[find\_in\_files\_timeout]: api.html#ui.find.find_in_files_timeout
[regex]: api.html#ui.find.regex
[regex\_label\_text]: api.html#ui.find.regex_label_text
[goto\_buffer]: api.html#view.goto_buffer
diff --git a/modules/textadept/find.lua b/modules/textadept/find.lua
index bea17dd2..113a32bb 100644
--- a/modules/textadept/find.lua
+++ b/modules/textadept/find.lua
@@ -52,10 +52,6 @@ local M = ui.find
-- @field in_files_label_text (string, Write-only)
-- The text of the "In files" label.
-- This is primarily used for localization.
--- @field find_in_files_timeout (number)
--- The approximate interval in seconds between prompts for continuing an
--- "In files" search.
--- The default value is 10 seconds.
-- @field INDIC_FIND (number)
-- The find in files highlight indicator number.
-- @field _G.events.FIND_WRAPPED (string)
@@ -78,7 +74,6 @@ M.whole_word_label_text = not CURSES and _L['Whole word'] or _L['Word(F2)']
M.regex_label_text = not CURSES and _L['Regex'] or _L['Regex(F3)']
M.in_files_label_text = not CURSES and _L['In files'] or _L['Files(F4)']
-M.find_in_files_timeout = 10
M.INDIC_FIND = _SCINTILLA.next_indic_number()
-- Events.
@@ -267,16 +262,25 @@ function M.find_in_files(dir, filter)
_L['[Files Found Buffer]'],
string.format('%s %s', _L['Find:']:gsub('_', ''), M.find_entry_text))
buffer.indicator_current = M.INDIC_FIND
- local ff_buffer = buffer
- local buffer = buffer.new() -- temporary buffer
- buffer.code_page = 0
- local text, found, ref_time = M.find_entry_text, false, os.time()
- buffer.search_flags = get_flags()
+ -- Determine which files to search.
+ local filenames, utf8_filenames = {}, {}
lfs.dir_foreach(dir, function(filename)
- buffer:clear_all()
- buffer:empty_undo_buffer()
- local f = io.open(filename, 'rb')
+ filenames[#filenames + 1] = filename
+ utf8_filenames[#utf8_filenames + 1] = filename:iconv('UTF-8', _CHARSET)
+ end, filter or M.find_in_files_filters[dir] or lfs.default_filter)
+
+ -- Perform the search in a temporary buffer and print results.
+ local orig_buffer, buffer = buffer, buffer.new()
+ view:goto_buffer(orig_buffer)
+ buffer.code_page = 0 -- default is UTF-8
+ buffer.search_flags = get_flags()
+ local text, i, found = M.find_entry_text, 1, false
+ local stopped = ui.dialogs.progressbar({
+ title = string.format('%s: %s', _L['Find in Files']:gsub('_', ''), text),
+ text = utf8_filenames[i], stoppable = true
+ }, function()
+ local f = io.open(filenames[i], 'rb')
buffer:set_text(f:read('a'))
f:close()
local binary = nil -- determine lazily for performance reasons
@@ -284,40 +288,34 @@ function M.find_in_files(dir, filter)
while buffer:search_in_target(text) > -1 do
found = true
if binary == nil then binary = buffer:text_range(0, 65536):find('\0') end
- local utf8_filename = filename:iconv('UTF-8', _CHARSET)
- if not binary then
- local line_num = buffer:line_from_position(buffer.target_start)
- local line = buffer:get_line(line_num)
- ff_buffer:append_text(
- string.format('%s:%d:%s', utf8_filename, line_num + 1, line))
- local pos = ff_buffer.length - #line +
- buffer.target_start - buffer:position_from_line(line_num)
- ff_buffer:indicator_fill_range(
- pos, buffer.target_end - buffer.target_start)
- if not line:find('\n$') then ff_buffer:append_text('\n') end
- else
- ff_buffer:append_text(
- string.format('%s:1:%s\n', utf8_filename, _L['Binary file matches.']))
+ if binary then
+ _G.buffer:append_text(string.format(
+ '%s:1:%s\n', utf8_filenames[i], _L['Binary file matches.']))
break
end
+ local line_num = buffer:line_from_position(buffer.target_start)
+ local line = buffer:get_line(line_num)
+ _G.buffer:append_text(
+ string.format('%s:%d:%s', utf8_filenames[i], line_num + 1, line))
+ local pos = _G.buffer.length - #line +
+ buffer.target_start - buffer:position_from_line(line_num)
+ _G.buffer:indicator_fill_range(
+ pos, buffer.target_end - buffer.target_start)
+ if not line:find('\n$') then _G.buffer:append_text('\n') end
buffer:set_target_range(buffer.target_end, buffer.length)
end
- if os.difftime(os.time(), ref_time) >= M.find_in_files_timeout then
- local button = ui.dialogs.yesno_msgbox{
- title = _L['Continue?'],
- text = _L['Still searching in files... Continue waiting?'],
- icon = 'gtk-dialog-question', no_cancel = true
- }
- if button ~= 1 then
- ff_buffer:append_text(_L['Find in Files aborted'] .. '\n')
- return false
- end
- ref_time = os.time()
- end
- end, filter or M.find_in_files_filters[dir] or lfs.default_filter)
- if not found then ff_buffer:append_text(_L['No results found']) end
- buffer:delete() -- delete temporary buffer
- ui._print(_L['[Files Found Buffer]'], '') -- goto end, set save pos, etc.
+ buffer:clear_all()
+ buffer:empty_undo_buffer()
+ _G.buffer:goto_pos(_G.buffer.length) -- [Files Found Buffer]
+ i = i + 1
+ if i > #filenames then return nil end
+ return i * 100 / #filenames, utf8_filenames[i]
+ end)
+ buffer:close(true) -- temporary buffer
+ ui._print(
+ _L['[Files Found Buffer]'],
+ stopped and _L['Find in Files aborted'] .. '\n' or
+ not found and _L['No results found'] .. '\n' or '')
end
-- Unescapes \uXXXX sequences in the string *text* and returns the result.
diff --git a/src/Makefile b/src/Makefile
index 9706b777..aab07f49 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -143,7 +143,7 @@ cdk_objs = $(addprefix cdk-, binding.o buttonbox.o cdk.o cdk_display.o \
cdk_objs.o cdkscreen.o draw.o entry.o fselect.o \
itemlist.o label.o mentry.o popup_label.o \
scroll.o scroller.o select_file.o selection.o \
- traverse.o version.o)
+ slider.o traverse.o version.o)
# Add debugging symbols and disable optimizations when DEBUG=1.
# Note: In order to profile with gprof (-pg), do not retain symbols in LDFLAGS.
@@ -370,7 +370,7 @@ scintilla_zip = 429993cf4429.zip
lua_tgz = lua-5.3.5.tar.gz
lpeg_tgz = lpeg-1.0.2.tar.gz
lfs_zip = v1_7_0_2.zip
-gtdialog_zip = db67f8a489e8.zip
+gtdialog_zip = 6edd57eeed93.zip
cdk_tgz = cdk-5.0-20150928.tgz
termkey_tgz = libtermkey-0.20.tar.gz
win32gtk_zip = win32gtk-2.24.32.zip
@@ -410,6 +410,8 @@ cdk: cdk.patch | $(cdk_tgz)
if [ -d $@ ]; then rm -r $@; fi
mkdir $@ && tar xzf $| -C $@ && mv $@/*/* $@
mv $@/include/*.h $@
+ $@/gen-scale.sh SLIDER Slider Int int $@/gen-slider.h > $@/slider.h
+ $@/gen-scale.sh SLIDER Slider Int int $@/gen-slider.c > $@/slider.c
patch -d $@ -N -p1 < $<
$(termkey_tgz): ; $(WGET) http://www.leonerd.org.uk/code/libtermkey/$@
termkey: termkey.patch | $(termkey_tgz)
diff --git a/src/textadept.c b/src/textadept.c
index c63fd195..14ba536e 100644
--- a/src/textadept.c
+++ b/src/textadept.c
@@ -462,6 +462,7 @@ static int lfind_focus(lua_State *L) {
if (focused_entry->exitType == vNORMAL) {
f_clicked(getCDKButtonboxCurrentButton(buttonbox), NULL);
refresh_all();
+ if (toggled(in_files)) refreshCDKScreen(findbox); // splits cause trouble
}
find_entry->exitType = replace_entry->exitType = vNEVER_ACTIVATED;
activateCDKEntry(focused_entry, NULL);
@@ -569,12 +570,33 @@ static int lce_focus(lua_State *L) {
return 0;
}
+/** Runs the work function passed to `ui.dialogs.progressbar()`. */
+static char *progressbar_cb() {
+ lua_getfield(lua, LUA_REGISTRYINDEX, "ta_progress");
+ if (lua_pcall(lua, 0, 2, 0) == LUA_OK) {
+ if (lua_isnil(lua, -2)) return (lua_pop(lua, 2), NULL);
+ if (lua_isnil(lua, -1)) lua_pushliteral(lua, ""), lua_replace(lua, -2);
+ if (lua_isnumber(lua, -2)) {
+ lua_pushliteral(lua, " "), lua_insert(lua, -2),
+ lua_pushliteral(lua, "\n");
+ lua_concat(lua, 4); // "num str\n"
+ char *s = strcpy(malloc(lua_rawlen(lua, -1) + 1), lua_tostring(lua, -1));
+ return (lua_pop(lua, 1), s); // will be freed by gtdialog
+ } else lua_pop(lua, 2), lua_pushliteral(lua, "invalid return values");
+ }
+ lL_event(lua, "error", LUA_TSTRING, lua_tostring(lua, -1), -1);
+ return (lua_pop(lua, 1), NULL);
+}
+
/** `ui.dialog()` Lua function. */
static int lui_dialog(lua_State *L) {
+ GTDialogType type = gtdialog_type(luaL_checkstring(L, 1));
int i, j, k, n = lua_gettop(L) - 1, argc = n;
for (i = 2; i < n + 2; i++)
if (lua_istable(L, i)) argc += lua_rawlen(L, i) - 1;
- const char **argv = malloc((argc + 1) * sizeof(const char *));
+ if (type == GTDIALOG_PROGRESSBAR)
+ lua_pushnil(L), lua_setfield(L, LUA_REGISTRYINDEX, "ta_progress"), argc--;
+ const char *argv[argc + 1]; // not malloc since luaL_checklstring throws
for (i = 0, j = 2; j < n + 2; j++)
if (lua_istable(L, j)) {
int len = lua_rawlen(L, j);
@@ -583,11 +605,14 @@ static int lui_dialog(lua_State *L) {
argv[i++] = luaL_checkstring(L, -1);
lua_pop(L, 1);
}
+ } else if (lua_isfunction(L, j) && type == GTDIALOG_PROGRESSBAR) {
+ lua_pushvalue(L, j), lua_setfield(L, LUA_REGISTRYINDEX, "ta_progress");
+ gtdialog_set_progressbar_callback(progressbar_cb, NULL);
} else argv[i++] = luaL_checkstring(L, j);
argv[argc] = NULL;
- char *out = gtdialog(gtdialog_type(luaL_checkstring(L, 1)), argc, argv);
+ char *out = gtdialog(type, argc, argv);
lua_pushstring(L, out);
- free(out), free(argv);
+ free(out);
#if (CURSES && _WIN32)
redrawwin(scintilla_get_window(focused_view)); // needed for pdcurses
#endif
diff --git a/test/test.lua b/test/test.lua
index b884f188..78291350 100644
--- a/test/test.lua
+++ b/test/test.lua
@@ -908,6 +908,33 @@ function test_ui_dialogs_optionselect_interactive()
assert_raises(function() ui.dialogs.optionselect{items = {'foo', 'bar', 'baz'}, select = {1, 'bar'}} end, "bad argument #select[2] to 'optionselect' (number expected, got string")
end
+function test_ui_dialogs_progressbar_interactive()
+ local i = 0
+ ui.dialogs.progressbar({title = 'foo'}, function()
+ os.execute('sleep 0.1')
+ i = i + 10
+ if i > 100 then return nil end
+ return i, i .. '%'
+ end)
+
+ local stopped = ui.dialogs.progressbar({
+ title = 'foo', indeterminite = true, stoppable = true
+ }, function()
+ os.execute('sleep 0.1')
+ return 50
+ end)
+ assert(stopped, 'progressbar not stopped')
+
+ ui.update() -- allow GTK to remove callback for previous function
+ i = 0
+ ui.dialogs.progressbar({title = 'foo', stoppable = true}, function()
+ os.execute('sleep 0.1')
+ i = i + 10
+ if i > 100 then return nil end
+ return i, i <= 50 and "stop disable" or "stop enable"
+ end)
+end
+
function test_ui_dialogs_textbox_interactive()
ui.dialogs.textbox{
text = 'foo', editable = true, selected = true, monospaced_font = true