mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 07:10:06 +08:00
chore(hop.nvim): update bundle hop.nvim
close https://github.com/SpaceVim/SpaceVim/issues/4837
update to: 90db1b2c61
This commit is contained in:
parent
1d4406b5ca
commit
4d8d77fb5e
2
bundle/hop.nvim/LICENSE
vendored
2
bundle/hop.nvim/LICENSE
vendored
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2021, Dimitri Sabadie <dimitri.sabadie@gmail.com>
|
||||
Copyright (c) 2021-2022, Dimitri Sabadie <dimitri.sabadie@gmail.com>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
201
bundle/hop.nvim/README.md
vendored
201
bundle/hop.nvim/README.md
vendored
@ -6,7 +6,17 @@
|
||||
/_/
|
||||
· Neovim motions on speed! ·
|
||||
|
||||
[![](https://img.shields.io/badge/matrix-join%20the%20speed!-blueviolet)](https://matrix.to/#/#hop.nvim:matrix.org)
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/github/issues/phaazon/hop.nvim?color=cyan&style=for-the-badge"/>
|
||||
<img src="https://img.shields.io/github/issues-pr/phaazon/hop.nvim?color=green&style=for-the-badge"/>
|
||||
<img src="https://img.shields.io/github/contributors-anon/phaazon/hop.nvim?color=blue&style=for-the-badge"/>
|
||||
<img src="https://img.shields.io/github/last-commit/phaazon/hop.nvim?style=for-the-badge"/>
|
||||
<img src="https://img.shields.io/github/v/tag/phaazon/hop.nvim?color=pink&label=release&style=for-the-badge"/>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#using-vim-plug">Install</a> · <a href="https://github.com/phaazon/hop.nvim/wiki">Wiki</a> · <a href="https://github.com/phaazon/hop.nvim/wiki/Screenshots">Screenshots</a> · <a href="https://matrix.to/#/#hop.nvim:matrix.org">Discuss</a>
|
||||
</p>
|
||||
|
||||
**Hop** is an [EasyMotion]-like plugin allowing you to jump anywhere in a
|
||||
document with as few keystrokes as possible. It does so by annotating text in
|
||||
@ -15,19 +25,14 @@ represents a key to type to jump to the annotated text. Most of the time,
|
||||
those sequences’ lengths will be between 1 to 3 characters, making every jump
|
||||
target in your document reachable in a few keystrokes.
|
||||
|
||||
<p align="center">
|
||||
<img src="https://user-images.githubusercontent.com/506592/176885253-5f618593-77c5-4843-9101-a9de30f0a022.png"/>
|
||||
</p>
|
||||
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [Motivation](#motivation)
|
||||
* [Features](#features)
|
||||
* [Word mode (`:HopWord`)](#word-mode-hopword)
|
||||
* [Line mode (`:HopLine`)](#line-mode-hopline)
|
||||
* [1-char mode (`:HopChar1`)](#1-char-mode-hopchar1)
|
||||
* [2-char mode (`:HopChar2`)](#2-char-mode-hopchar2)
|
||||
* [Pattern mode (`:HopPattern`)](#pattern-mode-hoppattern)
|
||||
* [Visual extend](#visual-extend)
|
||||
* [Jump on sole occurrence](#jump-on-sole-occurrence)
|
||||
* [Use as operator motion](#use-as-operator-motion)
|
||||
* [Inclusive / exclusive motion](#inclusive--exclusive-motion)
|
||||
* [Getting started](#getting-started)
|
||||
* [Installation](#installation)
|
||||
* [Important note about versioning](#important-note-about-versioning)
|
||||
@ -36,8 +41,6 @@ target in your document reachable in a few keystrokes.
|
||||
* [Nightly users](#nightly-users)
|
||||
* [Usage](#usage)
|
||||
* [Keybindings](#keybindings)
|
||||
* [Configuration](#configuration)
|
||||
* [Extension](#extension)
|
||||
* [Chat](#chat)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
@ -66,83 +69,18 @@ Neovim.
|
||||
|
||||
# Features
|
||||
|
||||
- [x] Go to any word in the current buffer.
|
||||
- [x] Go to any character in the current buffer.
|
||||
- [x] Go to any bigrams in the current buffer.
|
||||
- [x] Use Hop cross windows with multi-windows support.
|
||||
- [x] Make an arbitrary search akin to <kbd>/</kbd> and go to any occurrences.
|
||||
- [x] Go to any line.
|
||||
- [x] Visual extend mode, which allows you to extend a visual selection by hopping elsewhere in the document.
|
||||
- [x] Use it with commands like `d`, `c`, `y` to delete/change/yank up to your new cursor position.
|
||||
- [x] Support a wide variety of user configuration options, among the possibility to alter the behavior of commands
|
||||
to hint only before or after the cursor, for the current line, change the dictionary keys to use for the labels,
|
||||
jump on sole occurrence, etc.
|
||||
- [x] Extensible: provide your own jump targets and create Hop extensions!
|
||||
|
||||
## Word mode (`:HopWord`)
|
||||
|
||||
This mode highlights all the recognized words in the visible part of the buffer and allows you to jump to any.
|
||||
|
||||
![](https://phaazon.net/media/uploads/hop_word_mode.gif)
|
||||
|
||||
## Line mode (`:HopLine`)
|
||||
|
||||
This mode highlights the beginnings of each line in the visible part of the buffer for quick line hopping.
|
||||
|
||||
![](https://phaazon.net/media/uploads/hop_line_mode.gif)
|
||||
|
||||
## 1-char mode (`:HopChar1`)
|
||||
|
||||
This mode expects the user to type a single character. That character will then be highlighted in the visible part of
|
||||
the buffer, allowing to jump to any of its occurrence. This mode is especially useful to jump to operators, punctuations
|
||||
or any symbols not recognized as parts of words.
|
||||
|
||||
![](https://phaazon.net/media/uploads/hop_char1_mode.gif)
|
||||
|
||||
## 2-char mode (`:HopChar2`)
|
||||
|
||||
A variant of the 1-char mode, this mode exacts the user to type two characters, representing a _bigram_ (they follow
|
||||
each other, in order). The bigram occurrences in the visible part of the buffer will then be highlighted for you to jump
|
||||
to any.
|
||||
|
||||
![](https://phaazon.net/media/uploads/hop_char2_mode.gif)
|
||||
|
||||
Note that it’s possible to _fallback to 1-char mode_ if you hit a special key as second key. This key can be controlled
|
||||
via the user configuration. `:h hop-config-char2_fallback_key`.
|
||||
|
||||
## Pattern mode (`:HopPattern`)
|
||||
|
||||
Akin to `/`, this mode prompts you for a pattern (regex) to search. Occurrences will be highlighted, allowing you to
|
||||
jump to any.
|
||||
|
||||
![](https://phaazon.net/media/uploads/hop_pattern_mode.gif)
|
||||
|
||||
## Visual extend
|
||||
|
||||
If you call any Hop commands / Lua functions from one of the visual modes, the visual selection will be extended.
|
||||
|
||||
![](https://phaazon.net/media/uploads/hop_visual_extend.gif)
|
||||
|
||||
## Jump on sole occurrence
|
||||
|
||||
If only a single occurrence is visible in the buffer, Hop will automatically jump to it without requiring pressing any
|
||||
extra key.
|
||||
|
||||
![](https://phaazon.net/media/uploads/hop_sole_occurrence.gif)
|
||||
|
||||
## Use as operator motion
|
||||
|
||||
You can use Hop with any command that expects a motion, such as `d`, `y`, `c`, and it does what you would expect:
|
||||
Delete/yank/change the document up to the new cursor position.
|
||||
|
||||
## Inclusive / exclusive motion
|
||||
|
||||
By default, Hop will operate in exclusive mode, which is similar to what you get with `t`: deleting from the cursor
|
||||
position up to the next `)` (without deleting the `)`), which is normally done with `dt)`. However, if you want to be
|
||||
inclusive (i.e. delete the `)`, which is `df)` in vanilla), you can set the `inclusive_jump` option to `true`.
|
||||
|
||||
Some limitations currently exist, requiring `virtualedit` special settings. `:h hop-config-inclusive_jump` for more
|
||||
information.
|
||||
- Go to any word in the current buffer (`:HopWord`).
|
||||
- Go to any character in the current buffer (`:HopChar1`).
|
||||
- Go to any bigrams in the current buffer (`:HopChar2`).
|
||||
- Make an arbitrary search akin to <kbd>/</kbd> and go to any occurrences (`:HopPattern`).
|
||||
- Go to any line and any line start (`:HopLine`, `:HopLineStart`).
|
||||
- Go to anywhere (`:HopAnywhere`).
|
||||
- Use Hop cross windows with multi-windows support (`:Hop*MW`).
|
||||
- Use it with commands like `v`, `d`, `c`, `y` to visually select/delete/change/yank up to your new cursor position.
|
||||
- Support a wide variety of user configuration options, among the possibility to alter the behavior of commands
|
||||
to hint only before or after the cursor (`:Hop*BC`, `:Hop*AC`), for the current line (`:Hop*CurrentLine`),
|
||||
change the dictionary keys to use for the labels, jump on sole occurrence, etc.
|
||||
- Extensible: provide your own jump targets and create Hop extensions!
|
||||
|
||||
# Getting started
|
||||
|
||||
@ -184,7 +122,7 @@ Plug 'phaazon/hop.nvim'
|
||||
```lua
|
||||
use {
|
||||
'phaazon/hop.nvim',
|
||||
branch = 'v1', -- optional but strongly recommended
|
||||
branch = 'v2', -- optional but strongly recommended
|
||||
config = function()
|
||||
-- you can configure Hop the way you like here; see :h hop-config
|
||||
require'hop'.setup { keys = 'etovxqpdygfblzhckisuran' }
|
||||
@ -199,29 +137,7 @@ the last one**. If you are not, then you are exposed to compatibility issues / b
|
||||
|
||||
# Usage
|
||||
|
||||
A bunch of vim commands are available to get your fingers wrapped around **Hop** quickly:
|
||||
|
||||
- `:HopWord`: hop around by highlighting words.
|
||||
- `:HopPattern`: hop around by matching against a pattern (as with `/`).
|
||||
- `:HopChar1`: type a single key and hop to any occurrence of that key in the document.
|
||||
- `:HopChar2`: type a bigram (two keys) and hop to any occurrence of that bigram in the document.
|
||||
- `:HopLine`: jump to any visible line in your buffer.
|
||||
- `:HopLineStart`: jump to any visible first non-whitespace character of each line in your buffer.
|
||||
|
||||
Most of these commands have variant to jump before / after the cursor, and on the current line. For instance,
|
||||
`:HopChar1CurrentLineAC` is a form of `f` (Vim native motion) using Hop.
|
||||
|
||||
If you would rather use the Lua API, you can test it via the command prompt:
|
||||
|
||||
```vim
|
||||
:lua require'hop'.hint_words()
|
||||
```
|
||||
|
||||
For a more complete user guide and help pages:
|
||||
|
||||
```vim
|
||||
:help hop
|
||||
```
|
||||
See the [wiki](https://github.com/phaazon/hop.nvim/wiki).
|
||||
|
||||
# Keybindings
|
||||
|
||||
@ -231,53 +147,22 @@ If you want to create a key binding from within Lua:
|
||||
|
||||
```lua
|
||||
-- place this in one of your configuration file(s)
|
||||
vim.api.nvim_set_keymap('n', 'f', "<cmd>lua require'hop'.hint_char1({ direction = require'hop.hint'.HintDirection.AFTER_CURSOR, current_line_only = true })<cr>", {})
|
||||
vim.api.nvim_set_keymap('n', 'F', "<cmd>lua require'hop'.hint_char1({ direction = require'hop.hint'.HintDirection.BEFORE_CURSOR, current_line_only = true })<cr>", {})
|
||||
vim.api.nvim_set_keymap('o', 'f', "<cmd>lua require'hop'.hint_char1({ direction = require'hop.hint'.HintDirection.AFTER_CURSOR, current_line_only = true, inclusive_jump = true })<cr>", {})
|
||||
vim.api.nvim_set_keymap('o', 'F', "<cmd>lua require'hop'.hint_char1({ direction = require'hop.hint'.HintDirection.BEFORE_CURSOR, current_line_only = true, inclusive_jump = true })<cr>", {})
|
||||
vim.api.nvim_set_keymap('', 't', "<cmd>lua require'hop'.hint_char1({ direction = require'hop.hint'.HintDirection.AFTER_CURSOR, current_line_only = true })<cr>", {})
|
||||
vim.api.nvim_set_keymap('', 'T', "<cmd>lua require'hop'.hint_char1({ direction = require'hop.hint'.HintDirection.BEFORE_CURSOR, current_line_only = true })<cr>", {})
|
||||
vim.api.nvim_set_keymap('n', '<leader>e', "<cmd> lua require'hop'.hint_words({ hint_position = require'hop.hint'.HintPosition.END })<cr>", {})
|
||||
vim.api.nvim_set_keymap('v', '<leader>e', "<cmd> lua require'hop'.hint_words({ hint_position = require'hop.hint'.HintPosition.END })<cr>", {})
|
||||
vim.api.nvim_set_keymap('o', '<leader>e', "<cmd> lua require'hop'.hint_words({ hint_position = require'hop.hint'.HintPosition.END, inclusive_jump = true })<cr>", {})
|
||||
local hop = require('hop')
|
||||
local directions = require('hop.hint').HintDirection
|
||||
vim.keymap.set('', 'f', function()
|
||||
hop.hint_char1({ direction = directions.AFTER_CURSOR, current_line_only = true })
|
||||
end, {remap=true})
|
||||
vim.keymap.set('', 'F', function()
|
||||
hop.hint_char1({ direction = directions.BEFORE_CURSOR, current_line_only = true })
|
||||
end, {remap=true})
|
||||
vim.keymap.set('', 't', function()
|
||||
hop.hint_char1({ direction = directions.AFTER_CURSOR, current_line_only = true, hint_offset = -1 })
|
||||
end, {remap=true})
|
||||
vim.keymap.set('', 'T', function()
|
||||
hop.hint_char1({ direction = directions.BEFORE_CURSOR, current_line_only = true, hint_offset = 1 })
|
||||
end, {remap=true})
|
||||
```
|
||||
|
||||
# Configuration
|
||||
|
||||
You can configure Hop via several different mechanisms:
|
||||
|
||||
- _Global configuration_ uses the Lua `setup` API (`:h hop.setup`). This allows you to setup global options that will be
|
||||
used by all Hop Lua functions as well as the vim commands (e.g. `:HopWord`). This is the easiest way to configure Hop
|
||||
on a global scale. You can do this in your `init.lua` or any `.vim` file by using the `lua` vim command.
|
||||
Example:
|
||||
```vim
|
||||
" init.vim
|
||||
"
|
||||
" Use better keys for the bépo keyboard layout and set
|
||||
" a balanced distribution of terminal / sequence keys
|
||||
lua require'hop'.setup { keys = 'etovxqpdygfblzhckisuran', jump_on_sole_occurrence = false }
|
||||
```
|
||||
- _Local configuration overrides_ are available only on the Lua API and are `{opts}` Lua tables passed to the various
|
||||
Lua functions. Those options have precedence over global options, so they allow to locally override options. Useful if
|
||||
you want to test a special option for a single Lua function, such as `require'hop'.hint_lines()`. You can test them
|
||||
inside the command line, such as:
|
||||
```
|
||||
:lua require'hop'.hint_words({ direction = require'hop.hint'.HintDirection.BEFORE_CURSOR })
|
||||
```
|
||||
- In the case of none of the above are provided, options are automatically read from the _default_ options. See `:h
|
||||
hop-config` for a list of default values.
|
||||
|
||||
# Extension
|
||||
|
||||
It is possible to extend Hop by creating *Hop extension plugins*. For more info:
|
||||
|
||||
```vim
|
||||
:h hop-extension
|
||||
```
|
||||
|
||||
> Disclaimer: you may have written a nice Hop extension plugin. You can open an issue to merge it upstream but remember
|
||||
> that it’s unlikely to be merged as Hop should remain small and straight-to-the point.
|
||||
|
||||
# Chat
|
||||
|
||||
Join the discussion on the official [Matrix room](https://matrix.to/#/#hop.nvim:matrix.org)!
|
||||
|
54
bundle/hop.nvim/doc/hop.txt
vendored
54
bundle/hop.nvim/doc/hop.txt
vendored
@ -1,4 +1,4 @@
|
||||
*hop.txt* For Neovim version 0.5 Last change: 2021 Nov 02
|
||||
*hop.txt* For Neovim version 0.5 Last change: 2022 Oct 09
|
||||
|
||||
__
|
||||
/ /_ ____ ____
|
||||
@ -7,6 +7,7 @@
|
||||
/_/ /_/\____/ .___/
|
||||
/_/
|
||||
· Neovim motions on speed! ·
|
||||
v2.0.2
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *hop-contents*
|
||||
@ -177,6 +178,14 @@ creates a variant of the command that will only run for the current line.
|
||||
|
||||
This is akin to calling the |hop.hint_lines_skip_whitespace| Lua function.
|
||||
|
||||
`:HopVertical` *:HopVertical*
|
||||
`:HopVerticalBC` *:HopVerticalBC*
|
||||
`:HopVerticalAC` *:HopVerticalAC*
|
||||
`:HopVerticalMW` *:HopVerticalMW*
|
||||
Like `HopLine` but keeps the column position of the cursor.
|
||||
|
||||
This is akin to calling the |hop.hint_vertical| Lua function.
|
||||
|
||||
`:HopAnywhere` *:HopAnywhere*
|
||||
`:HopAnywhereBC` *:HopAnywhereBC*
|
||||
`:HopAnywhereAC` *:HopAnywhereAC*
|
||||
@ -310,6 +319,16 @@ Most of the functions and values you need to know about are in `hop`.
|
||||
Arguments:~
|
||||
{opts} Hop options.
|
||||
|
||||
`hop.hint_vertical(`{opts}`)` *hop.hint_vertical*
|
||||
Hint the cursor position of each lines currently visible in the buffer
|
||||
view and allow to jump to them. If the line is shorter than the current
|
||||
cursor column position, it will default to the end of the line.
|
||||
|
||||
This works with empty lines as well.
|
||||
|
||||
Arguments:~
|
||||
{opts} Hop options.
|
||||
|
||||
`hop.hint_anywhere(`{opts}`)` *hop.hint_anywhere*
|
||||
Annotate anywhere in the current window with key sequences.
|
||||
|
||||
@ -499,7 +518,7 @@ doing that for you.
|
||||
of all the words in the window and will make the cursor jump to the one
|
||||
fully reduced.
|
||||
|
||||
`hop.jump_target.regex_by_line_start()` *hop.jump_target.regex_by_line_start*
|
||||
`hop.jump_target.by_line_start()` *hop.jump_target.by_line_start*
|
||||
Highlight the beginning of each line in the current window.
|
||||
|
||||
`hop.jump_target.regex_by_line_start_skip_whitespace()` *hop.jump_target.regex_by_line_start_skip_whitespace*
|
||||
@ -728,6 +747,18 @@ below.
|
||||
Defaults:~
|
||||
`hint_position = require'hop.hint'.HintPosition.BEGIN`
|
||||
|
||||
`hint_offset` *hop-config-hint_offset*
|
||||
Offset to apply to a jump location.
|
||||
|
||||
If it is non-zero, the jump target will be offset horizontally from the
|
||||
selected jump position by `hint_offset` character(s).
|
||||
|
||||
This option can be used for emulating the motion commands |t| and |T| where
|
||||
the cursor is positioned on/before the target position.
|
||||
|
||||
Defaults:~
|
||||
`hint_offset = 0`
|
||||
|
||||
`current_line_only` *hop-config-current_line_only*
|
||||
Apply Hop commands only to the current line.
|
||||
|
||||
@ -738,22 +769,6 @@ below.
|
||||
Defaults:~
|
||||
`current_line_only = false`
|
||||
|
||||
`inclusive_jump` *hop-config-inclusive_jump*
|
||||
Make all motions inclusive; i.e. jumping to a jump target will actually
|
||||
jump one display cell right to the jump target. Set this option to `true`
|
||||
if you would like to have the same behavior as with the |f| motion. Set it
|
||||
to `false` if you would like to have the same behavior as with the |t|
|
||||
motion.
|
||||
|
||||
There is one important limitation if you use `inclusive_jump = true`: if
|
||||
the jump target you would like to jump to is the last character on a
|
||||
line, it will not do what you expect; for instance, deleting or yanking
|
||||
with `d` / `y` will not include the last character by default, unless you
|
||||
set |virtualedit| to `onemore`.
|
||||
|
||||
Defaults:~
|
||||
`inclusive_jump = false`
|
||||
|
||||
`uppercase_labels` *hop-config-uppercase_labels*
|
||||
Display labels as uppercase. This option only affects the displayed
|
||||
labels; you still select them by typing the keys on your keyboard.
|
||||
@ -845,6 +860,9 @@ highlight is used. For the rest:
|
||||
Highlight used for the fake cursor visible when running a Hop command /
|
||||
Lua functions.
|
||||
|
||||
`HopPreview` *hop-hl-HopPreview*
|
||||
Highlight used for to preview the hint for HopPattern.
|
||||
|
||||
Highlights are inserted in an augroup, `HopInitHighlight`, and an autocommand
|
||||
is automatically set when initializing the plugin, unless you set
|
||||
|hop-config-create_hl_autocmd| to `false`.
|
||||
|
2
bundle/hop.nvim/lua/hop/defaults.lua
vendored
2
bundle/hop.nvim/lua/hop/defaults.lua
vendored
@ -9,9 +9,9 @@ M.jump_on_sole_occurrence = true
|
||||
M.case_insensitive = true
|
||||
M.create_hl_autocmd = true
|
||||
M.current_line_only = false
|
||||
M.inclusive_jump = false
|
||||
M.uppercase_labels = false
|
||||
M.multi_windows = false
|
||||
M.hint_position = require'hop.hint'.HintPosition.BEGIN
|
||||
M.hint_offset = 0
|
||||
|
||||
return M
|
||||
|
2
bundle/hop.nvim/lua/hop/health.lua
vendored
2
bundle/hop.nvim/lua/hop/health.lua
vendored
@ -5,7 +5,7 @@ local hop = require'hop'
|
||||
--
|
||||
-- This function will perform checks at initialization to ensure everything will work as expected.
|
||||
function M.check()
|
||||
local health = require'health'
|
||||
local health = vim.health or require'health'
|
||||
|
||||
health.report_start('Ensuring keys are unique')
|
||||
local existing_keys = {}
|
||||
|
3
bundle/hop.nvim/lua/hop/highlight.lua
vendored
3
bundle/hop.nvim/lua/hop/highlight.lua
vendored
@ -19,6 +19,9 @@ function M.insert_highlights()
|
||||
|
||||
-- Highlight used for the fake cursor visible when hopping.
|
||||
vim.api.nvim_command('highlight default link HopCursor Cursor')
|
||||
|
||||
-- Highlight used for preview pattern
|
||||
vim.api.nvim_command('highlight link HopPreview IncSearch')
|
||||
end
|
||||
|
||||
function M.create_autocmd()
|
||||
|
18
bundle/hop.nvim/lua/hop/hint.lua
vendored
18
bundle/hop.nvim/lua/hop/hint.lua
vendored
@ -99,8 +99,10 @@ function M.set_hint_extmarks(hl_ns, hints, opts)
|
||||
label = label:upper()
|
||||
end
|
||||
|
||||
local col = hint.jump_target.column - 1
|
||||
|
||||
if vim.fn.strdisplaywidth(label) == 1 then
|
||||
vim.api.nvim_buf_set_extmark(hint.jump_target.buffer or 0, hl_ns, hint.jump_target.line, hint.jump_target.column - 1, {
|
||||
vim.api.nvim_buf_set_extmark(hint.jump_target.buffer or 0, hl_ns, hint.jump_target.line, col, {
|
||||
virt_text = { { label, "HopNextKey" } },
|
||||
virt_text_pos = 'overlay',
|
||||
hl_mode = 'combine',
|
||||
@ -109,7 +111,7 @@ function M.set_hint_extmarks(hl_ns, hints, opts)
|
||||
else
|
||||
-- get the byte index of the second hint so that we can slice it correctly
|
||||
local snd_idx = vim.fn.byteidx(label, 1)
|
||||
vim.api.nvim_buf_set_extmark(hint.jump_target.buffer or 0, hl_ns, hint.jump_target.line, hint.jump_target.column - 1, { -- HERE
|
||||
vim.api.nvim_buf_set_extmark(hint.jump_target.buffer or 0, hl_ns, hint.jump_target.line, col, {
|
||||
virt_text = { { label:sub(1, snd_idx), "HopNextKey1" }, { label:sub(snd_idx + 1), "HopNextKey2" } },
|
||||
virt_text_pos = 'overlay',
|
||||
hl_mode = 'combine',
|
||||
@ -119,4 +121,16 @@ function M.set_hint_extmarks(hl_ns, hints, opts)
|
||||
end
|
||||
end
|
||||
|
||||
function M.set_hint_preview(hl_ns, jump_targets)
|
||||
for _, jt in ipairs(jump_targets) do
|
||||
vim.api.nvim_buf_set_extmark(jt.buffer, hl_ns, jt.line, jt.column - 1, {
|
||||
end_row = jt.line,
|
||||
end_col = jt.column - 1 + jt.length,
|
||||
hl_group = 'HopPreview',
|
||||
hl_eol = true,
|
||||
priority = prio.HINT_PRIO
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
417
bundle/hop.nvim/lua/hop/init.lua
vendored
417
bundle/hop.nvim/lua/hop/init.lua
vendored
@ -1,9 +1,3 @@
|
||||
local defaults = require'hop.defaults'
|
||||
local hint = require'hop.hint'
|
||||
local jump_target = require'hop.jump_target'
|
||||
local prio = require'hop.priority'
|
||||
local window = require'hop.window'
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Ensure options are sound.
|
||||
@ -18,6 +12,9 @@ local function check_opts(opts)
|
||||
if opts.multi_windows and opts.current_line_only then
|
||||
vim.notify('Cannot use current_line_only across multiple windows', 3)
|
||||
end
|
||||
if vim.api.nvim_get_mode().mode ~= 'n' then
|
||||
opts.multi_windows = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Allows to override global options with user local overrides.
|
||||
@ -33,18 +30,62 @@ local function eprintln(msg, teasing)
|
||||
end
|
||||
end
|
||||
|
||||
-- A hack to prevent #57 by deleting twice the namespace (it’s super weird).
|
||||
local function clear_namespace(buf_handle, hl_ns)
|
||||
vim.api.nvim_buf_clear_namespace(buf_handle, hl_ns, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf_handle, hl_ns, 0, -1)
|
||||
-- Create hint state
|
||||
--
|
||||
-- {
|
||||
-- all_ctxs: All windows's context
|
||||
-- buf_list: All buffers displayed in all windows
|
||||
-- <xxx>_ns: Required namespaces
|
||||
-- }
|
||||
local function create_hint_state(opts)
|
||||
local window = require'hop.window'
|
||||
|
||||
local hint_state = {}
|
||||
|
||||
-- get all window's context and buffer list
|
||||
hint_state.all_ctxs = window.get_window_context(opts.multi_windows)
|
||||
hint_state.buf_list = {}
|
||||
for _, bctx in ipairs(hint_state.all_ctxs) do
|
||||
hint_state.buf_list[#hint_state.buf_list + 1] = bctx.hbuf
|
||||
for _, wctx in ipairs(bctx.contexts) do
|
||||
window.clip_window_context(wctx, opts.direction)
|
||||
end
|
||||
end
|
||||
|
||||
-- create the highlight groups; the highlight groups will allow us to clean everything at once when Hop quits
|
||||
hint_state.hl_ns = vim.api.nvim_create_namespace('hop_hl')
|
||||
hint_state.dim_ns = vim.api.nvim_create_namespace('hop_dim')
|
||||
|
||||
-- backup namespaces of diagnostic
|
||||
if vim.fn.has("nvim-0.6") == 1 then
|
||||
hint_state.diag_ns = vim.diagnostic.get_namespaces()
|
||||
end
|
||||
|
||||
-- Store users cursorline state
|
||||
hint_state.cursorline = vim.api.nvim_win_get_option(vim.api.nvim_get_current_win(), 'cursorline')
|
||||
|
||||
return hint_state
|
||||
end
|
||||
|
||||
-- Dim everything out to prepare the Hop session.
|
||||
-- A hack to prevent #57 by deleting twice the namespace (it’s super weird).
|
||||
local function clear_namespace(buf_list, hl_ns)
|
||||
for _, buf in ipairs(buf_list) do
|
||||
if vim.api.nvim_buf_is_valid(buf) then
|
||||
vim.api.nvim_buf_clear_namespace(buf, hl_ns, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf, hl_ns, 0, -1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Set the highlight of unmatched lines of the buffer.
|
||||
--
|
||||
-- - hl_ns is the highlight namespace.
|
||||
-- - top_line is the top line in the buffer to start highlighting at
|
||||
-- - bottom_line is the bottom line in the buffer to stop highlighting at
|
||||
local function apply_dimming(buf_handle, hl_ns, top_line, bottom_line, cursor_pos, direction, current_line_only)
|
||||
local function set_unmatched_lines(buf_handle, hl_ns, top_line, bottom_line, cursor_pos, direction, current_line_only)
|
||||
local hint = require'hop.hint'
|
||||
local prio = require'hop.priority'
|
||||
|
||||
local start_line = top_line
|
||||
local end_line = bottom_line
|
||||
local start_col = 0
|
||||
@ -53,9 +94,8 @@ local function apply_dimming(buf_handle, hl_ns, top_line, bottom_line, cursor_po
|
||||
if direction == hint.HintDirection.AFTER_CURSOR then
|
||||
start_col = cursor_pos[2]
|
||||
elseif direction == hint.HintDirection.BEFORE_CURSOR then
|
||||
if cursor_pos[2] ~= 0 then
|
||||
end_col = cursor_pos[2] + 1
|
||||
end
|
||||
end_line = bottom_line - 1
|
||||
if cursor_pos[2] ~= 0 then end_col = cursor_pos[2] end
|
||||
end
|
||||
|
||||
if current_line_only then
|
||||
@ -68,13 +108,45 @@ local function apply_dimming(buf_handle, hl_ns, top_line, bottom_line, cursor_po
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_set_extmark(buf_handle, hl_ns, start_line, start_col, {
|
||||
local extmark_options = {
|
||||
end_line = end_line,
|
||||
end_col = end_col,
|
||||
hl_group = 'HopUnmatched',
|
||||
hl_eol = true,
|
||||
priority = prio.DIM_PRIO
|
||||
})
|
||||
}
|
||||
|
||||
if end_col then
|
||||
local current_line = vim.api.nvim_buf_get_lines(buf_handle, cursor_pos[1] - 1, cursor_pos[1], true)[1]
|
||||
local current_width = vim.fn.strdisplaywidth(current_line)
|
||||
|
||||
if end_col > current_width then
|
||||
end_col = current_width - 1
|
||||
end
|
||||
|
||||
extmark_options.end_col = end_col
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_set_extmark(buf_handle, hl_ns, start_line, start_col,
|
||||
extmark_options)
|
||||
end
|
||||
|
||||
-- Dim everything out to prepare the Hop session for all windows.
|
||||
local function apply_dimming(hint_state, opts)
|
||||
local window = require'hop.window'
|
||||
|
||||
for _, bctx in ipairs(hint_state.all_ctxs) do
|
||||
for _, wctx in ipairs(bctx.contexts) do
|
||||
window.clip_window_context(wctx, opts.direction)
|
||||
-- dim everything out, add the virtual cursor and hide diagnostics
|
||||
set_unmatched_lines(bctx.hbuf, hint_state.dim_ns, wctx.top_line, wctx.bot_line, wctx.cursor_pos, opts.direction, opts.current_line_only)
|
||||
end
|
||||
|
||||
if vim.fn.has("nvim-0.6") == 1 then
|
||||
for ns in pairs(hint_state.diag_ns) do
|
||||
vim.diagnostic.show(ns, bctx.hbuf, nil, { virtual_text = false })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Add the virtual cursor, taking care to handle the cases where:
|
||||
@ -83,6 +155,8 @@ end
|
||||
-- - the current line is empty
|
||||
-- - there are multibyte characters on the line
|
||||
local function add_virt_cur(ns)
|
||||
local prio = require'hop.priority'
|
||||
|
||||
local cur_info = vim.fn.getcurpos()
|
||||
local cur_row = cur_info[2] - 1
|
||||
local cur_col = cur_info[3] - 1 -- this gives cursor column location, in bytes
|
||||
@ -90,6 +164,12 @@ local function add_virt_cur(ns)
|
||||
local virt_col = cur_info[5] - 1
|
||||
local cur_line = vim.api.nvim_get_current_line()
|
||||
|
||||
-- toggle cursorline off if currently set
|
||||
local cursorline_info = vim.api.nvim_win_get_option(vim.api.nvim_get_current_win(), 'cursorline')
|
||||
if cursorline_info == true then
|
||||
vim.api.nvim_win_set_option(vim.api.nvim_get_current_win(), 'cursorline', false)
|
||||
end
|
||||
|
||||
-- first check to see if cursor is in a tab char or past end of line
|
||||
if cur_offset ~= 0 then
|
||||
vim.api.nvim_buf_set_extmark(0, ns, cur_row, cur_col, {
|
||||
@ -114,27 +194,112 @@ local function add_virt_cur(ns)
|
||||
end
|
||||
end
|
||||
|
||||
-- Get pattern from input for hint and preview
|
||||
function M.get_input_pattern(prompt, maxchar, opts)
|
||||
local hint = require'hop.hint'
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
local hs = {}
|
||||
if opts then
|
||||
hs = create_hint_state(opts)
|
||||
hs.preview_ns = vim.api.nvim_create_namespace('hop_preview')
|
||||
apply_dimming(hs, opts)
|
||||
add_virt_cur(hs.hl_ns)
|
||||
end
|
||||
|
||||
local K_Esc = vim.api.nvim_replace_termcodes('<Esc>', true, false, true)
|
||||
local K_BS = vim.api.nvim_replace_termcodes('<BS>', true, false, true)
|
||||
local K_C_H = vim.api.nvim_replace_termcodes('<C-H>', true, false, true)
|
||||
local K_CR = vim.api.nvim_replace_termcodes('<CR>', true, false, true)
|
||||
local K_NL = vim.api.nvim_replace_termcodes('<NL>', true, false, true)
|
||||
local pat_keys = {}
|
||||
local pat = ''
|
||||
|
||||
while (true) do
|
||||
pat = vim.fn.join(pat_keys, '')
|
||||
if opts then
|
||||
clear_namespace(hs.buf_list, hs.preview_ns)
|
||||
if #pat > 0 then
|
||||
local ok, re = pcall(jump_target.regex_by_case_searching, pat, false, opts)
|
||||
if ok then
|
||||
local jump_target_gtr = jump_target.jump_targets_by_scanning_lines(re)
|
||||
local generated = jump_target_gtr(opts)
|
||||
hint.set_hint_preview(hs.preview_ns, generated.jump_targets)
|
||||
end
|
||||
end
|
||||
end
|
||||
vim.api.nvim_echo({}, false, {})
|
||||
vim.cmd('redraw')
|
||||
vim.api.nvim_echo({{prompt, 'Question'}, {pat}}, false, {})
|
||||
|
||||
local ok, key = pcall(vim.fn.getchar)
|
||||
if not ok then -- Interrupted by <C-c>
|
||||
pat = nil
|
||||
break
|
||||
end
|
||||
|
||||
if type(key) == 'number' then
|
||||
key = vim.fn.nr2char(key)
|
||||
elseif key:byte() == 128 then
|
||||
-- It's a special key in string
|
||||
end
|
||||
|
||||
if key == K_Esc then
|
||||
pat = nil
|
||||
break
|
||||
elseif key == K_CR or key == K_NL then
|
||||
break
|
||||
elseif key == K_BS or key == K_C_H then
|
||||
pat_keys[#pat_keys] = nil
|
||||
else
|
||||
pat_keys[#pat_keys + 1] = key
|
||||
end
|
||||
|
||||
if maxchar and #pat_keys >= maxchar then
|
||||
pat = vim.fn.join(pat_keys, '')
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if opts then
|
||||
clear_namespace(hs.buf_list, hs.preview_ns)
|
||||
-- quit only when got nothin for pattern to avoid blink of highlight
|
||||
if not pat then M.quit(hs) end
|
||||
end
|
||||
vim.api.nvim_echo({}, false, {})
|
||||
vim.cmd('redraw')
|
||||
return pat
|
||||
end
|
||||
|
||||
-- Move the cursor at a given location.
|
||||
--
|
||||
-- If inclusive is `true`, the jump target will be incremented visually by 1, so that operator-pending motions can
|
||||
-- correctly take into account the right offset. This is the main difference between motions such as `f` (inclusive)
|
||||
-- and `t` (exclusive).
|
||||
-- Add option to shift cursor by column offset
|
||||
--
|
||||
-- This function will update the jump list.
|
||||
function M.move_cursor_to(w, line, column, inclusive)
|
||||
-- If we do not ask for inclusive jump, we don’t have to retreive any additional lines because we will jump to the
|
||||
-- actual jump target. If we do want an inclusive jump, we need to retreive the line the jump target lies in so that
|
||||
-- we can compute the offset correctly. This is linked to the fact that currently, Neovim doesn’s have an API to «
|
||||
-- offset something by 1 visual column. »
|
||||
if inclusive then
|
||||
function M.move_cursor_to(w, line, column, hint_offset, direction)
|
||||
-- If we do not ask for an offset jump, we don’t have to retrieve any additional lines because we will jump to the
|
||||
-- actual jump target. If we do want a jump with an offset, we need to retrieve the line the jump target lies in so
|
||||
-- that we can compute the offset correctly. This is linked to the fact that currently, Neovim doesn’s have an API to
|
||||
-- « offset something by N visual columns. »
|
||||
|
||||
-- If it is pending for operator shift column to the right by 1
|
||||
if vim.api.nvim_get_mode().mode == 'no' and direction ~= 1 then
|
||||
column = column + 1
|
||||
end
|
||||
|
||||
if hint_offset ~= nil and not (hint_offset == 0) then
|
||||
-- Add `hint_offset` based on `charidx`.
|
||||
local buf_line = vim.api.nvim_buf_get_lines(vim.api.nvim_win_get_buf(w), line - 1, line, false)[1]
|
||||
column = vim.fn.byteidx(buf_line, column + 1)
|
||||
-- Since `charidx` returns -1 when `column` is the tail, subtract 1 and add 1 to the return value to get
|
||||
-- the correct value.
|
||||
local char_idx = vim.fn.charidx(buf_line, column - 1) + 1 + hint_offset
|
||||
column = vim.fn.byteidx(buf_line, char_idx)
|
||||
end
|
||||
|
||||
-- update the jump list
|
||||
vim.cmd("normal! m'")
|
||||
vim.api.nvim_set_current_win(w)
|
||||
vim.api.nvim_win_set_cursor(w, { line, column})
|
||||
vim.api.nvim_win_set_cursor(w, { line, column })
|
||||
end
|
||||
|
||||
function M.hint_with(jump_target_gtr, opts)
|
||||
@ -143,11 +308,13 @@ function M.hint_with(jump_target_gtr, opts)
|
||||
end
|
||||
|
||||
M.hint_with_callback(jump_target_gtr, opts, function(jt)
|
||||
M.move_cursor_to(jt.window, jt.line + 1, jt.column - 1, opts.inclusive_jump)
|
||||
M.move_cursor_to(jt.window, jt.line + 1, jt.column - 1, opts.hint_offset, opts.direction)
|
||||
end)
|
||||
end
|
||||
|
||||
function M.hint_with_callback(jump_target_gtr, opts, callback)
|
||||
local hint = require'hop.hint'
|
||||
|
||||
if opts == nil then
|
||||
opts = override_opts(opts)
|
||||
end
|
||||
@ -157,64 +324,49 @@ function M.hint_with_callback(jump_target_gtr, opts, callback)
|
||||
return
|
||||
end
|
||||
|
||||
local all_ctxs = window.get_window_context(opts.multi_windows)
|
||||
|
||||
-- create the highlight groups; the highlight groups will allow us to clean everything at once when Hop quits
|
||||
local hl_ns = vim.api.nvim_create_namespace('hop_hl')
|
||||
local dim_ns = vim.api.nvim_create_namespace('')
|
||||
-- create hint state
|
||||
local hs = create_hint_state(opts)
|
||||
|
||||
-- create jump targets
|
||||
local generated = jump_target_gtr(opts)
|
||||
local jump_target_count = #generated.jump_targets
|
||||
|
||||
local h = nil
|
||||
local target_idx = nil
|
||||
if jump_target_count == 0 then
|
||||
eprintln(' -> there’s no such thing we can see…', opts.teasing)
|
||||
clear_namespace(0, hl_ns)
|
||||
clear_namespace(0, dim_ns)
|
||||
return
|
||||
target_idx = 0
|
||||
elseif vim.v.count > 0 then
|
||||
target_idx = vim.v.count
|
||||
elseif jump_target_count == 1 and opts.jump_on_sole_occurrence then
|
||||
local jt = generated.jump_targets[1]
|
||||
callback(jt)
|
||||
target_idx = 1
|
||||
end
|
||||
|
||||
clear_namespace(0, hl_ns)
|
||||
clear_namespace(0, dim_ns)
|
||||
if target_idx ~= nil then
|
||||
local jt = generated.jump_targets[target_idx]
|
||||
if jt then
|
||||
callback(jt)
|
||||
else
|
||||
eprintln(' -> there’s no such thing we can see…', opts.teasing)
|
||||
end
|
||||
|
||||
clear_namespace(hs.buf_list, hs.hl_ns)
|
||||
clear_namespace(hs.buf_list, hs.dim_ns)
|
||||
return
|
||||
end
|
||||
|
||||
-- we have at least two targets, so generate hints to display
|
||||
local hints = hint.create_hints(generated.jump_targets, generated.indirect_jump_targets, opts)
|
||||
hs.hints = hint.create_hints(generated.jump_targets, generated.indirect_jump_targets, opts)
|
||||
|
||||
local hint_state = {
|
||||
hints = hints,
|
||||
hl_ns = hl_ns,
|
||||
dim_ns = dim_ns,
|
||||
}
|
||||
|
||||
local buf_list = {}
|
||||
for _, bctx in ipairs(all_ctxs) do
|
||||
buf_list[#buf_list + 1] = bctx.hbuf
|
||||
for _, wctx in ipairs(bctx.contexts) do
|
||||
window.clip_window_context(wctx, opts.direction)
|
||||
-- dim everything out, add the virtual cursor and hide diagnostics
|
||||
apply_dimming(bctx.hbuf, dim_ns, wctx.top_line, wctx.bot_line, wctx.cursor_pos, opts.direction, opts.current_line_only)
|
||||
end
|
||||
end
|
||||
|
||||
add_virt_cur(hl_ns)
|
||||
if vim.fn.has("nvim-0.6") == 1 then
|
||||
hint_state.diag_ns = vim.diagnostic.get_namespaces()
|
||||
for ns in pairs(hint_state.diag_ns) do vim.diagnostic.show(ns, 0, nil, { virtual_text = false }) end
|
||||
end
|
||||
hint.set_hint_extmarks(hl_ns, hints, opts)
|
||||
-- dim everything out, add the virtual cursor and hide diagnostics
|
||||
apply_dimming(hs, opts)
|
||||
add_virt_cur(hs.hl_ns)
|
||||
hint.set_hint_extmarks(hs.hl_ns, hs.hints, opts)
|
||||
vim.cmd('redraw')
|
||||
|
||||
local h = nil
|
||||
while h == nil do
|
||||
local ok, key = pcall(vim.fn.getchar)
|
||||
if not ok then
|
||||
for _, buf in ipairs(buf_list) do
|
||||
M.quit(buf, hint_state)
|
||||
end
|
||||
M.quit(hs)
|
||||
break
|
||||
end
|
||||
local not_special_key = true
|
||||
@ -232,13 +384,11 @@ function M.hint_with_callback(jump_target_gtr, opts, callback)
|
||||
|
||||
if not_special_key and opts.keys:find(key, 1, true) then
|
||||
-- If this is a key used in Hop (via opts.keys), deal with it in Hop
|
||||
h = M.refine_hints(buf_list, key, hint_state, callback, opts)
|
||||
h = M.refine_hints(key, hs, callback, opts)
|
||||
vim.cmd('redraw')
|
||||
else
|
||||
-- If it's not, quit Hop
|
||||
for _, buf in ipairs(buf_list) do
|
||||
M.quit(buf, hint_state)
|
||||
end
|
||||
M.quit(hs)
|
||||
-- If the key captured via getchar() is not the quit_key, pass it through
|
||||
-- to nvim to be handled normally (including mappings)
|
||||
if key ~= vim.api.nvim_replace_termcodes(opts.quit_key, true, false, true) then
|
||||
@ -253,7 +403,9 @@ end
|
||||
--
|
||||
-- Refining hints allows to advance the state machine by one step. If a terminal step is reached, this function jumps to
|
||||
-- the location. Otherwise, it stores the new state machine.
|
||||
function M.refine_hints(buf_list, key, hint_state, callback, opts)
|
||||
function M.refine_hints(key, hint_state, callback, opts)
|
||||
local hint = require'hop.hint'
|
||||
|
||||
local h, hints = hint.reduce_hints(hint_state.hints, key)
|
||||
|
||||
if h == nil then
|
||||
@ -264,15 +416,10 @@ function M.refine_hints(buf_list, key, hint_state, callback, opts)
|
||||
|
||||
hint_state.hints = hints
|
||||
|
||||
for _, buf in ipairs(buf_list) do
|
||||
clear_namespace(buf, hint_state.hl_ns)
|
||||
end
|
||||
clear_namespace(hint_state.buf_list, hint_state.hl_ns)
|
||||
hint.set_hint_extmarks(hint_state.hl_ns, hints, opts)
|
||||
vim.cmd('redraw')
|
||||
else
|
||||
for _, buf in ipairs(buf_list) do
|
||||
M.quit(buf, hint_state)
|
||||
end
|
||||
M.quit(hint_state)
|
||||
|
||||
-- prior to jump, register the current position into the jump list
|
||||
vim.cmd("normal! m'")
|
||||
@ -283,16 +430,28 @@ function M.refine_hints(buf_list, key, hint_state, callback, opts)
|
||||
end
|
||||
|
||||
-- Quit Hop and delete its resources.
|
||||
function M.quit(buf_handle, hint_state)
|
||||
clear_namespace(buf_handle, hint_state.hl_ns)
|
||||
clear_namespace(buf_handle, hint_state.dim_ns)
|
||||
function M.quit(hint_state)
|
||||
clear_namespace(hint_state.buf_list, hint_state.hl_ns)
|
||||
clear_namespace(hint_state.buf_list, hint_state.dim_ns)
|
||||
|
||||
if vim.fn.has("nvim-0.6") == 1 then
|
||||
for ns in pairs(hint_state.diag_ns) do vim.diagnostic.show(ns, buf_handle) end
|
||||
-- Restore users cursorline setting
|
||||
if hint_state.cursorline == true then
|
||||
vim.api.nvim_win_set_option(vim.api.nvim_get_current_win(), 'cursorline', true)
|
||||
end
|
||||
|
||||
for _, buf in ipairs(hint_state.buf_list) do
|
||||
-- sometimes, buffers might be unloaded; that’s the case with floats for instance (we can invoke Hop from them but
|
||||
-- then they disappear); we need to check whether the buffer is still valid before trying to do anything else with
|
||||
-- it
|
||||
if vim.api.nvim_buf_is_valid(buf) and vim.fn.has("nvim-0.6") == 1 then
|
||||
for ns in pairs(hint_state.diag_ns) do vim.diagnostic.show(ns, buf) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.hint_words(opts)
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
|
||||
local generator
|
||||
@ -309,20 +468,26 @@ function M.hint_words(opts)
|
||||
end
|
||||
|
||||
function M.hint_patterns(opts, pattern)
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
|
||||
-- The pattern to search is either retrieved from the (optional) argument
|
||||
-- or directly from user input.
|
||||
if pattern == nil then
|
||||
local pat
|
||||
if pattern then
|
||||
pat = pattern
|
||||
else
|
||||
vim.cmd('redraw')
|
||||
vim.fn.inputsave()
|
||||
|
||||
local ok
|
||||
ok, pattern = pcall(vim.fn.input, 'Search: ')
|
||||
pat = M.get_input_pattern('Hop pattern: ', nil, opts)
|
||||
vim.fn.inputrestore()
|
||||
if not pat then return end
|
||||
end
|
||||
|
||||
if not ok then
|
||||
return
|
||||
end
|
||||
if #pat == 0 then
|
||||
eprintln('-> empty pattern', opts.teasing)
|
||||
return
|
||||
end
|
||||
|
||||
local generator
|
||||
@ -333,16 +498,18 @@ function M.hint_patterns(opts, pattern)
|
||||
end
|
||||
|
||||
M.hint_with(
|
||||
generator(jump_target.regex_by_case_searching(pattern, false, opts)),
|
||||
generator(jump_target.regex_by_case_searching(pat, false, opts)),
|
||||
opts
|
||||
)
|
||||
end
|
||||
|
||||
function M.hint_char1(opts)
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
|
||||
local ok, c = pcall(vim.fn.getchar)
|
||||
if not ok then
|
||||
local c = M.get_input_pattern('Hop 1 char: ', 1)
|
||||
if not c then
|
||||
return
|
||||
end
|
||||
|
||||
@ -354,32 +521,21 @@ function M.hint_char1(opts)
|
||||
end
|
||||
|
||||
M.hint_with(
|
||||
generator(jump_target.regex_by_case_searching(vim.fn.nr2char(c), true, opts)),
|
||||
generator(jump_target.regex_by_case_searching(c, true, opts)),
|
||||
opts
|
||||
)
|
||||
end
|
||||
|
||||
function M.hint_char2(opts)
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
|
||||
local ok, a = pcall(vim.fn.getchar)
|
||||
if not ok then
|
||||
local c = M.get_input_pattern('Hop 2 char: ', 2)
|
||||
if not c then
|
||||
return
|
||||
end
|
||||
|
||||
local ok2, b = pcall(vim.fn.getchar)
|
||||
if not ok2 then
|
||||
return
|
||||
end
|
||||
|
||||
local pattern = vim.fn.nr2char(a)
|
||||
|
||||
-- if we have a fallback key defined in the opts, if the second character is that key, we then fallback to the same
|
||||
-- behavior as hint_char1()
|
||||
if opts.char2_fallback_key == nil or b ~= vim.fn.char2nr(vim.api.nvim_replace_termcodes(opts.char2_fallback_key, true, false, true)) then
|
||||
pattern = pattern .. vim.fn.nr2char(b)
|
||||
end
|
||||
|
||||
local generator
|
||||
if opts.current_line_only then
|
||||
generator = jump_target.jump_targets_for_current_line
|
||||
@ -388,12 +544,14 @@ function M.hint_char2(opts)
|
||||
end
|
||||
|
||||
M.hint_with(
|
||||
generator(jump_target.regex_by_case_searching(pattern, true, opts)),
|
||||
generator(jump_target.regex_by_case_searching(c, true, opts)),
|
||||
opts
|
||||
)
|
||||
end
|
||||
|
||||
function M.hint_lines(opts)
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
|
||||
local generator
|
||||
@ -404,12 +562,37 @@ function M.hint_lines(opts)
|
||||
end
|
||||
|
||||
M.hint_with(
|
||||
generator(jump_target.regex_by_line_start()),
|
||||
generator(jump_target.by_line_start()),
|
||||
opts
|
||||
)
|
||||
end
|
||||
|
||||
function M.hint_vertical(opts)
|
||||
local hint = require'hop.hint'
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
-- only makes sense as end position given movement goal.
|
||||
opts.hint_position = hint.HintPosition.END
|
||||
|
||||
local generator
|
||||
if opts.current_line_only then
|
||||
generator = jump_target.jump_targets_for_current_line
|
||||
else
|
||||
generator = jump_target.jump_targets_by_scanning_lines
|
||||
end
|
||||
|
||||
-- FIXME: need to exclude current and include empty lines.
|
||||
M.hint_with(
|
||||
generator(jump_target.regex_by_vertical()),
|
||||
opts
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
function M.hint_lines_skip_whitespace(opts)
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
|
||||
local generator
|
||||
@ -426,6 +609,8 @@ function M.hint_lines_skip_whitespace(opts)
|
||||
end
|
||||
|
||||
function M.hint_anywhere(opts)
|
||||
local jump_target = require'hop.jump_target'
|
||||
|
||||
opts = override_opts(opts)
|
||||
|
||||
local generator
|
||||
@ -444,7 +629,7 @@ end
|
||||
-- Setup user settings.
|
||||
function M.setup(opts)
|
||||
-- Look up keys in user-defined table with fallback to defaults.
|
||||
M.opts = setmetatable(opts or {}, {__index = defaults})
|
||||
M.opts = setmetatable(opts or {}, {__index = require'hop.defaults'})
|
||||
M.initialized = true
|
||||
|
||||
-- Insert the highlights and register the autocommand if asked to.
|
||||
|
49
bundle/hop.nvim/lua/hop/jump_target.lua
vendored
49
bundle/hop.nvim/lua/hop/jump_target.lua
vendored
@ -91,6 +91,13 @@ local function mark_jump_targets_line(buf_handle, win_handle, regex, line_contex
|
||||
if b == nil or (b == 0 and e == 0) then
|
||||
break
|
||||
end
|
||||
-- Preview need a length to highlight the matched string. Zero means nothing to highlight.
|
||||
local matched_length = e - b
|
||||
-- As the make for jump target must be placed at a cell (but some pattern like '^' is
|
||||
-- placed between cells), we should make sure e > b
|
||||
if b == e then
|
||||
e = e + 1
|
||||
end
|
||||
|
||||
local colp = col + b
|
||||
if hint_position == hint.HintPosition.MIDDLE then
|
||||
@ -99,10 +106,9 @@ local function mark_jump_targets_line(buf_handle, win_handle, regex, line_contex
|
||||
colp = col + e - 1
|
||||
end
|
||||
jump_targets[#jump_targets + 1] = {
|
||||
line = line_nr,
|
||||
column = math.max(1, colp + col_offset + col_bias),
|
||||
line = line_context.line_nr,
|
||||
column = math.max(1, colp + col_offset + col_bias),
|
||||
length = math.max(0, matched_length),
|
||||
buffer = buf_handle,
|
||||
window = win_handle,
|
||||
}
|
||||
@ -342,10 +348,13 @@ function M.regex_by_searching(pat, plain_search)
|
||||
if plain_search then
|
||||
pat = vim.fn.escape(pat, '\\/.$^~[]')
|
||||
end
|
||||
|
||||
local regex = vim.regex(pat)
|
||||
|
||||
return {
|
||||
oneshot = false,
|
||||
match = function(s)
|
||||
return vim.regex(pat):match_str(s)
|
||||
return regex:match_str(s)
|
||||
end
|
||||
}
|
||||
end
|
||||
@ -364,10 +373,12 @@ function M.regex_by_case_searching(pat, plain_search, opts)
|
||||
pat = '\\c' .. pat
|
||||
end
|
||||
|
||||
local regex = vim.regex(pat)
|
||||
|
||||
return {
|
||||
oneshot = false,
|
||||
match = function(s)
|
||||
return vim.regex(pat):match_str(s)
|
||||
return regex:match_str(s)
|
||||
end
|
||||
}
|
||||
end
|
||||
@ -378,22 +389,42 @@ function M.regex_by_word_start()
|
||||
end
|
||||
|
||||
-- Line regex.
|
||||
function M.regex_by_line_start()
|
||||
function M.by_line_start()
|
||||
local c = vim.fn.winsaveview().leftcol
|
||||
|
||||
return {
|
||||
oneshot = true,
|
||||
match = function(_)
|
||||
return 0, 1, false
|
||||
match = function(s)
|
||||
local l = vim.fn.strdisplaywidth(s)
|
||||
if c > 0 and l == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return 0, 1
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
-- Line regex at cursor position.
|
||||
function M.regex_by_vertical()
|
||||
local position = vim.api.nvim_win_get_cursor(0)[2]
|
||||
local regex = vim.regex(string.format("^.\\{0,%d\\}\\(.\\|$\\)", position))
|
||||
return {
|
||||
oneshot = true,
|
||||
match = function(s)
|
||||
return regex:match_str(s)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
-- Line regex skipping finding the first non-whitespace character on each line.
|
||||
function M.regex_by_line_start_skip_whitespace()
|
||||
local pat = vim.regex("\\S")
|
||||
local regex = vim.regex("\\S")
|
||||
|
||||
return {
|
||||
oneshot = true,
|
||||
match = function(s)
|
||||
return pat:match_str(s)
|
||||
return regex:match_str(s)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
2
bundle/hop.nvim/lua/hop/perm.lua
vendored
2
bundle/hop.nvim/lua/hop/perm.lua
vendored
@ -7,7 +7,7 @@ end
|
||||
|
||||
-- Get the next key of the input key in the input key set, if any, or return nil.
|
||||
local function next_key(keys, key)
|
||||
local _, e = keys:find(key)
|
||||
local _, e = keys:find(key, 1, true)
|
||||
|
||||
if e == #keys then
|
||||
return nil
|
||||
|
6
bundle/hop.nvim/lua/hop/window.lua
vendored
6
bundle/hop.nvim/lua/hop/window.lua
vendored
@ -4,6 +4,7 @@ local M = {}
|
||||
|
||||
local function window_context(win_handle, cursor_pos)
|
||||
-- get a bunch of information about the window and the cursor
|
||||
vim.api.nvim_set_current_win(win_handle)
|
||||
local win_info = vim.fn.getwininfo(win_handle)[1]
|
||||
local win_view = vim.fn.winsaveview()
|
||||
local top_line = win_info.topline - 1
|
||||
@ -52,9 +53,10 @@ function M.get_window_context(multi_windows)
|
||||
-- Generate contexts of windows
|
||||
local cur_hwin = vim.api.nvim_get_current_win()
|
||||
local cur_hbuf = vim.api.nvim_win_get_buf(cur_hwin)
|
||||
|
||||
all_ctxs[#all_ctxs + 1] = {
|
||||
hbuf = cur_hbuf,
|
||||
contexts = { window_context(cur_hwin, vim.api.nvim_win_get_cursor(cur_hwin)) },
|
||||
contexts = { window_context(cur_hwin, {vim.fn.line('.'), vim.fn.charcol('.')} ) },
|
||||
}
|
||||
|
||||
if not multi_windows then
|
||||
@ -131,7 +133,7 @@ end
|
||||
-- If the direction is HintDirection.AFTER_CURSOR, then everything before the cursor will be clipped.
|
||||
function M.clip_window_context(context, direction)
|
||||
if direction == hint.HintDirection.BEFORE_CURSOR then
|
||||
context.bot_line = context.cursor_pos[1] - 1
|
||||
context.bot_line = context.cursor_pos[1]
|
||||
elseif direction == hint.HintDirection.AFTER_CURSOR then
|
||||
context.top_line = context.cursor_pos[1] - 1
|
||||
end
|
||||
|
8
bundle/hop.nvim/plugin/hop.vim
vendored
8
bundle/hop.nvim/plugin/hop.vim
vendored
@ -47,12 +47,18 @@ command! HopLineBC lua require'hop'.hint_lines({ direction = require'hop.hint'.H
|
||||
command! HopLineAC lua require'hop'.hint_lines({ direction = require'hop.hint'.HintDirection.AFTER_CURSOR })
|
||||
command! HopLineMW lua require'hop'.hint_lines({ multi_windows = true })
|
||||
|
||||
" The jump-to-line command.
|
||||
" The jump-to-line command (non-whitespace).
|
||||
command! HopLineStart lua require'hop'.hint_lines_skip_whitespace()
|
||||
command! HopLineStartBC lua require'hop'.hint_lines_skip_whitespace({ direction = require'hop.hint'.HintDirection.BEFORE_CURSOR })
|
||||
command! HopLineStartAC lua require'hop'.hint_lines_skip_whitespace({ direction = require'hop.hint'.HintDirection.AFTER_CURSOR })
|
||||
command! HopLineStartMW lua require'hop'.hint_lines_skip_whitespace({ multi_windows = true })
|
||||
|
||||
" The vertical command (line jump preserving the column cursor position).
|
||||
command! HopVertical lua require'hop'.hint_vertical()
|
||||
command! HopVerticalBC lua require'hop'.hint_vertical({ direction = require'hop.hint'.HintDirection.BEFORE_CURSOR })
|
||||
command! HopVerticalAC lua require'hop'.hint_vertical({ direction = require'hop.hint'.HintDirection.AFTER_CURSOR })
|
||||
command! HopVerticalMW lua require'hop'.hint_vertical({ multi_windows = true })
|
||||
|
||||
" The jump-to-anywhere command.
|
||||
command! HopAnywhere lua require'hop'.hint_anywhere()
|
||||
command! HopAnywhereBC lua require'hop'.hint_anywhere({ direction = require'hop.hint'.HintDirection.BEFORE_CURSOR })
|
||||
|
Loading…
Reference in New Issue
Block a user