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

Enable winopts for all commands with positioning relative to the cursor #545

Closed
1 task
wimstefan opened this issue Oct 17, 2022 · 7 comments
Closed
1 task
Labels
question Further information is requested

Comments

@wimstefan
Copy link

Info

  • Operating System: Gentoo Base System release 2.9 (~amd64)

  • Shell: zsh 5.9

  • Terminal: wezterm 20221016-210733-84de038d

  • nvim --version: NVIM v0.9.0-dev-115-g042eb74

  • fzf --version: 0.34.0 (04d0b02)

  • The issue is reproducible with mini.sh

fzf-lua configuration
local fzf_lua = require('fzf-lua')

local bottom_row = {
  height = 0.4,
  width = 1,
  row = 1,
  col = 0,
  preview = {
    layout = 'horizontal',
    horizontal = 'right:55%',
  }
}
local right_popup = {
  height = 0.97,
  width = 0.2,
  row = 0.3,
  col = 1
}
local cursor_popup = {
  relative = 'cursor',
  height = 0.2,
  width = 0.3
}
local right_column = {
  height = 1,
  width = 0.45,
  row = 0,
  col = 1,
  preview = {
    layout = 'vertical',
    vertical = 'down:65%'
  }
}

fzf_lua.register_ui_select({
  winopts = cursor_popup
})

fzf_lua.setup({
  global_resume = true,
  winopts = bottom_row,
  builtin = {
    winopts = right_column
  },
  colorschemes = {
    winopts = right_popup
  },
  diagnostics = {
    winopts = right_column
  },
  files = {
    prompt = 'Files❯ ',
  },
  git = {
    branches = {
      winopts = right_column
    },
    bcommits = {
      winopts = right_column
    },
    commits = {
      winopts = right_column
    },
    status = {
      winopts = right_column
    },
  },
  grep = {
    cmd = 'ugrep -RIjnkzs --hidden --ignore-files --exclude-dir=".git"',
    winopts = right_column
  },
  highlights = {
    winopts = right_column
  },
  lsp = {
    ui_select = true,
    code_actions = {
      winopts = cursor_popup
    }
  },
  spell_suggest = {
    winopts = cursor_popup
  }
})

Description

Is it possible to make winopts available for all commands?

After switching from Telescope I tried to mimic the get_cursor theme which is really useful for spell suggestions or code actions with a popup relative to the cursor. You can see my attempts to achieve that above but until now I didn't succeed (due to a lack of deeper understanding how things work ;))

@ibhagwan ibhagwan added the question Further information is requested label Oct 17, 2022
@ibhagwan
Copy link
Owner

Is it possible to make winopts available for all commands?

The winopts directly under setup is used as the default one for all commands (I.e. what you set to bottom_row), if you specify another winopts under a provider it will be merged onto the global one overriding values, e.g. the one under grep (right_column) will take precedence when running grep/live grep commands.winopts can also be specified as part of the command direct call which will then be merged with both the global and the provider one, I.e. :lua require'fzf-lua'.files({ winopts = … }).

After switching from Telescope I tried to mimic the get_cursor theme which is really useful for spell suggestions or code actions with a popup relative to the cursor.

The current window is hard coded as relative = editor, if you wish to change that to cursor I can have another relative field under winopts which will be relayed to nvim_open_win, let me know if this is what you need?

@wimstefan
Copy link
Author

Thanks a lot for your detailed explanation 👍 So I understood the configuration options correct at least ;)
I'm wondering though why the winopts setting for spell_suggest in my config is not recognized? And the keybinding I'm using only works if I use a function:

vim.keymap.set('n', '<Leader>fs', function() require('fzf-lua').spell_suggest({ winopts = cursor_popup }) end, { desc = 'Fzf: spell suggest' }

A direct call uses the global winopt settings and opens a floating window at the bottom:

vim.keymap.set('n', '<Leader>fs', require('fzf-lua').spell_suggest, { desc = 'Fzf: spell suggest' })

That's still not quite clear for me. But at least I got a working configuration now. Many thanks for that!

And a relative field under winopts would be mightily appreciated! :D

@ibhagwan
Copy link
Owner

Thanks a lot for your detailed explanation 👍 So I understood the configuration options correct at least ;)
I'm wondering though why the winopts setting for spell_suggest in my config is not recognized? And the keybinding I'm using only works if I use a function:

