local T = {} -- Returns visually selected text and cursor column where selection starts. -- Works with selections over multiple lines, but will only return the -- starting line, as well as the starting line's text. function T.get_current_selection() local line, start_col, end_col = vim.fn.getpos("'<")[2], vim.fn.getpos("'<")[3], vim.fn.getpos("'>")[3] local selection = T.get_line(line):sub(start_col, end_col) return selection, start_col end -- Returns word currently under cursor and cursor column where -- the word begins. -- If big argument resolves to true, it will get the whitespace -- delimited word, otherwise the vim specified wordboundary word. function T.get_current_word(big) local pattern = [[\k]] if not big then pattern = [[\S]] end local cur_col = vim.api.nvim_win_get_cursor(0)[2] local line = T.get_line() local word_before_cur = vim.fn.matchstrpos(line:sub(1, cur_col + 1), pattern .. "*$") local word_start_col = word_before_cur[2] + 1 word_before_cur = word_before_cur[1] local word_after_cur = vim.fn.matchstr(line:sub(cur_col + 1), "^" .. pattern .. "*"):sub(2) return word_before_cur .. word_after_cur, word_start_col end -- Returns the link currently under cursor, roughly the vim equivalent of yiW. -- Works for links containing spaces in their text or reference link. function T.get_link_under_cursor(links, curpos) for _, link in pairs(links) do if link.startpos <= curpos + 1 and link.endpos > curpos then return link end end return nil end -- Returns the next link of the current line from the cursor onwards. function T.get_next_link_on_line(links, curpos) local nearestpos = math.huge local nearestlink for _, link in pairs(links) do if link.endpos > curpos and link.endpos < nearestpos then nearestpos = link.endpos nearestlink = link end end return nearestlink end -- Sanitizes the string before replacement, taking care of escaping any -- characters that lua uses to signify patterns. local function replace(str, patt, repl, n) patt = string.gsub(patt, "[%(%)%.%+%-%*%?%[%]%^%$%%]", "%%%1") repl = string.gsub(repl, "[%%]", "%%%%") return string.gsub(str, patt, repl, n) end -- Replaces the input text on the current line with new text. -- Takes an optional initial column on which the text to be replaced starts, -- which can prevent falsely substituting the wrong text fragment if an -- identical one exists earlier on the line. (E.g. I want to replace the -- second 'test' in 'test test 1 2 3'). function T.replace_text_in_current_line(text, new_text, start_col) local line_full = T.get_line() local line_edited if start_col then line_edited = line_full:sub(1, start_col - 1) .. replace(line_full:sub(start_col), text, new_text, 1) else line_edited = replace(line_full, text, new_text, 1) end return line_edited end --- Return editor line contents. -- Returns the content of the line number passed in or the currently active -- line if no number passed in. Lines are, different to the neovim function, -- *one-indexed*. --- @param linenr number --- @return string function T.get_line(linenr) if linenr then return vim.api.nvim_buf_get_lines(0, linenr - 1, linenr, false)[1] end return vim.api.nvim_get_current_line() end return T