Skip to content
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
42 changes: 33 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,25 @@ return {

-- Dependencies are lazy-loaded by default unless specified otherwise.
dependencies = {
{ 'nvim-telescope/telescope.nvim' },
{ 'nvim-telescope/telescope-ui-select.nvim' },
{ 'akinsho/toggleterm.nvim' },
{ 'nvim-lua/plenary.nvim' },
{ 'folke/which-key.nvim' },
{ 'nvim-treesitter/nvim-treesitter' }
{ 'nvim-treesitter/nvim-treesitter' },

-- install picker based on your likeing
{ 'akinsho/toggleterm.nvim' },

-- install picker based on your likeing, remove or ignore rest

-- telescope
{ 'nvim-telescope/telescope.nvim' },
{ 'nvim-telescope/telescope-ui-select.nvim' },

-- Snacks picker
{'folke/snacks.nvim', opts = {
picker = {enabled = true, ui_select = true }
}},

-- Mini.Pick
{'nvim-mini/mini.pick'},
},
}
```
Expand All @@ -55,7 +66,8 @@ return {
vim.g.pioConfig ={
lsp = 'clangd', -- value: clangd | ccls
clangd_source = 'ccls', -- value: ccls | compiledb, For detailed explation check :help platformio-clangd_source
picker_backend = 'auto', -- value: auto | telescope | ui_select, default: auto, check :help platformio-picker
picker_backend = 'auto', -- value: auto | telescope | snacks | mini_pick | ui_select
-- default: auto, check :help platformio-picker
menu_key = '<leader>\\', -- replace this menu key to your convenience
debug = false -- enable debug messages
}
Expand Down Expand Up @@ -111,11 +123,23 @@ return {
-- Dependencies are lazy-loaded by default unless specified otherwise.
dependencies = {
{ 'akinsho/toggleterm.nvim' },
{ 'nvim-telescope/telescope.nvim' },
{ 'nvim-telescope/telescope-ui-select.nvim' },
{ 'nvim-lua/plenary.nvim' },
{ 'folke/which-key.nvim' },
{ 'nvim-treesitter/nvim-treesitter' }
{ 'nvim-treesitter/nvim-treesitter' },

-- install picker based on your likeing, remove or ignore rest

-- telescope
{ 'nvim-telescope/telescope.nvim' },
{ 'nvim-telescope/telescope-ui-select.nvim' },

-- Snacks picker
{'folke/snacks.nvim', opts = {
picker = {enabled = true, ui_select = true }
}},

-- Mini.Pick
{'nvim-mini/mini.pick'},
},
}
```
Expand Down
24 changes: 19 additions & 5 deletions doc/platformio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,31 @@ picker_backend *platformio-picker*

Allowed values:
- `auto`
Default. Tries Telescope backend first. If Telescope is unavailable,
falls back to `vim.ui.select` backend.
Default. Tries backends in this order, using the first one that is
installed: `telescope`, then `snacks`, then `mini_pick`, then
`ui_select`. `ui_select` is always available since it only needs
Neovim's built-in `vim.ui.select`, so `auto` never fails to find
a backend.

- `telescope`
Force Telescope picker backend. If Telescope backend cannot be loaded,
plugin falls back to `vim.ui.select` as a safety fallback.
Force the Telescope picker backend (requires telescope.nvim).

- `snacks`
Force the Snacks picker backend (requires folke/snacks.nvim with
its `picker` module enabled).

- `mini_pick`
Force the mini.pick backend (requires nvim-mini/mini.pick).

- `ui_select`
Force `vim.ui.select` backend. This works with Neovim built-in
`vim.ui.select` or any plugin that overrides it (for example,
telescope-ui-select, dressing.nvim, snacks picker adapters, etc.).
telescope-ui-select, dressing.nvim, snacks' `ui_select` option,
mini.pick's `MiniPick.ui_select`, etc.).

Unlike `auto`, explicitly requesting `telescope`, `snacks`, `mini_pick`,
or `ui_select` does NOT fall back to another backend if the requested
one isn't installed—it reports an error and the picker does not open.

menu_key *platformio-menu_key*
Key prefix that opens the PlatformIO which-key menu (requires
Expand Down
27 changes: 16 additions & 11 deletions lua/platformio/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -189,17 +189,22 @@ function M.setup(user_config)
user_config.clangd_source = M.config.clangd_source
end
end
if
user_config.picker_backend
and user_config.picker_backend ~= 'auto'
and user_config.picker_backend ~= 'telescope'
and user_config.picker_backend ~= 'ui_select'
then
vim.api.nvim_echo(
{ { 'Invalid picker backend {allowed "auto", "telescope" or "ui_select"} (default "' .. M.config.picker_backend .. '" will be used)', 'ErrorMsg' } },
true,
{}
)
local valid_picker_backends = {
auto = true,
telescope = true,
snacks = true,
mini_pick = true,
ui_select = true,
}
if user_config.picker_backend and not valid_picker_backends[user_config.picker_backend] then
vim.api.nvim_echo({
{
'Invalid picker backend {allowed "auto", "telescope", "snacks", "mini_pick" or "ui_select"} (default "'
.. M.config.picker_backend
.. '" will be used)',
'ErrorMsg',
},
}, true, {})
user_config.picker_backend = M.config.picker_backend
end

Expand Down
47 changes: 25 additions & 22 deletions lua/platformio/pickers/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ local M = {}

local config = require('platformio').config

local AUTO_ORDER = { 'telescope', 'snacks', 'mini_pick', 'ui_select' }

local function load_backend(name)
local ok, backend = pcall(require, 'platformio.pickers.' .. name)
if ok then
Expand All @@ -10,54 +12,55 @@ local function load_backend(name)
return nil
end

-- 'auto' tries backends in order and silently falls back; an explicit backend
-- name that isn't installed reports why and does not fall back to another one.
local function get_backend()
local backend_name = config.picker_backend or 'auto'

if backend_name == 'telescope' then
return load_backend('telescope') or load_backend('ui_select')
if backend_name == 'auto' then
for _, name in ipairs(AUTO_ORDER) do
local backend = load_backend(name)
if backend then
return backend
end
end
vim.notify('No picker backend available for PlatformIO.', vim.log.levels.ERROR)
return nil
end

if backend_name == 'ui_select' then
return load_backend('ui_select')
local backend = load_backend(backend_name)
if not backend then
vim.notify(string.format('PlatformIO: picker backend "%s" is not installed.', backend_name), vim.log.levels.ERROR)
end

return load_backend('telescope') or load_backend('ui_select')
return backend
end

function M.pick_board(boards, on_select)
local backend = get_backend()
if not backend then
vim.notify('No picker backend available for PlatformIO.', vim.log.levels.ERROR)
return
if backend then
backend.pick_board(boards, on_select)
end
backend.pick_board(boards, on_select)
end

function M.pick_framework(frameworks, on_select)
local backend = get_backend()
if not backend then
vim.notify('No picker backend available for PlatformIO.', vim.log.levels.ERROR)
return
if backend then
backend.pick_framework(frameworks, on_select)
end
backend.pick_framework(frameworks, on_select)
end

function M.pick_library(libraries, on_select)
local backend = get_backend()
if not backend then
vim.notify('No picker backend available for PlatformIO.', vim.log.levels.ERROR)
return
if backend then
backend.pick_library(libraries, on_select)
end
backend.pick_library(libraries, on_select)
end

function M.pick_terminal(terminals, on_select)
local backend = get_backend()
if not backend then
vim.notify('No picker backend available for PlatformIO.', vim.log.levels.ERROR)
return
if backend then
backend.pick_terminal(terminals, on_select)
end
backend.pick_terminal(terminals, on_select)
end

return M
116 changes: 116 additions & 0 deletions lua/platformio/pickers/mini_pick.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
local MiniPick = require('mini.pick')

local M = {}

local SEP = ' | '
local COLUMN_NS = vim.api.nvim_create_namespace('platformio_pick_columns')

local function to_items(list, label_fn)
local items = {}
for i, entry in ipairs(list) do
items[i] = { text = label_fn(entry), data = entry }
end
return items
end

local function pad(text, width)
text = text or ''
if #text >= width then
return text:sub(1, width)
end
return text .. string.rep(' ', width - #text)
end

local function framework_label(framework)
return framework
end

local BOARD_NAME_W, BOARD_VENDOR_W = 35, 20

local function board_label(board)
return pad(board.name or '', BOARD_NAME_W) .. SEP .. pad(board.vendor or '', BOARD_VENDOR_W) .. SEP .. (board.platform or '')
end

local LIB_NAME_W, LIB_OWNER_W = 20, 20

local function library_label(lib)
local owner = (lib.owner and lib.owner.username) or ''
return pad(lib.name or '', LIB_NAME_W) .. SEP .. pad(owner, LIB_OWNER_W) .. SEP .. (lib.description or '')
end

local function terminal_label(entry)
local is_hidden = vim.api.nvim_buf_is_loaded(entry.term.bufnr) and (vim.fn.bufwinid(entry.term.bufnr) == -1)
return string.format('%d:%s (hidden: %s)', entry.term.id, entry.termtype, tostring(is_hidden))
end

local function data_preview(buf_id, item)
vim.bo[buf_id].filetype = 'lua'
vim.bo[buf_id].modifiable = true
vim.api.nvim_buf_set_lines(buf_id, 0, -1, false, vim.split(vim.inspect(item.data), '\n'))
vim.bo[buf_id].modifiable = false
end

-- Colors the two padded columns and the separators on top of mini.pick's default
-- rendering (which still handles line text + query match highlighting).
local function columns_show(col1_w, col2_w, hl1, hl2)
return function(buf_id, items, query)
MiniPick.default_show(buf_id, items, query)
vim.api.nvim_buf_clear_namespace(buf_id, COLUMN_NS, 0, -1)
local sep_len = #SEP
local col2_start = col1_w + sep_len
local col2_end = col2_start + col2_w
local opts = { hl_mode = 'combine', priority = 100 }
for i = 1, #items do
local row = i - 1
pcall(vim.api.nvim_buf_set_extmark, buf_id, COLUMN_NS, row, 0, vim.tbl_extend('force', opts, { end_col = col1_w, hl_group = hl1 }))
pcall(vim.api.nvim_buf_set_extmark, buf_id, COLUMN_NS, row, col1_w, vim.tbl_extend('force', opts, { end_col = col2_start, hl_group = 'Delimiter' }))
pcall(vim.api.nvim_buf_set_extmark, buf_id, COLUMN_NS, row, col2_start, vim.tbl_extend('force', opts, { end_col = col2_end, hl_group = hl2 }))
pcall(
vim.api.nvim_buf_set_extmark,
buf_id,
COLUMN_NS,
row,
col2_end,
vim.tbl_extend('force', opts, { end_col = col2_end + sep_len, hl_group = 'Delimiter' })
)
end
end
end

local board_show = columns_show(BOARD_NAME_W, BOARD_VENDOR_W, 'Title', 'Comment')
local library_show = columns_show(LIB_NAME_W, LIB_OWNER_W, 'Title', 'Comment')

local function open_picker(items, name, on_select, preview_fn, show_fn)
MiniPick.start({
source = {
items = items,
name = name,
preview = preview_fn,
show = show_fn,
choose = function(item)
if item then
on_select(item.data)
end
return false
end,
},
})
end

function M.pick_framework(frameworks, on_select)
open_picker(to_items(frameworks, framework_label), 'Frameworks', on_select)
end

function M.pick_board(boards, on_select)
open_picker(to_items(boards, board_label), 'Boards', on_select, data_preview, board_show)
end

function M.pick_library(libraries, on_select)
open_picker(to_items(libraries, library_label), 'Libraries', on_select, data_preview, library_show)
end

function M.pick_terminal(terminals, on_select)
open_picker(to_items(terminals, terminal_label), 'PIO terminals', on_select)
end

return M
Loading
Loading