That’s because for some odd reason I decided to define some providers under a neovim section, this doesn’t make sense anymore so I think I’ll change it, for now you can just use setup({ nvim = { spell_suggest = { … } })

And a relative field under winopts would be mightily appreciated! :D

Will add it and keep this thread updated.

@ibhagwan
Copy link
Owner

c90a88b - update to this and spell_suggest should work directly under setup.

And a relative field under winopts would be mightily appreciated! :D

This turns out to be already working without any changes :-)

local relative = self.winopts.relative or 'editor'

For spell suggest you can use:

:lua require'fzf-lua'.spell_suggest({ winopts = {relative="cursor"} })

Note that using this breaks preview/scrollbar layout so use this only without preview.

@wimstefan
Copy link
Author

Now that looks better already! :)
The last thing nagging is the row position of the popup: it's still on the bottom and not on the cursor position.

My current configuration
    use({
      'ibhagwan/fzf-lua',
      requires = {
        { 'junegunn/fzf', run = './install --all --xdg' }
      },
      config = function()
        local fzf_lua = require('fzf-lua')

        local bottom_row = {
          height = 0.4,
          width = 1,
          row = 1,
          col = 0,
          preview = {
            layout = 'horizontal',
            horizontal = 'right:55%',
          }
        }
        local right_popup = {
          height = 0.97,
          width = 0.2,
          row = 0.3,
          col = 1
        }
        local cursor_popup = {
          relative = 'cursor',
          height = 0.2,
          width = 0.3
        }
        local right_column = {
          height = 1,
          width = 0.45,
          row = 0,
          col = 1,
          preview = {
            layout = 'vertical',
            vertical = 'down:65%'
          }
        }

        local function show_notifications()
          local opts = {}
          opts.prompt = 'Notifications> '
          opts.fzf_opts = {
            ['--no-multi'] = ''
          }

          local entries = require('notify').history()
          local notifications = {}
          for i = 1, #entries do
            local all_messages = ''
            local formatted_messages = {}

            local function diag_level_code(diag)
              local level = entries[i].level
              if level == "ERROR" then
                return fzf_lua.utils.ansi_codes.red(diag)
              elseif level == "WARN" then
                return fzf_lua.utils.ansi_codes.yellow(diag)
              elseif level == "DEBUG" then
                return fzf_lua.utils.ansi_codes.yellow(diag)
              elseif level == "INFO" then
                return fzf_lua.utils.ansi_codes.green(diag)
              elseif level == "HINT" then
                return fzf_lua.utils.ansi_codes.blue(diag)
              end
            end

            local function format_msg(...)
              for _, entry in ipairs(...) do
                table.insert(formatted_messages, '\n' .. entry)
              end
              return formatted_messages
            end

            local messages = entries[i].message
            if #messages > 1 then
              format_msg(messages)
              all_messages = table.concat(formatted_messages)
            else
              all_messages = messages[1]
            end

            table.insert(notifications,
              string.format('%-5s  %s %16s %s %s',
                fzf_lua.utils.ansi_codes.blue(vim.fn.strftime('%F %H:%M', entries[i].time)),
                diag_level_code(entries[i].icon),
                diag_level_code(entries[i].level),
                fzf_lua.utils.ansi_codes.cyan('« ' .. entries[i].title[1] .. ' »'),
                all_messages
              )
            )
          end

          if vim.tbl_isempty(notifications) then return end
          fzf_lua.fzf_exec(notifications, opts)
        end

        vim.keymap.set('n', '<Leader>F', require('fzf-lua').builtin, { desc = 'Fzf: builtin' })
        vim.keymap.set('n', '<Leader>b', require('fzf-lua').buffers, { desc = 'Fzf: buffers' })
        vim.keymap.set('n', '<Leader>c', require('fzf-lua').colorschemes, { desc = 'Fzf: colorschemes' })
        vim.keymap.set('n', '<Leader>f', require('fzf-lua').files, { desc = 'Fzf: files' })
        vim.keymap.set('n', '<Leader>o', require('fzf-lua').oldfiles, { desc = 'Fzf: oldfiles' })
        vim.keymap.set('n', '<Leader>fg', require('fzf-lua').lgrep_curbuf, { desc = 'Fzf: grep current file' })
        vim.keymap.set('n', '<Leader>fG', require('fzf-lua').live_grep_native, { desc = 'Fzf: grep all files' })
        vim.keymap.set('n', '<Leader>h', require('fzf-lua').help_tags, { desc = 'Fzf: help' })
        vim.keymap.set('n', '<Leader>M', require('fzf-lua').man_pages, { desc = 'Fzf: man' })
        vim.keymap.set('n', '<Leader>m', require('fzf-lua').marks, { desc = 'Fzf: marks' })
        vim.keymap.set('n', '<Leader>r', require('fzf-lua').registers, { desc = 'Fzf: registers' })
        vim.keymap.set('n', '<Leader>fgb', require('fzf-lua').git_bcommits, { desc = 'Fzf: git buffer commits' })
        vim.keymap.set('n', '<Leader>fgc', require('fzf-lua').git_commits, { desc = 'Fzf: git commits' })
        vim.keymap.set('n', '<Leader>fgf', require('fzf-lua').git_files, { desc = 'Fzf: git files' })
        vim.keymap.set('n', '<Leader>fgs', require('fzf-lua').git_status, { desc = 'Fzf: git status' })
        vim.keymap.set('n', '<Leader>fc', require('fzf-lua').command_history, { desc = 'Fzf: command history' })
        vim.keymap.set('n', '<Leader>fm', require('fzf-lua').keymaps, { desc = 'Fzf: keymaps' })
        vim.keymap.set('n', '<Leader>fq', require('fzf-lua').quickfix, { desc = 'Fzf: quickfix' })
        vim.keymap.set('n', '<Leader>fs', require('fzf-lua').spell_suggest, { desc = 'Fzf: spell suggest' })
        vim.keymap.set('n', '<Leader>fw', require('fzf-lua').grep_cword, { desc = 'Fzf: grep string' })
        vim.keymap.set('n', '<Leader>fn', function() show_notifications() end, { desc = 'Fzf: notifications' })

        fzf_lua.register_ui_select({
          winopts = cursor_popup
        })

        fzf_lua.setup({
          global_resume = true,
          winopts = bottom_row,
          builtin = {
            winopts = right_column
          },
          colorschemes = {
            winopts = right_popup
          },
          diagnostics = {
            winopts = right_column
          },
          files = {
            prompt = 'Files❯ ',
          },
          git = {
            branches = {
              winopts = right_column
            },
            bcommits = {
              winopts = right_column
            },
            commits = {
              winopts = right_column
            },
            status = {
              winopts = right_column
            },
          },
          grep = {
            cmd = 'ugrep -RIjnkzs --hidden --ignore-files --exclude-dir=".git"',
            winopts = right_column
          },
          highlights = {
            winopts = right_column
          },
          lsp = {
            code_actions = {
              winopts = cursor_popup
            }
          },
          spell_suggest = {
            winopts = cursor_popup
          }
        })
      end
    })

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 18, 2022

Have you tried this? It pops up right at the cursor position

:lua require'fzf-lua'.spell_suggest({ winopts = {relative="cursor",row=0, col=0, height=0.2, width=0.5} }
)

Also, since sizes/positioning are relative sizes to current neovim window anything >1.0 is sent as is to nvim_open_win, so if you wanted to the popup to be one line below the cursor you could use:

row=1 would mean "last line of neovim window"

:lua require'fzf-lua'.spell_suggest({ winopts = {relative="cursor",row=1.01, col=0, height=0.2, width=0.5
} })

@wimstefan
Copy link
Author

This is simply brilliant 😃️ ❤️
It does precisely what I was imagining but couldn't realize myself :)
Thank you so much Sir! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants