Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some refactor on hop #58

Merged
merged 16 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions doc/hop.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*hop.txt* For Neovim version 0.9 Last change: 2023 Sep 11
*hop.txt* For Neovim version 0.9 Last change: 2023 Nov 8

__
/ /_ ____ ____
Expand All @@ -7,7 +7,7 @@
/_/ /_/\____/ .___/
/_/
· Neovim motions on speed! ·
v2.3.0
v2.5.0

==============================================================================
CONTENTS *hop-contents*
Expand Down Expand Up @@ -209,7 +209,7 @@ creates a variant of the command that will only run for the current line.
You can configure the position of the paste relative to the jump target by
using the `hint_offset` option.

This is akin to calling the |hop.paste_char1| Lua Function
This is akin to calling the |hop-yank.paste_char1| Lua Function
`:HopYankChar1` *:HopYankChar1*
`:HopYankChar1BC` *:HopYankChar1BC*
`:HopYankChar1AC` *:HopYankChar1AC*
Expand All @@ -221,13 +221,13 @@ creates a variant of the command that will only run for the current line.
`hop.hop_char1` without jumping to bounds.
range is (inclusive,inclusive).

This is akin to calling the |hop.yank_char1| Lua Function
This is akin to calling the |hop-yank.yank_char1| Lua Function

`:HopNodes` *:HopNodes*

Hint all Treesitter nodes surranding the node on the cursor position.

This is akin to calling the |hop.hint_nodes| Lua Function
This is akin to calling the |hop-treesitter.hint_nodes| Lua Function
*hop-lua-api*
Lua API~

Expand All @@ -245,8 +245,8 @@ unstable.
`hop.jump_target` Core module used to create jump targets.
`hop.perm` Permutation functions. Permutations are used as labels for
the hints.
`hop.yank` Yank and paste functions
`hop.treesitter` Parse buffer language tree
`hop-yank.yank` Yank and paste functions
`hop-treesitter.treesitter` Parse buffer language tree

Main API~

Expand Down Expand Up @@ -368,7 +368,7 @@ Most of the functions and values you need to know about are in `hop`.
Arguments:~
{opts} Hop options.

`hop.hint_nodes(`{opts}`)` *hop.hint_nodes*
`hop-treesitter.hint_nodes(`{opts}`)` *hop-treesitter.hint_nodes*
Hint all Treesitter nodes surranding the node on the cursor position.

Arguments:~
Expand Down Expand Up @@ -730,6 +730,13 @@ below.
Defaults:~
`teasing = true`

`virtual_cursor` *hop-config-virtual_cursor*
Creates a virtual cursor in place of actual cursor when hop waits for
user input to indicate the active window.

Defaults:~
`virtual_cursor = true`

`jump_on_sole_occurrence` *hop-config-jump_on_sole_occurrence*
Immediately jump without displaying hints if only one occurrence exists.

Expand Down
18 changes: 18 additions & 0 deletions lua/hop-treesitter/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
local M = {}
M.opts = {}

M.hint_nodes = function(opts)
local hop = require('hop')

opts = setmetatable(opts or {}, { __index = M.opts })
hop.hint_with(require('hop-treesitter.treesitter').nodes(), opts)
end

function M.register(opts)
M.opts = opts
vim.api.nvim_create_user_command('HopNodes', function()
M.hint_nodes({})
end, {})
end

return M
8 changes: 4 additions & 4 deletions lua/hop/treesitter.lua → lua/hop-treesitter/treesitter.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local jump_targets = require('hop.jump_target')
local jump_target = require('hop.jump_target')

local T = {}

Expand All @@ -9,7 +9,7 @@ T.nodes = function()
---@return Locations
return function(opts)
local Locations = T.parse(opts.ignore_injections)
jump_targets.sort_indirect_jump_targets(Locations.indirect_jump_targets, opts)
jump_target.sort_indirect_jump_targets(Locations.indirect_jump_targets, opts)
return Locations
end
end
Expand All @@ -21,7 +21,7 @@ end
---@return boolean
local function duplicate(targets, row, col)
for _, t in pairs(targets) do
if t.line == row and t.column == col + 1 then
if t.cursor.row == row and t.cursor.col == col then
return true
end
end
Expand All @@ -48,7 +48,7 @@ T.parse = function(ignore_injections)

local len = #locations.jump_targets + 1
-- Increment column to convert it to 1-index
locations.jump_targets[len] = { buffer = 0, line = row, column = col + 1, length = 0, window = 0 }
locations.jump_targets[len] = { buffer = 0, cursor = { row = row + 1, col = col }, length = 0, window = 0 }
locations.indirect_jump_targets[len] = { index = len, score = len }
end

Expand Down
121 changes: 121 additions & 0 deletions lua/hop-yank/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
local M = {}
M.opts = {}

local defaults = {
yank_register = '',
}

---@param opts Options
M.yank_char1 = function(opts)
local hop = require('hop')
local jump_regex = require('hop.jump_regex')
local yank = require('hop-yank.yank')

opts = setmetatable(opts or {}, { __index = M.opts })

if opts.multi_windows then
opts.multi_windows = false
vim.notify('Cannot use yank across multiple windows', vim.log.levels.WARN)
end

local prompts = {
'Yank start pattern: ',
'Yank end pattern: ',
}

---@type JumpTarget[]
local targets = {}
for key, prompt in pairs(prompts) do
local c = hop.get_input_pattern(prompt, 1)
if not c or c == '' then
return
end

hop.hint_with_regex(jump_regex.regex_by_case_searching(c, true, opts), opts, function(jt)
targets[key] = jt
end)
end

if targets[1] == nil or targets[2] == nil then
return
end

local text = yank.get_text(targets[1], targets[2])
if #text == 0 or text[1] == '' then
return
end

yank.yank_to(text, opts.yank_register)
end

---@param opts Options
M.paste_char1 = function(opts)
local hop = require('hop')
local jump_target = require('hop.jump_target')
local jump_regex = require('hop.jump_regex')

opts = setmetatable(opts or {}, { __index = M.opts })

local c = hop.get_input_pattern('Paste 1 char', 1)
if not c or c == '' then
return
end

---@param jt JumpTarget|nil
hop.hint_with_regex(jump_regex.regex_by_case_searching(c, true, opts), opts, function(jt)
local target = jt

if target == nil then
return
end

jump_target.move_jump_target(target, 0, opts.hint_offset)

require('hop-yank.yank').paste_from(target, opts.yank_register)
end)
end

function M.register(opts)
local direction = require('hop.hint').HintDirection

M.opts = opts
if not M.opts.yank_register then
M.opts.yank_register = defaults.yank_register
end

local user_command = vim.api.nvim_create_user_command
local commands = {
HopYankChar1 = M.yank_char1,
HopPasteChar1 = M.paste_char1,
}

for label, hint in pairs(commands) do
user_command(label, hint, {})

user_command(label .. 'BC', function()
hint({ direction = direction.BEFORE_CURSOR })
end, {})

user_command(label .. 'AC', function()
hint({ direction = direction.AFTER_CURSOR })
end, {})

user_command(label .. 'CurrentLine', function()
hint({ current_line_only = true })
end, {})

user_command(label .. 'CurrentLineBC', function()
hint({ direction = direction.BEFORE_CURSOR, current_line_only = true })
end, {})

user_command(label .. 'CurrentLineAC', function()
hint({ direction = direction.AFTER_CURSOR, current_line_only = true })
end, {})

user_command(label .. 'MW', function()
hint({ multi_windows = true })
end, {})
end
end

return M
22 changes: 18 additions & 4 deletions lua/hop/yank.lua → lua/hop-yank/yank.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,24 @@ M.paste_from = function(target, register)
end

local replacement = vim.split(text, '\n', { trimempty = true })
vim.api.nvim_buf_set_text(0, target.line, target.column, target.line, target.column, replacement)
vim.api.nvim_buf_set_text(
target.buffer,
target.cursor.row - 1,
target.cursor.col + 1,
target.cursor.row - 1,
target.cursor.col + 1,
replacement
)
end

--- checks the range bounds and when end is before the start swaps theme
---@param start_range JumpTarget
---@param end_range JumpTarget
---@return JumpTarget,JumpTarget
local function check_bounds(start_range, end_range)
if start_range.line < end_range.line then
if start_range.cursor.row < end_range.cursor.row then
return start_range, end_range
elseif start_range.line == end_range.line and start_range.column <= end_range.column then
elseif start_range.cursor.row == end_range.cursor.row and start_range.cursor.col <= end_range.cursor.col then
return start_range, end_range
end
return end_range, start_range
Expand All @@ -39,7 +46,14 @@ end
---@return string[]
M.get_text = function(start_range, end_range)
start_range, end_range = check_bounds(start_range, end_range)
return vim.api.nvim_buf_get_text(0, start_range.line, start_range.column - 1, end_range.line, end_range.column, {})
return vim.api.nvim_buf_get_text(
0,
start_range.cursor.row - 1,
start_range.cursor.col,
end_range.cursor.row - 1,
end_range.cursor.col + 1,
{}
)
end

return M
5 changes: 3 additions & 2 deletions lua/hop/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ M.perm_method = require('hop.perm').TrieBacktrackFilling
M.reverse_distribution = false
M.x_bias = 10
M.teasing = true
M.virtual_cursor = false
M.jump_on_sole_occurrence = true
M.case_insensitive = true
M.create_hl_autocmd = true
Expand All @@ -20,10 +21,10 @@ M.uppercase_labels = false
M.multi_windows = false
M.ignore_injections = false
M.hint_position = hint.HintPosition.BEGIN ---@type HintPosition
M.hint_offset = 0
M.hint_offset = 0 ---@type WindowCell
M.hint_type = hint.HintType.OVERLAY ---@type HintType
M.excluded_filetypes = {}
M.yank_register = ''
M.match_mappings = {}
M.extensions = { 'hop-yank', 'hop-treesitter' }

return M
Loading