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

help_tags() does not escape special characters #3027

Open
vanaigr opened this issue Apr 1, 2024 · 4 comments
Open

help_tags() does not escape special characters #3027

vanaigr opened this issue Apr 1, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@vanaigr
Copy link

vanaigr commented Apr 1, 2024

Description

using Telescope help_tags to jump to [==] (equivalence class) opens help for = instead.

Neovim version

NVIM v0.9.2
Build type: RelWithDebInfo
LuaJIT 2.1.1694082368

Operating system and version

Windows 10

Telescope version / branch / rev

1bb28df

checkhealth telescope

==============================================================================
Telescope: require("Telescope.health").check()

Checking for required plugins ~
- OK plenary installed.
- OK nvim-treesitter installed.

Checking external dependencies ~
- ERROR rg: not found. `live-grep` finder will not function without [BurntSushi/ripgrep](https://github.com/BurntSushi/ripgrep) installed.
- WARNING fd: not found. Install [sharkdp/fd](https://github.com/sharkdp/fd) for extended capabilities

===== Installed extensions ===== ~

Steps to reproduce

nvim -nu minimal.lua
:Telescope help_tags<CR>
[==]<CR>

Expected behavior

help_tags opens help for [==] (in runtime/doc/pattern.txt),
the same file that is displayed in the preview.

image
image

Actual behavior

Help is opened for = (in runtime/doc/change.txt)
image

Minimal config

vim.cmd [[set runtimepath=$VIMRUNTIME]]
vim.cmd [[set packpath=/tmp/nvim/site]]
local package_root = '/tmp/nvim/site/pack'
local install_path = package_root .. '/packer/start/packer.nvim'
local function load_plugins()
  require('packer').startup {
    {
      'wbthomason/packer.nvim',
      {
        'nvim-telescope/telescope.nvim',
        requires = {
          'nvim-lua/plenary.nvim',
          { 'nvim-telescope/telescope-fzf-native.nvim', run = 'make' },
        },
      },
    },
    config = {
      package_root = package_root,
      compile_path = install_path .. '/plugin/packer_compiled.lua',
      display = { non_interactive = true },
    },
  }
end
_G.load_config = function()
  require('telescope').setup()
end
if vim.fn.isdirectory(install_path) == 0 then
  print("Installing Telescope and dependencies.")
  vim.fn.system { 'git', 'clone', '--depth=1', 'https://github.com/wbthomason/packer.nvim', install_path }
end
load_plugins()
require('packer').sync()
vim.cmd [[autocmd User PackerComplete ++once echo "Ready!" | lua load_config()]]
@vanaigr vanaigr added the bug Something isn't working label Apr 1, 2024
@vanaigr
Copy link
Author

vanaigr commented Apr 1, 2024

:help for 'help' contains this paragraph:

 {subject} can include wildcards such as "*", "?" and
"[a-z]":
   :help z?	jump to help for any "z" command
   :help z.	jump to the help for "z."
But when a tag exists it is taken literally:
   :help :?	jump to help for ":?"

And in help [==]@en produced by telescope, '[' and ']' are treated as special characters.

if cmd == "default" or cmd == "horizontal" then
vim.cmd("help " .. selection.value)
elseif cmd == "vertical" then
vim.cmd("vert help " .. selection.value)
elseif cmd == "tab" then
vim.cmd("tab help " .. selection.value)
end

@vanaigr
Copy link
Author

vanaigr commented Apr 1, 2024

I think this might work for all characters, although I couldn't test it for non-ascii:

local lang = 'en'
local subject= '[==]'
local code_points = vim.fn.str2list(subject)
local escaped_str = '\\v'
for _, code in ipairs(code_points) do
    escaped_str = escaped_str .. '%U' .. string.format('%x', code)
end
escaped_str = escaped_str .. '@' .. lang
vim.cmd.help(escaped_str)

@jamestrew
Copy link
Contributor

Oof, I'm almost tempted to say "it's not our problem" considering :h [==] nets the same result...

Your solution is pretty interesting though - first time actually learning about all this "magic".
But I think your concern is valid - particularly for non-utf8 encodings...

@vanaigr
Copy link
Author

vanaigr commented Apr 29, 2024

couldn't test it for non-ascii

I tested it and it works for multibyte characters.

I also wrote a test to see which other help tags are affected:
Results (for 0.9.5):

1605 :[vV\x16] autocmd.txt
autocmd.txt:755
repeat.txt:49

4482 [+cmd] editing.txt
editing.txt:489
motion.txt:315

4483 [..] pattern.txt
pattern.txt:1179
repeat.txt:16

4505 [==] pattern.txt
pattern.txt:1174
change.txt:564

8485 s/\= change.txt
change.txt:896
change.txt:184

8489 s/\\ change.txt
change.txt:813
change.txt:785

How to test:

# move tags file from neovim's runtime/doc/tags to current directory
nvim --clean -u tags-test.lua
tags-test.lua
-- quite slow!

local function goto_fixed(tag)
    local lang = 'en'
    local code_points = vim.fn.str2list(tag)
    local escaped_str = '\\v'
    for _, code in ipairs(code_points) do
        escaped_str = escaped_str .. '%U' .. string.format('%x', code)
    end
    escaped_str = escaped_str .. '@' .. lang
    vim.cmd.help(escaped_str)
end
local function goto_orig(tag)
    vim.cmd.help(tag .. '@en')
end
local function get_pos()
    local name = vim.fn.expand('%:t')
    local lnum = vim.fn.line('.')
    return name .. ':' .. lnum
end

vim.cmd('syntax off')
vim.cmd('set syntax=off')

local count = 0
local lines = vim.fn.readfile('tags')
Result = {}
for i, line in ipairs(lines) do
    local tag, file, _ = unpack(vim.split(line, '\t'))

    goto_fixed(tag)
    local fixed_pos = get_pos()
    goto_orig(tag)
    local orig_pos = get_pos()

    if fixed_pos ~= orig_pos then
        table.insert(Result, i..' '..tag..' '..file)
        table.insert(Result, fixed_pos)
        table.insert(Result, orig_pos)
        table.insert(Result, '')
    end

    ::next::

    count = count + 1
    if count == 100 then
        print(i, 'of', #lines)
        vim.cmd('redraw!')
        count = 0
    end
end

vim.cmd('close')

print('Done')
vim.api.nvim_buf_set_lines(0, 0, 0, false, Result)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants