diff --git a/lua/telescope/actions.lua b/lua/telescope/actions.lua index abd5bf8..f1b4a38 100644 --- a/lua/telescope/actions.lua +++ b/lua/telescope/actions.lua @@ -78,5 +78,23 @@ actions.close = function(prompt_bufnr) vim.cmd(string.format([[bwipeout! %s]], prompt_bufnr)) end +actions.set_command_line = function(prompt_bufnr) + local entry = actions.get_selected_entry(prompt_bufnr) + + actions.close(prompt_bufnr) + + vim.cmd(entry.value) +end + +-- TODO: Think about how to do this. +actions.insert_value = function(prompt_bufnr) + local entry = actions.get_selected_entry(prompt_bufnr) + + vim.schedule(function() + actions.close(prompt_bufnr) + end) + + return entry.value +end return actions diff --git a/lua/telescope/builtin.lua b/lua/telescope/builtin.lua index 42156f6..afc104c 100644 --- a/lua/telescope/builtin.lua +++ b/lua/telescope/builtin.lua @@ -2,8 +2,16 @@ A collection of builtin pipelines for telesceope. Meant for both example and for easy startup. + +Any of these functions can just be called directly by doing: + +:lua require('telescope.builtin').__name__() + +This will use the default configuration options. + Other configuration options still in flux at the moment --]] +local actions = require('telescope.actions') local finders = require('telescope.finders') local previewers = require('telescope.previewers') local pickers = require('telescope.pickers') @@ -36,14 +44,11 @@ builtin.git_files = function(opts) previewer = previewers.cat, sorter = sorters.get_fuzzy_file(), }):find() - end builtin.live_grep = function(opts) local live_grepper = finders.new { - maximum_results = 1000, - - fn_command = function(self, prompt) + fn_command = function(_, prompt) -- TODO: Make it so that we can start searching on the first character. if not prompt or prompt == "" then return nil @@ -186,7 +191,7 @@ builtin.command_history = function(opts) local results = {} for i = 3, #history_list do local item = history_list[i] - local start, finish = string.find(item, "%d+ +") + local _, finish = string.find(item, "%d+ +") table.insert(results, string.sub(item, finish + 1)) end @@ -195,6 +200,15 @@ builtin.command_history = function(opts) finder = finders.new_table(results), sorter = sorters.get_norcalli_sorter(), + attach_mappings = function(map) + map('i', '', actions.set_command_line) + + -- TODO: Find a way to insert the text... it seems hard. + -- map('i', '', actions.insert_value, { expr = true }) + + return true + end, + -- TODO: Adapt `help` to this. -- previewer = previewers.cat, }):find() @@ -230,4 +244,26 @@ builtin.builtin = function(opts) }):find() end + +builtin.fd = function(opts) + local fd_string = nil + if 1 == vim.fn.executable("fd") then + fd_string = "fd" + elseif 1 == vim.fn.executable("fdfind") then + fd_string = "fdfind" + end + + if not fd_string then + print("You need to install fd") + return + end + + pickers.new(opts, { + prompt = 'Find Files', + finder = finders.new_oneshot_job {fd_string}, + previewer = previewers.cat, + sorter = sorters.get_fuzzy_file(), + }):find() +end + return builtin diff --git a/lua/telescope/finders.lua b/lua/telescope/finders.lua index b3c5022..56b823b 100644 --- a/lua/telescope/finders.lua +++ b/lua/telescope/finders.lua @@ -155,6 +155,24 @@ end -- } -- end +finders.new_job = function(command_generator) + return finders.new { + fn_command = function(_, prompt) + local command_list = command_generator(prompt) + if command_list == nil then + return nil + end + + local command = table.remove(command_list, 1) + + return { + command = command, + args = command_list, + } + end + } +end + finders.new_oneshot_job = function(command_list, entry_maker) command_list = vim.deepcopy(command_list) diff --git a/lua/telescope/mappings.lua b/lua/telescope/mappings.lua index ba618d4..6c8641c 100644 --- a/lua/telescope/mappings.lua +++ b/lua/telescope/mappings.lua @@ -29,14 +29,14 @@ end --[[ Usage: -mappings.apply_keymap(42, { +mappings.apply_keymap(42, , { n = { ["x"] = "just do this string", [""] = function(picker, prompt_bufnr) actions.close_prompt() - local filename = ... +> local filename = ... vim.cmd(string.format(":e %s", filename)) end, }, @@ -45,41 +45,75 @@ mappings.apply_keymap(42, { } }) --]] -mappings.apply_keymap = function(prompt_bufnr, buffer_keymap) +local telescope_map = function(prompt_bufnr, mode, key_bind, key_func, opts) + opts = opts or { + silent = true + } + + if type(key_func) == "string" then + a.nvim_buf_set_keymap( + prompt_bufnr, + mode, + key_bind, + key_func, + opts or { + silent = true + } + ) + else + local key_id = assign_function(prompt_bufnr, key_func) + local prefix = "" + + local map_string + if opts.expr then + map_string = string.format( + [[luaeval("require('telescope.mappings').execute_keymap(%s, %s)")]], + prompt_bufnr, + key_id + ) + else + if mode == "i" and not opts.expr then + prefix = "" + end + + map_string = string.format( + "%s:lua require('telescope.mappings').execute_keymap(%s, %s)", + prefix, + prompt_bufnr, + key_id + ) + end + + a.nvim_buf_set_keymap( + prompt_bufnr, + mode, + key_bind, + map_string, + opts + ) + end +end + +mappings.apply_keymap = function(prompt_bufnr, attach_mappings, buffer_keymap) + local applied_mappings = { n = {}, i = {} } + + local map = function(mode, key_bind, key_func, opts) + applied_mappings[mode][key_bind] = true + + telescope_map(prompt_bufnr, mode, key_bind, key_func, opts) + end + + if attach_mappings and not attach_mappings(map) then + return + end + for mode, mode_map in pairs(buffer_keymap) do + -- TODO: Probalby should not overwrite any keymaps + -- local buffer_keymaps + for key_bind, key_func in pairs(mode_map) do - if type(key_func) == "string" then - a.nvim_buf_set_keymap( - prompt_bufnr, - mode, - key_bind, - key_func, - { - silent = true - } - ) - else - local key_id = assign_function(prompt_bufnr, key_func) - local prefix = "" - if mode == "i" then - prefix = "" - end - - a.nvim_buf_set_keymap( - prompt_bufnr, - mode, - key_bind, - string.format( - "%s:lua require('telescope.mappings').execute_keymap(%s, %s)", - prefix, - prompt_bufnr, - key_id - ), - { - silent = true - } - ) - + if not applied_mappings[mode][key_bind] then + telescope_map(prompt_bufnr, mode, key_bind, key_func) end end end diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index 4b450f2..51b1162 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -14,7 +14,7 @@ local get_default = utils.get_default -- TODO: Make this work with deep extend I think. local extend = function(opts, defaults) - local result = vim.deepcopy(opts or {}) + local result = opts or {} for k, v in pairs(defaults or {}) do if result[k] == nil then result[k] = v @@ -69,7 +69,19 @@ function Picker:new(opts) sorter = opts.sorter, previewer = opts.previewer, - mappings = get_default(opts.mappings, default_mappings), + -- opts.mappings => overwrites entire table + -- opts.override_mappings => merges your table in with defaults. + -- Add option to change default + -- opts.attach(bufnr) + + --[[ + function(map) + map('n', '', actions.close, [opts]) + telescope.apply_mapping + end + --]] + -- mappings = get_default(opts.mappings, default_mappings), + attach_mappings = opts.attach_mappings, get_window_options = opts.get_window_options, selection_strategy = opts.selection_strategy, @@ -366,7 +378,7 @@ function Picker:find() finder = finder, }) - mappings.apply_keymap(prompt_bufnr, self.mappings) + mappings.apply_keymap(prompt_bufnr, self.attach_mappings, default_mappings) vim.cmd [[startinsert]] end diff --git a/lua/telescope/previewers.lua b/lua/telescope/previewers.lua index 48b3a1a..224cda0 100644 --- a/lua/telescope/previewers.lua +++ b/lua/telescope/previewers.lua @@ -10,6 +10,10 @@ Previewer.__index = Previewer local bat_options = " --style=grid --paging=always " -- --terminal-width=%s +-- TODO: We shoudl make sure that all our terminals close all the way. +-- Otherwise it could be bad if they're just sitting around, waiting to be closed. +-- I don't think that's the problem, but it could be? + function Previewer:new(opts) opts = opts or {} diff --git a/media/demo_script.lua b/media/demo_script.lua new file mode 100644 index 0000000..8074523 --- /dev/null +++ b/media/demo_script.lua @@ -0,0 +1,47 @@ +local finders = require('telescope.finders') +local previewers = require('telescope.previewers') +local pickers = require('telescope.pickers') +local sorters = require('telescope.sorters') + +-- Get all the items from v:oldfiles that are valid files +local valid_oldfiles = vim.tbl_filter(function(val) + return 0 ~= vim.fn.filereadable(val) +end, vim.v.oldfiles) + +-- print(vim.inspect(valid_oldfiles)) +-- => { +-- "/home/tj/blah.txt", +-- "/home/tj/another_dir/file.py", +-- ... +-- } + +-- Create a finder from a Lua list. +local oldfiles_finder = finders.new_table(valid_oldfiles) + +-- Get a pre-defined sorter. +-- Sorters return a "score" for each "Entry" found by a finder. +-- +-- This sorter is optimized to best find files in a fuzzy manner. +local oldfiles_sorter = sorters.get_fuzzy_file() + +-- Get a pre-defined previewer. +-- Previewers take the currently selected entry, +-- and put a preview of it in a floating window +local oldfiles_previewer = previewers.cat + +-- Create and run a Picker. +-- Pickers are the main entry point to telescope. +-- They manage the interactions between: +-- Finder, +-- Sorter, +-- Previewer +-- +-- And provide the UI for the user. +pickers.new { + prompt = 'Oldfiles', + finder = oldfiles_finder, + sorter = oldfiles_sorter, + previewer = oldfiles_previewer, +}:find() + + diff --git a/media/demo_script_2.lua b/media/demo_script_2.lua new file mode 100644 index 0000000..9394ffc --- /dev/null +++ b/media/demo_script_2.lua @@ -0,0 +1,30 @@ +local finders = require('telescope.finders') +local previewers = require('telescope.previewers') +local pickers = require('telescope.pickers') + +-- Create a new finder. +-- This finder, rather than taking a Lua list, +-- generates a shell command that should be run. +-- +-- Each line of the shell command is converted to an entry, +-- and is possible to preview with builtin previews. +-- +-- In this example, we use ripgrep to search over your entire directory +-- live as you type. +local live_grepper = finders.new_job(function(prompt) + if not prompt or prompt == "" then + return nil + end + + return { 'rg', "--vimgrep", prompt} +end) + +-- Create and run the Picker. +-- +-- NOTE: No sorter is needed to be passed. +-- Results will be returned in the order they are received. +pickers.new({ + prompt = 'Live Grep', + finder = live_grepper, + previewer = previewers.vimgrep, +}):find()