Add primary selection support (#1729)

* Add support for primary selections

* Handle primary selection in `DocView`s
This commit is contained in:
Guldoman 2024-09-13 19:31:15 +02:00 committed by GitHub
parent f5c63d8c8f
commit de118ab82a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 101 additions and 37 deletions

View File

@ -93,6 +93,13 @@ local function cut_or_copy(delete)
system.set_clipboard(full_text) system.set_clipboard(full_text)
end end
local function set_primary_selection(doc)
-- Doesn't work on Windows, so avoid spending time getting the text
if PLATFORM ~= "Windows" then
system.set_primary_selection(doc:get_selection_text())
end
end
local function split_cursor(dv, direction) local function split_cursor(dv, direction)
local new_cursors = {} local new_cursors = {}
local dv_translate = direction < 0 local dv_translate = direction < 0
@ -297,6 +304,15 @@ local commands = {
end end
end, end,
["doc:paste-primary-selection"] = function(dv, x, y)
if type(x) == "number" and type(y) == "number" then
set_cursor(dv, x, y, "set")
-- Workaround to avoid that a middle mouse drag starts selecting
dv.mouse_selecting = nil
end
dv.doc:text_input(system.get_primary_selection() or "")
end,
["doc:newline"] = function(dv) ["doc:newline"] = function(dv)
for idx, line, col in dv.doc:get_selections(false, true) do for idx, line, col in dv.doc:get_selections(false, true) do
local indent = dv.doc.lines[line]:match("^[\t ]*") local indent = dv.doc.lines[line]:match("^[\t ]*")
@ -353,6 +369,7 @@ local commands = {
["doc:select-all"] = function(dv) ["doc:select-all"] = function(dv)
dv.doc:set_selection(1, 1, math.huge, math.huge) dv.doc:set_selection(1, 1, math.huge, math.huge)
set_primary_selection(dv.doc)
-- avoid triggering DocView:scroll_to_make_visible -- avoid triggering DocView:scroll_to_make_visible
dv.last_line1 = 1 dv.last_line1 = 1
dv.last_col1 = 1 dv.last_col1 = 1
@ -365,6 +382,7 @@ local commands = {
append_line_if_last_line(line2) append_line_if_last_line(line2)
dv.doc:set_selections(idx, line2 + 1, 1, line1, 1) dv.doc:set_selections(idx, line2 + 1, 1, line1, 1)
end end
set_primary_selection(dv.doc)
end, end,
["doc:select-word"] = function(dv) ["doc:select-word"] = function(dv)
@ -373,6 +391,7 @@ local commands = {
local line2, col2 = translate.end_of_word(dv.doc, line1, col1) local line2, col2 = translate.end_of_word(dv.doc, line1, col1)
dv.doc:set_selections(idx, line2, col2, line1, col1) dv.doc:set_selections(idx, line2, col2, line1, col1)
end end
set_primary_selection(dv.doc)
end, end,
["doc:join-lines"] = function(dv) ["doc:join-lines"] = function(dv)
@ -626,6 +645,7 @@ local commands = {
local line2, col2 = dv:resolve_screen_position(x, y) local line2, col2 = dv:resolve_screen_position(x, y)
dv.mouse_selecting = { line1, col1, nil } dv.mouse_selecting = { line1, col1, nil }
dv.doc:set_selection(line2, col2, line1, col1) dv.doc:set_selection(line2, col2, line1, col1)
set_primary_selection(dv.doc)
end, end,
["doc:create-cursor-previous-line"] = function(dv) ["doc:create-cursor-previous-line"] = function(dv)
@ -696,9 +716,16 @@ local translations = {
} }
for name, obj in pairs(translations) do for name, obj in pairs(translations) do
commands["doc:move-to-" .. name] = function(dv) dv.doc:move_to(obj[name:gsub("-", "_")], dv) end commands["doc:move-to-" .. name] = function(dv)
commands["doc:select-to-" .. name] = function(dv) dv.doc:select_to(obj[name:gsub("-", "_")], dv) end dv.doc:move_to(obj[name:gsub("-", "_")], dv)
commands["doc:delete-to-" .. name] = function(dv) dv.doc:delete_to(obj[name:gsub("-", "_")], dv) end end
commands["doc:select-to-" .. name] = function(dv)
dv.doc:select_to(obj[name:gsub("-", "_")], dv)
set_primary_selection(dv.doc)
end
commands["doc:delete-to-" .. name] = function(dv)
dv.doc:delete_to(obj[name:gsub("-", "_")], dv)
end
end end
commands["doc:move-to-previous-char"] = function(dv) commands["doc:move-to-previous-char"] = function(dv)

View File

@ -393,6 +393,7 @@ keymap.add_direct {
["1lclick"] = "doc:set-cursor", ["1lclick"] = "doc:set-cursor",
["2lclick"] = { "doc:set-cursor-word", "emptyview:new-doc", "tabbar:new-doc" }, ["2lclick"] = { "doc:set-cursor-word", "emptyview:new-doc", "tabbar:new-doc" },
["3lclick"] = "doc:set-cursor-line", ["3lclick"] = "doc:set-cursor-line",
["mclick"] = "doc:paste-primary-selection",
["shift+left"] = "doc:select-to-previous-char", ["shift+left"] = "doc:select-to-previous-char",
["shift+right"] = "doc:select-to-next-char", ["shift+right"] = "doc:select-to-next-char",
["shift+up"] = "doc:select-to-previous-line", ["shift+up"] = "doc:select-to-previous-line",

View File

@ -260,6 +260,18 @@ function system.get_clipboard() end
---@param text string ---@param text string
function system.set_clipboard(text) end function system.set_clipboard(text) end
---
---Retrieve the text currently stored in the primary selection.
---
---@return string
function system.get_primary_selection() end
---
---Set the content of the primary selection.
---
---@param text string
function system.set_primary_selection(text) end
--- ---
---Get the process id of lite-xl itself. ---Get the process id of lite-xl itself.
--- ---

View File

@ -897,6 +897,28 @@ static int f_set_clipboard(lua_State *L) {
} }
static int f_get_primary_selection(lua_State *L) {
#if SDL_VERSION_ATLEAST(2, 26, 0)
char *text = SDL_GetPrimarySelectionText();
if (!text) { return 0; }
lua_pushstring(L, text);
SDL_free(text);
return 1;
#else
return 0;
#endif
}
static int f_set_primary_selection(lua_State *L) {
#if SDL_VERSION_ATLEAST(2, 26, 0)
const char *text = luaL_checkstring(L, 1);
SDL_SetPrimarySelectionText(text);
#endif
return 0;
}
static int f_get_process_id(lua_State *L) { static int f_get_process_id(lua_State *L) {
#ifdef _WIN32 #ifdef _WIN32
lua_pushinteger(L, GetCurrentProcessId()); lua_pushinteger(L, GetCurrentProcessId());
@ -1227,40 +1249,42 @@ static int f_setenv(lua_State* L) {
static const luaL_Reg lib[] = { static const luaL_Reg lib[] = {
{ "poll_event", f_poll_event }, { "poll_event", f_poll_event },
{ "wait_event", f_wait_event }, { "wait_event", f_wait_event },
{ "set_cursor", f_set_cursor }, { "set_cursor", f_set_cursor },
{ "set_window_title", f_set_window_title }, { "set_window_title", f_set_window_title },
{ "set_window_mode", f_set_window_mode }, { "set_window_mode", f_set_window_mode },
{ "get_window_mode", f_get_window_mode }, { "get_window_mode", f_get_window_mode },
{ "set_window_bordered", f_set_window_bordered }, { "set_window_bordered", f_set_window_bordered },
{ "set_window_hit_test", f_set_window_hit_test }, { "set_window_hit_test", f_set_window_hit_test },
{ "get_window_size", f_get_window_size }, { "get_window_size", f_get_window_size },
{ "set_window_size", f_set_window_size }, { "set_window_size", f_set_window_size },
{ "set_text_input_rect", f_set_text_input_rect }, { "set_text_input_rect", f_set_text_input_rect },
{ "clear_ime", f_clear_ime }, { "clear_ime", f_clear_ime },
{ "window_has_focus", f_window_has_focus }, { "window_has_focus", f_window_has_focus },
{ "raise_window", f_raise_window }, { "raise_window", f_raise_window },
{ "show_fatal_error", f_show_fatal_error }, { "show_fatal_error", f_show_fatal_error },
{ "rmdir", f_rmdir }, { "rmdir", f_rmdir },
{ "chdir", f_chdir }, { "chdir", f_chdir },
{ "mkdir", f_mkdir }, { "mkdir", f_mkdir },
{ "list_dir", f_list_dir }, { "list_dir", f_list_dir },
{ "absolute_path", f_absolute_path }, { "absolute_path", f_absolute_path },
{ "get_file_info", f_get_file_info }, { "get_file_info", f_get_file_info },
{ "get_clipboard", f_get_clipboard }, { "get_clipboard", f_get_clipboard },
{ "set_clipboard", f_set_clipboard }, { "set_clipboard", f_set_clipboard },
{ "get_process_id", f_get_process_id }, { "get_primary_selection", f_get_primary_selection },
{ "get_time", f_get_time }, { "set_primary_selection", f_set_primary_selection },
{ "sleep", f_sleep }, { "get_process_id", f_get_process_id },
{ "exec", f_exec }, { "get_time", f_get_time },
{ "fuzzy_match", f_fuzzy_match }, { "sleep", f_sleep },
{ "set_window_opacity", f_set_window_opacity }, { "exec", f_exec },
{ "load_native_plugin", f_load_native_plugin }, { "fuzzy_match", f_fuzzy_match },
{ "path_compare", f_path_compare }, { "set_window_opacity", f_set_window_opacity },
{ "get_fs_type", f_get_fs_type }, { "load_native_plugin", f_load_native_plugin },
{ "text_input", f_text_input }, { "path_compare", f_path_compare },
{ "setenv", f_setenv }, { "get_fs_type", f_get_fs_type },
{ "text_input", f_text_input },
{ "setenv", f_setenv },
{ NULL, NULL } { NULL, NULL }
}; };