From 8160ad061328dfd40696b1c36c8aa911062cf8a4 Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Sun, 1 Feb 2026 04:04:55 -0800 Subject: move string seek/transform operations to util --- rt.lua | 143 +++++++++++++-------------------------------------------------- util.lua | 102 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 114 deletions(-) diff --git a/rt.lua b/rt.lua index da6c238..6b2c09d 100644 --- a/rt.lua +++ b/rt.lua @@ -535,173 +535,88 @@ function rt.open_option_info(opt) end end -function rt.search_text_insert_char(ev) - if ev.event ~= 'down' and ev.event ~= 'repeat' then +local function search_text_transform(f, ...) + local menu = state:menu() + local str, pos = f(menu.search_text, menu.search_cursor, ...) + if not str then return end - local menu = state:menu() - menu:set_search_text( - menu.search_text:sub(1, menu.search_cursor - 1) .. - ev.key_text .. - menu.search_text:sub(menu.search_cursor), - menu.search_cursor + #ev.key_text) + menu:set_search_text(str, pos) osd:dirty() end -function rt.search_text_del_prev_char() - local menu = state:menu() - if menu.search_cursor <= 1 then +function rt.search_text_insert_char(ev) + if ev.event ~= 'down' and ev.event ~= 'repeat' then return end - local pos = util.utf8_seek(menu.search_text, menu.search_cursor, -1) - menu:set_search_text( - menu.search_text:sub(1, pos - 1) .. - menu.search_text:sub(menu.search_cursor), - pos) - osd:dirty() + search_text_transform(util.str_insert_char, ev.key_text) end -function rt.search_text_del_next_char() - local menu = state:menu() - if menu.search_cursor > #menu.search_text then - return - end +function rt.search_text_del_prev_char() + search_text_transform(util.str_del_prev_char) +end - menu:set_search_text( - menu.search_text:sub(1, menu.search_cursor - 1) .. - menu.search_text:sub(util.utf8_seek( - menu.search_text, menu.search_cursor, 1))) - osd:dirty() +function rt.search_text_del_next_char() + search_text_transform(util.str_del_next_char) end function rt.search_text_del_prev_word() - local menu = state:menu() - if menu.search_cursor <= 1 then - return - end - - local pos = menu.search_text:sub(1, menu.search_cursor - 1):match( - '()%S*%s*$') - menu:set_search_text( - menu.search_text:sub(1, pos - 1) .. - menu.search_text:sub(menu.search_cursor), - pos) - osd:dirty() + search_text_transform(util.str_del_prev_word) end function rt.search_text_del_next_word() - local menu = state:menu() - if menu.search_cursor > #menu.search_text then - return - end - - local pos = menu.search_text:match('%s*%S*()', menu.search_cursor) - menu:set_search_text( - menu.search_text:sub(1, menu.search_cursor - 1) .. - menu.search_text:sub(pos)) - osd:dirty() + search_text_transform(util.str_del_next_word) end function rt.search_text_del_to_start() - local menu = state:menu() - if menu.search_cursor <= 1 then - return - end - - menu:set_search_text(menu.search_text:sub(menu.search_cursor), 1) - osd:dirty() + search_text_transform(util.str_del_to_start) end function rt.search_text_del_to_end() - local menu = state:menu() - if menu.search_cursor > #menu.search_text then - return - end - - menu:set_search_text(menu.search_text:sub(1, menu.search_cursor - 1)) - osd:dirty() + search_text_transform(util.str_del_to_end) end function rt.search_text_transpose_chars() - local menu = state:menu() - if menu.search_cursor <= 1 then - return - end - - local pos = util.utf8_seek(menu.search_text, menu.search_cursor, 1) - local cp2 = util.utf8_seek(menu.search_text, pos, -1) - if cp2 <= 1 then - return - end - local cp1 = util.utf8_seek(menu.search_text, cp2, -1) - - menu:set_search_text( - menu.search_text:sub(1, cp1 - 1) .. - menu.search_text:sub(cp2, pos - 1) .. - menu.search_text:sub(cp1, cp2 - 1) .. - menu.search_text:sub(pos), - pos) - osd:dirty() + search_text_transform(util.str_transpose_chars) end function rt.search_text_transpose_words() - local menu = state:menu() - if menu.search_cursor <= 1 then - return - end - - local pos = menu.search_text:match('%s*%S*()', menu.search_cursor) - local pre, w1, sp, w2 = menu.search_text:sub(1, pos - 1):match( - '^(.-)(%S+)(%s+)(%S+%s*)$') - if not pre then - return - end - - menu:set_search_text( - pre .. w2 .. sp .. w1 .. menu.search_text:sub(pos), - pos) - osd:dirty() + search_text_transform(util.str_transpose_words) end -local function set_search_cursor(pos) +local function search_cursor_move(f) + local menu = state:menu() + local pos = f(menu.search_text, menu.search_cursor) + if state:menu():set_search_cursor(pos) then osd:dirty() end end function rt.search_cursor_prev_char() - local menu = state:menu() - set_search_cursor(util.utf8_seek( - menu.search_text, menu.search_cursor, -1)) + search_cursor_move(util.str_seek_prev_char) end function rt.search_cursor_next_char() - local menu = state:menu() - set_search_cursor(util.utf8_seek( - menu.search_text, menu.search_cursor, 1)) + search_cursor_move(util.str_seek_next_char) end function rt.search_cursor_prev_word() - local menu = state:menu() - set_search_cursor( - menu.search_text:sub(1, menu.search_cursor - 1):match( - '()%S*%s*$')) + search_cursor_move(util.str_seek_prev_word) end function rt.search_cursor_next_word() - local menu = state:menu() - set_search_cursor( - menu.search_text:match('%s*%S*()', menu.search_cursor)) + search_cursor_move(util.str_seek_next_word) end function rt.search_cursor_start() - set_search_cursor(1) + search_cursor_move(function() return 1 end) end function rt.search_cursor_end() - set_search_cursor(#state:menu().search_text + 1) + search_cursor_move(function(str) return #str + 1 end) end function rt.start_search() diff --git a/util.lua b/util.lua index 04e1bf6..99bba7b 100644 --- a/util.lua +++ b/util.lua @@ -125,4 +125,106 @@ function util.stable_kmerge(t, u, k) return res end +function util.str_seek_prev_char(str, pos) + return util.utf8_seek(str, pos, -1) +end + +function util.str_seek_next_char(str, pos) + return util.utf8_seek(str, pos, 1) +end + +function util.str_seek_prev_word(str, pos) + return str:sub(1, pos - 1):match('()%S*%s*$') +end + +function util.str_seek_next_word(str, pos) + return str:match('%s*%S*()', pos) +end + +function util.str_insert_char(str, pos, ch) + return str:sub(1, pos - 1) .. ch .. str:sub(pos), pos + #ch +end + +function util.str_del_prev_char(str, pos) + if pos <= 1 then + return + end + + local npos = util.utf8_seek(str, pos, -1) + return str:sub(1, npos - 1) .. str:sub(pos), npos +end + +function util.str_del_next_char(str, pos) + if pos > #str then + return + end + + return str:sub(1, pos - 1) .. str:sub(util.utf8_seek(str, pos, 1)), pos +end + +function util.str_del_prev_word(str, pos) + if pos <= 1 then + return + end + + local npos = str:sub(1, pos - 1):match('()%S*%s*$') + return str:sub(1, npos - 1) .. str:sub(pos), npos +end + +function util.str_del_next_word(str, pos) + if pos > #str then + return + end + + return str:sub(1, pos - 1) .. str:sub(str:match('%s*%S*()', pos)), pos +end + +function util.str_del_to_start(str, pos) + if pos <= 1 then + return + end + + return str:sub(pos), 1 +end + +function util.str_del_to_end(str, pos) + if pos > #str then + return + end + + return str:sub(1, pos - 1), pos +end + +function util.str_transpose_chars(str, pos) + if pos <= 1 then + return + end + + local npos = util.utf8_seek(str, pos, 1) + local cp2 = util.utf8_seek(str, npos, -1) + if cp2 <= 1 then + return + end + local cp1 = util.utf8_seek(str, cp2, -1) + + return str:sub(1, cp1 - 1) .. str:sub(cp2, npos - 1) .. + str:sub(cp1, cp2 - 1) .. str:sub(npos), + npos +end + +function util.str_transpose_words(str, pos) + if pos <= 1 then + return + end + + local npos = str:match('%s*%S*()', pos) + local pre, w1, sp, w2 = str:sub(1, npos - 1):match( + '^(.-)(%S+)(%s+)(%S+%s*)$') + if not pre then + return + end + + return pre .. w2 .. sp .. w1 .. str:sub(npos), npos +end + return util -- cgit v1.2.3-70-g09d2