Skip to content

Commit

Permalink
Merge pull request #27 from piersolenski/feature/insert_position
Browse files Browse the repository at this point in the history
Line position
  • Loading branch information
piersolenski authored Aug 19, 2024
2 parents bdce370 + 05a5d81 commit 59e63e1
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 55 deletions.
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ For languages that support auto importing through their LSP, `telescope-import`
https://github.com/piersolenski/telescope-import.nvim/assets/1285419/014753e3-ea7b-4bad-9f86-fb2566bf27c1

## 🤖 Supported languages

- Bash
- C++
- Java
- JavaScript
- Typescript
- Lua
- PHP
- Python
- Swift
- Typescript
- Zsh

## 🔩 Installation
Expand All @@ -39,21 +38,25 @@ Install [ripgrep](https://github.com/BurntSushi/ripgrep).

## ⚙️ Configuration

`telescope-import.nvim` requires no configuration out of the box, but you can tweak it in the following ways:

```lua
require("telescope").setup({
extensions = {
import = {
-- Add imports to the top of the file keeping the cursor in place
-- Imports can be added at a specified line whilst keeping the cursor in place
insert_at_top = true,
-- Support additional languages
-- Optionally support additional languages or modify existing languages...
custom_languages = {
{
-- The regex pattern for the import statement
regex = [[^(?:import(?:[\"'\s]*([\w*{}\n, ]+)from\s*)?[\"'\s](.*?)[\"'\s].*)]],
-- The Vim filetypes
filetypes = { "typescript", "typescriptreact", "javascript", "react" },
-- The filetypes that ripgrep supports (find these via `rg --type-list`)
extensions = { "js", "ts" },
-- The Vim filetypes
filetypes = { "vue" },
-- Optionally set a line other than 1
insert_at_line = 2 ---@type function|number,
-- The regex pattern for the import statement
regex = [[^(?:import(?:[\"'\s]*([\w*{}\n, ]+)from\s*)?[\"'\s](.*?)[\"'\s].*)]],
},
},
},
Expand Down
12 changes: 12 additions & 0 deletions lua/import/get_filetype_config.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
local function get_filetype_config(languages, filetype)
for _, config in ipairs(languages) do
for _, current_filetype in ipairs(config.filetypes) do
if current_filetype == filetype then
return config
end
end
end
return nil
end

return get_filetype_config
16 changes: 1 addition & 15 deletions lua/import/get_project_imports.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,6 @@ local function create_file_types_flag(strings)
return result
end

local function get_filetype_config(languages, filetype)
for _, config in ipairs(languages) do
for _, current_filetype in ipairs(config.filetypes) do
if current_filetype == filetype then
return config
end
end
end
return nil
end

local function find_imports(config, file_path)
local types = create_file_types_flag(config.extensions)
local flags = { "--no-heading", "--no-line-number", "--color=never", "--no-filename" }
Expand All @@ -40,10 +29,7 @@ local function find_imports(config, file_path)
return vim.fn.systemlist(find_command)
end

local function get_project_imports(languages)
local filetype = utils.get_filetype()
local config = get_filetype_config(languages, filetype)

local function get_project_imports(config)
if config == nil then
return nil
end
Expand Down
31 changes: 27 additions & 4 deletions lua/import/insert_line.lua
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
local function insert_line(value, insert_at_top)
local function insert_line(value, line_number)
-- Capture the original line so that we can return to it if we insert the line
-- elsewhere
local original_position

if insert_at_top then
if line_number then
-- If the line_number is a function, call it to get the resulting number
if type(line_number) == "function" then
line_number = line_number()
end

-- Double check that we have a number in the case of custom configs
if type(line_number) ~= "number" then
error("Expected insert_at_line to return a number, but got " .. type(line_number))
end

original_position = vim.fn.getpos(".")
vim.cmd("normal! gg")

-- Ensure the line number is within the valid range
local line_count = vim.api.nvim_buf_line_count(0)
if line_number < 1 or line_number > line_count then
error("Line number out of range!")
return
end
-- Set cursor to the desired line
vim.api.nvim_win_set_cursor(0, { line_number, 0 })
end

-- Insert the line
vim.api.nvim_put({ value }, "l", false, false)

if insert_at_top then
if line_number then
-- Increment the line number to accommodate for extra line
original_position[2] = original_position[2] + 1
vim.fn.setpos(".", original_position)
end
end
Expand Down
32 changes: 16 additions & 16 deletions lua/import/languages.lua
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
local languages = {
{
regex = [[^(?:source\s+)]],
filetypes = { "sh", "zsh" },
extensions = { "sh", "zsh" },
filetypes = { "sh", "zsh" },
regex = [[^(?:source\s+)]],
},
{
regex = [[^import\s+((static\s+)?[\w.]+\*?);\s*$]],
filetypes = { "java" },
extensions = { "java" },
filetypes = { "java" },
regex = [[^import\s+((static\s+)?[\w.]+\*?);\s*$]],
},
{
regex = [[(?m)^(?:from\s+(\S+)\s+)?import\s+([^#\n]+)]],
filetypes = { "python" },
extensions = { "py" },
filetypes = { "python" },
regex = [[(?m)^(?:from\s+(\S+)\s+)?import\s+([^#\n]+)]],
},
{
regex = [[^(?:import(?:[\"'\s]*([\w*{}\n, ]+)from\s*)?[\"'\s](.*?)[\"'\s].*)]],
filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact" },
extensions = { "js", "ts" },
filetypes = { "vue", "javascript", "javascriptreact", "typescript", "typescriptreact" },
regex = [[^(?:import(?:[\"'\s]*([\w*{}\n, ]+)from\s*)?[\"'\s](.*?)[\"'\s].*)]],
},
{
regex = [[^(?:local (\w+) = require\([\"'](.*?)[\"']\))]],
filetypes = { "lua" },
extensions = { "lua" },
filetypes = { "lua" },
regex = [[^(?:local (\w+) = require\([\"'](.*?)[\"']\))]],
},
{
regex = [[^(?:#include [\"<].*[\">])\s*]],
filetypes = { "c", "cpp" },
extensions = { "h", "c", "cpp" },
filetypes = { "c", "cpp" },
regex = [[^(?:#include [\"<].*[\">])\s*]],
},
{
regex = [[^\s*use\s+([\w\\]+)(?:\s*;)?]],
filetypes = { "php" },
extensions = { "php" },
filetypes = { "php" },
regex = [[^\s*use\s+([\w\\]+)(?:\s*;)?]],
},
{
regex = [[^import\s+(\w+)\s*$]],
filetypes = { "swift" },
extensions = { "swift" },
filetypes = { "swift" },
regex = [[^import\s+(\w+)\s*$]],
},
}

Expand Down
29 changes: 18 additions & 11 deletions lua/import/picker.lua
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
local action_state = require("telescope.actions.state")
local actions = require("telescope.actions")
local finders = require("telescope.finders")
local pickers = require("telescope.pickers")
local conf = require("telescope.config").values
local action_state = require("telescope.actions.state")
local utils = require("import.utils")
local default_languages = require("import.languages")
local finders = require("telescope.finders")
local get_filetype_config = require("import.get_filetype_config")
local get_project_imports = require("import.get_project_imports")
local insert_line = require("import.insert_line")
local pickers = require("telescope.pickers")
local utils = require("import.utils")

local function picker(opts)
local languages = utils.concat_tables(opts.custom_languages, default_languages)

local imports = get_project_imports(languages)
local filetype = utils.get_filetype()
local filetype_config = get_filetype_config(languages, filetype)
local imports = get_project_imports(filetype_config)

if imports == nil then
vim.notify("Filetype not supported", vim.log.levels.ERROR)
Expand All @@ -23,16 +25,16 @@ local function picker(opts)
return nil
end

-- add syntax highlighting to the rsults of the picker
-- Add syntax highlighting to the results of the picker
local currentFiletype = vim.bo.filetype
vim.api.nvim_create_autocmd("FileType", {
pattern = "TelescopeResults",
once = true, -- do not affect other Telescope windows
once = true, -- Do not affect other Telescope windows
callback = function(ctx)
-- add filetype highlighting
-- Add filetype highlighting
vim.api.nvim_buf_set_option(ctx.buf, "filetype", currentFiletype)

-- make discernible as the results are now colored
-- Make discernible as the results are now colored
local ns = vim.api.nvim_create_namespace("telescope-import")
vim.api.nvim_win_set_hl_ns(0, ns)
vim.api.nvim_set_hl(ns, "TelescopeMatching", { reverse = true })
Expand All @@ -56,8 +58,13 @@ local function picker(opts)
attach_mappings = function(prompt_bufnr, _)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
local default_insertion_line = 1
local insert_at_line = (
filetype_config and filetype_config.insert_at_line or default_insertion_line
)
local should_insert_at_top = opts.insert_at_top
local selection = action_state.get_selected_entry()
insert_line(selection.value, opts.insert_at_top)
insert_line(selection.value, should_insert_at_top and insert_at_line)
end)
return true
end,
Expand Down
46 changes: 46 additions & 0 deletions lua/import/validate_config.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
local function validate_language(lang)
vim.validate({
extensions = { lang.extensions, "table" },
filetypes = { lang.filetypes, "table" },
regex = { lang.regex, "string" },
insert_at_line = { lang.insert_at_line, { "nil", "number", "function" }, true },
})

for _, ext in ipairs(lang.extensions) do
vim.validate({ extension = { ext, "string" } })
end

for _, ft in ipairs(lang.filetypes) do
vim.validate({ filetype = { ft, "string" } })
end
end

local function validate_config(opts)
vim.validate({
insert_at_top = { opts.insert_at_top, { "boolean" } },
custom_languages = {
opts.custom_languages,
function(value)
if type(value) ~= "table" and value ~= nil then
return false, "custom_languages must be a table or nil"
end

if value ~= nil then
for _, lang in ipairs(value) do
if type(lang) ~= "table" then
return false, "each item in custom_languages must be a table"
end
local ok, err = pcall(validate_language, lang)
if not ok then
return false, err
end
end
end

return true
end,
},
})
end

return validate_config
5 changes: 4 additions & 1 deletion lua/telescope/_extensions/import.lua
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
local has_telescope, telescope = pcall(require, "telescope")
local picker = require("import.picker")
local validate_config = require("import.validate_config")

if not has_telescope then
error("Install nvim-telescope/telescope.nvim to use telescope-import.nvim.")
end

local opts = {}
local default_opts = {
insert_at_top = true,
custom_languages = {},
insert_at_top = true,
}

return telescope.register_extension({
setup = function(external_opts, _)
validate_config(external_opts)

opts = vim.tbl_extend("force", default_opts, external_opts)
end,
exports = {
Expand Down

0 comments on commit 59e63e1

Please sign in to comment.