🐻 minimal ui2 fuzzy finder for Neovim codeberg.org/comfysage/artio.nvim
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(builtins): improve smart picker

- add buffer info
- fix `matchproximity()`

robin 8aedc0cd 207c1ece

+84 -37
+84 -37
lua/artio/builtins.lua
··· 317 317 ---@param item string 318 318 ---@return integer score 319 319 local function matchproximity(currentfile, item) 320 + currentfile = vim.fs.abspath(currentfile) 321 + local parts = vim.split(currentfile, "/", { trimempty = true }) 320 322 item = vim.fs.abspath(item) 321 323 322 324 return vim.iter(ipairs(vim.split(item, "/", { trimempty = true }))):fold(0, function(score, i, part) 323 - if part == currentfile[i] then 325 + if part == parts[i] then 324 326 return score + 50 325 327 end 326 328 return score ··· 332 334 --- - proportionally boosts items that match closely to the current file in proximity within the filesystem 333 335 builtins.smart = function(props) 334 336 props = props or {} 335 - local currentfile = vim.api.nvim_buf_get_name(0) 337 + local currentbuf = vim.fn.bufnr("%") 338 + local currentfile = vim.api.nvim_buf_get_name(currentbuf) 336 339 currentfile = vim.fs.abspath(currentfile) 340 + local alternatebuf = vim.fn.bufnr("#") 341 + local lbufnr = vim.fn.bufnr("$") 342 + local bufnr_len = #(string.format("%d", lbufnr)) 337 343 338 344 props.findprg = props.findprg or findprg 339 345 local base_dir = vim.fn.getcwd(0) ··· 345 351 .iter(find_buffers()) 346 352 :map(function(buf) 347 353 local v = vim.api.nvim_buf_get_name(buf) 348 - return vim.fs.abspath(v) 354 + return { path = vim.fs.abspath(v), buf = buf } 349 355 end) 350 356 :totable() 351 357 352 - local items = vim.list.unique(vim.iter({ lst, recentlst }):flatten(1):totable()) 358 + local items = vim.list.unique( 359 + vim 360 + .iter({ recentlst, lst }) 361 + :flatten(1) 362 + :map(function(x) 363 + if type(x) == "string" then 364 + x = { path = x } 365 + end 366 + return x 367 + end) 368 + :map(function(x) 369 + if x.buf and x.buf == currentbuf then 370 + x.current = true 371 + elseif x.buf and x.buf == alternatebuf then 372 + x.alt = true 373 + end 374 + return x 375 + end) 376 + :totable(), 377 + function(x) 378 + return x.path 379 + end 380 + ) 353 381 354 382 return artio.pick(extend({ 355 383 prompt = "smart", 356 384 items = items, 357 - fn = artio.mergesorters("base", function(l, input) 358 - if #input == 0 then 385 + fn = artio.mergesorters( 386 + "base", 387 + -- use default sorter but only display buffer files if input is empty 388 + function(l, input) 389 + if #input == 0 then 390 + return vim 391 + .iter(l) 392 + :map(function(item) 393 + if not item.v.buf then 394 + return 395 + end 396 + return { item.id, {}, 0 } 397 + end) 398 + :totable() 399 + end 400 + 401 + return artio.sorter(l, input) 402 + end, 403 + -- boost files that are open as buffers 404 + function(l, _) 359 405 return vim 360 406 .iter(l) 361 - :map(function(v) 362 - if not vim.tbl_contains(recentlst, v.v) then 407 + :map(function(item) 408 + if not item.v.buf then 363 409 return 364 410 end 365 - return { v.id, {}, 0 } 411 + return { item.id, {}, 100 } 412 + end) 413 + :totable() 414 + end, 415 + -- boost files that are close in proximity to the current file 416 + function(l, _) 417 + return vim 418 + .iter(l) 419 + :map(function(item) 420 + return { item.id, {}, matchproximity(currentfile, item.v.path) } 366 421 end) 367 422 :totable() 368 423 end 369 - 370 - return artio.sorter(l, input) 371 - end, function(l, _) 372 - return vim 373 - .iter(l) 374 - :map(function(v) 375 - if not vim.tbl_contains(recentlst, v.v) then 376 - return 377 - end 378 - return { v.id, {}, 100 } 379 - end) 380 - :totable() 381 - end, function(l, _) 382 - return vim 383 - .iter(l) 384 - :map(function(v) 385 - return { v.id, {}, matchproximity(currentfile, v.v) } 386 - end) 387 - :totable() 388 - end), 389 - on_close = function(text, _) 424 + ), 425 + on_close = function(v, _) 390 426 vim.schedule(function() 391 - vim.cmd.edit(text) 427 + vim.cmd.edit(v.path) 392 428 end) 393 429 end, 394 - format_item = function(item) 395 - return vim.fs.relpath(base_dir, item) or item 430 + format_item = function(v) 431 + local path = vim.fs.relpath(base_dir, v.path) or v.path 432 + local ind = v.current and "%" or v.alt and "#" or " " 433 + return v.buf and string.format("%s (%0" .. bufnr_len .. "d) %s", ind, v.buf, path) 434 + or string.format("%s " .. string.rep(" ", bufnr_len + 2) .. " %s", ind, path) 435 + end, 436 + hl_item = function(_) 437 + return { 438 + { { 0, 2 }, "Special" }, 439 + { { 2, 3 }, "Delimiter" }, 440 + { { 3, 3 + bufnr_len }, "Number" }, 441 + { { 3 + bufnr_len, 3 + bufnr_len + 1 }, "NonText" }, 442 + } 396 443 end, 397 444 get_icon = config.get().opts.use_icons and function(item) 398 - return require("mini.icons").get("file", item.v) 445 + return require("mini.icons").get("file", item.v.path) 399 446 end or nil, 400 - preview_item = function(item) 401 - return vim.fn.bufadd(item) 447 + preview_item = function(v) 448 + return vim.fn.bufadd(v.path) 402 449 end, 403 450 actions = extend( 404 451 {}, 405 452 utils.make_setqflistactions(function(item) 406 - return { filename = item.v } 453 + return { filename = item.v.path } 407 454 end) 408 455 ), 409 456 }, props))