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

feature: Pick command #1488

Open
1 task done
milisims opened this issue Mar 2, 2025 · 0 comments
Open
1 task done

feature: Pick command #1488

milisims opened this issue Mar 2, 2025 · 0 comments
Labels
enhancement New feature or request

Comments

@milisims
Copy link

milisims commented Mar 2, 2025

Did you check the docs?

  • I have read all the snacks.nvim docs

Is your feature request related to a problem? Please describe.

I use the vim cmdline far more often than specialized keymaps, and I use a lot of commandline abbreviations. For example, if I want to pick files from a specific directory, I have to write out lua Snacks.picker.files({ cwd = ... }), and while that's expressive and a better programmatic interface than the commandline, it would be nice to just have one abbreviation for something like Pick files where I could just write cwd=... after.

Describe the solution you'd like

A Pick command with useful completions. Sources followed by options, something like:
Pick files cwd=dir\ with\ escaped\ spaces layout=ivy hidden=true

Describe alternatives you've considered

Currently I'm using this. It completes booleans, 'focus', 'layout', and 'cwd', but any key in opts that is not a table will be completed as a key.

Using fargs lets escaped whitespace work without any effort, but requires no spaces per key/value. I like this solution overall.

      callback = function(cmd)
        local opts = { source = cmd.fargs[1] }

        for i = 2, #cmd.fargs do
          local k, v = cmd.fargs[i]:match('^(%w+)=(.*)$') -- escaping ws works
          if not k then
            error('Invalid argument: ' .. cmd.fargs[i])
          end
          if v == 'true' then
            opts[k] = true
          elseif v == 'false' then
            opts[k] = false
          else
            opts[k] = vim.fn.expandcmd(v) -- lets $ENV , %:p, etc work
          end
        end

        Snacks.picker.pick(opts)
      end

      -- arglead, cmdline, cursorpos
      complete = function(arglead, cmdline, _)
        if cmdline == 'Pick ' then
          return vim.tbl_keys(Snacks.picker.config.get().sources --[[@as table]])
        end

        local opts = Snacks.picker.config.get({ source = cmdline:match('Pick (%S+)') })

        local opt = arglead:match('^(%w+)=')
        if not opt then
          local ret = { 'cwd=' }
          local skip = { enabled = true, source = true }

          for k, v in pairs(opts) do
            if not skip[k] and type(v) ~= 'table' then
              table.insert(ret, k .. '=')
            end
          end
          return ret
        end

        if opt == 'focus' then
          return { 'input', 'list' }
        elseif opt == 'finder' then
          return vim
            .iter(Snacks.picker.config.get().sources)
            :map(function(_, v)
              return type(v.finder) == 'string' and v.finder or nil
            end)
            :totable()
        elseif opt == 'layout' then
          return vim.tbl_keys(Snacks.picker.config.get().layouts)
        elseif opt == 'cwd' then
          return vim.fn.getcompletion(arglead:sub(#opt + 2), 'dir', true)
        elseif type(opts[opt]) == 'boolean' then
          return { 'true', 'false' }
        end
      end

Additional context

No response

@milisims milisims added the enhancement New feature or request label Mar 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant