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

Include branch in repo URL for plugins #53

Merged
merged 3 commits into from
May 23, 2023
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
20 changes: 17 additions & 3 deletions doc/urlview.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ although it is less secure than the default HTTPS protocol.
Default action to take upon selecting a URL from a picker. This should be any
one of the actions in |urlview.actions|.

*urlview.config-default_include_branch*
{default_include_branch} boolean (default: false)

Default option for whether plugin URLs should link to the branch used by your
package manager, for |urlview.search-lazy|, |urlview.search-packer| or
|urlview.search-vimplug|. When this option is enabled, navigated links will
open the plugin's repository to the specific branch specified to your plugin
manager.

*urlview.config-unique*
{unique} boolean (default: true)

Expand Down Expand Up @@ -144,15 +153,20 @@ The file search context allows a user to find URLs in a particular file. This
requires passing in the parameter `filepath` for URLs in the desired file to be
searched, for example with `:UrlView file filepath="/etc/hosts"`.

Lazy Search Context *urlview.search-lazy*

This search context resolves Git repository URLs for plugins installed with
the lazy.nvim plugin manager. Invoked with `:UrlView lazy`.

Packer Search Context *urlview.search-packer*

This search context resolves Git repository URLs for plugins installed with
the packer.nvim plugin manager.
the packer.nvim plugin manager. Invoked with `:UrlView packer`.

vim-plug Search Context *urlview.search-vim_plug*
vim-plug Search Context *urlview.search-vimplug*

This search context resolves Git repository URLs for plugins installed with
the vim-plug plugin manager.
the vim-plug plugin manager. Invoked with `:UrlView vimplug`.

Registering a custom search context *urlview.search-custom*

Expand Down
2 changes: 2 additions & 0 deletions lua/urlview/config/default.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ local default_config = {
-- Options: "netrw", "system" (default OS browser), "clipboard"; or "firefox", "chromium" etc.
-- By default, this is "netrw", or "system" if netrw is disabled
default_action = "netrw",
-- Whether plugin URLs should link to the branch used by your package manager
default_include_branch = false,
-- Ensure links shown in the picker are unique (no duplicates)
unique = true,
-- Ensure links shown in the picker are sorted alphabetically
Expand Down
16 changes: 0 additions & 16 deletions lua/urlview/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,6 @@ function M.search(ctx, opts)
end
end

local function check_breaking()
if config.navigate_method ~= nil then
utils.log([[`config.navigate_method` has been deprecated for `config.default_action`
Please see https://github.com/axieax/urlview.nvim/issues/37#issuecomment-1251246520]])
end
if config.debug ~= nil then
utils.log([[`config.debug` has been deprecated for `config.log_level_min`
Please see https://github.com/axieax/urlview.nvim/issues/37#issuecomment-1257113527]])
end
if config.custom_searches ~= nil then
utils.log([[Registering custom search contexts with `config.custom_searches` has been deprecated
Please see https://github.com/axieax/urlview.nvim/issues/37#issuecomment-1268023592]])
end
end

local function autoload()
config_helpers.reset_defaults()
command.register_command()
Expand All @@ -66,7 +51,6 @@ autoload()
function M.setup(user_config)
user_config = utils.fallback(user_config, {})
config_helpers.update_config(user_config)
check_breaking()

jump.register_mappings(config.jump)
end
Expand Down
20 changes: 8 additions & 12 deletions lua/urlview/search/helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,31 +80,27 @@ end

--- Extract Git links from @plugins_spec
---@param plugins_spec table @map of specs for plugins
---@param key string @key in plugin_spec containing the Git URL
---@param uri_key string @key in plugin_spec containing the Git URL
---@param include_branch boolean @whether to include the branch in the URL
---@return table @list of extracted links
function M.extract_plugins_spec(plugins_spec, key)
function M.extract_plugins_spec(plugins_spec, uri_key, include_branch)
local function filter_files(plugin_url)
local fs_stat = vim.loop.fs_stat(plugin_url)
return not fs_stat or vim.tbl_isempty(fs_stat)
end

local function extract_key(plugin_spec)
return plugin_spec[key]
local uri = plugin_spec[uri_key]:gsub("%.git$", "") -- remove `.git` suffix
if include_branch and plugin_spec.branch then
uri = string.format("%s/tree/%s", uri, plugin_spec.branch)
end
return uri
end

local plugins = vim.tbl_map(extract_key, vim.tbl_values(plugins_spec or {}))
return vim.tbl_filter(filter_files, plugins)
end

--- Removes `.git` extension from @links
---@param links table (list) of URLs
---@return table (list) of links without the `.git` extension
function M.remove_git_url_suffix(links)
return vim.tbl_map(function(link)
return link:gsub("%.git$", "")
end, links)
end

--- Generates a simple search function from a template table
---@param pattern table (map) with `capture` key and optional `format` key
---@return function|nil
Expand Down
16 changes: 9 additions & 7 deletions lua/urlview/search/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,29 @@ function M.file(opts)
end

--- Extracts urls of packer.nvim plugins
---@param opts table (map)
---@return table (list) of strings (extracted links)
function M.packer()
function M.packer(opts)
-- selene: allow(global_usage)
local plugins = _G.packer_plugins or {}
return search_helpers.extract_plugins_spec(plugins, "url")
return search_helpers.extract_plugins_spec(plugins, "url", opts.include_branch)
end

--- Extracts urls of lazy.nvim plugins
---@param opts table (map)
---@return table (list) of strings (extracted links)
function M.lazy()
function M.lazy(opts)
local ok, lazy = pcall(require, "lazy")
local plugins = ok and lazy.plugins() or {}
local results = search_helpers.extract_plugins_spec(plugins, "url")
return search_helpers.remove_git_url_suffix(results)
return search_helpers.extract_plugins_spec(plugins, "url", opts.include_branch)
end

--- Extracts urls of vim-plug plugins
---@param opts table (map)
---@return table (list) of strings (extracted links)
function M.vimplug()
function M.vimplug(opts)
local plugins = vim.g.plugs or {}
return search_helpers.extract_plugins_spec(plugins, "uri")
return search_helpers.extract_plugins_spec(plugins, "uri", opts.include_branch)
end

return setmetatable(M, {
Expand Down
56 changes: 47 additions & 9 deletions lua/urlview/search/validation.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
local M = {}

local utils = require("urlview.utils")
local config = require("urlview.config")

--- Validates `value` is of `expected_type`
--- Validates `value` is of `expected_type` and casts to expected type
---@param value any @value to validate
---@param expected_type string @expected type
local function validate_type(value, expected_type)
local function validate_and_cast_type(value, expected_type)
if type(value) == expected_type then
return value
else
Expand All @@ -23,7 +24,7 @@ end
--- Verifies `opts` if `opts` is provided, otherwise returns all possible accepted options
---@param opts table (map) of user options
---@param accepted_opts table (map) of accepted options
--- (option_key (string) -> { type (string), is_optional (boolean) })
--- (option_key (string) -> { type (string), optional: boolean, default: any })
---@return table (map) of updated user options if `opts` is provided, otherwise returns all possible accepted options as a table (list)
local function verify_or_accept(opts, accepted_opts)
if not opts then
Expand All @@ -34,12 +35,22 @@ local function verify_or_accept(opts, accepted_opts)
-- validate provided options if `opts` provided
local new_opts = vim.deepcopy(opts)
for expected_key, expected_v in pairs(accepted_opts) do
local expected_type, is_optional = unpack(expected_v)
local expected_type = expected_v[1]
local is_optional = expected_v.optional
local user_option = opts[expected_key]
if not is_optional and user_option == nil then

if user_option == nil and not is_optional then
utils.log(string.format("Missing required option `%s`", expected_key), vim.log.levels.WARN)
elseif user_option ~= nil then
new_opts[expected_key] = validate_type(user_option, expected_type)
elseif user_option == nil and is_optional then
if expected_v.default == nil then
utils.log(
string.format("Missing default validation field for optional key `%s`", expected_key),
vim.log.levels.WARN
)
end
new_opts[expected_key] = expected_v.default
else
new_opts[expected_key] = validate_and_cast_type(user_option, expected_type)
if new_opts[expected_key] == nil then
utils.log(
string.format("Invalid type for option `%s` (expected: %s)", expected_key, expected_type),
Expand All @@ -58,7 +69,7 @@ end
---@return table (map) of updated user options if `opts` is provided, otherwise returns all possible accepted options as a table (list)
function M.buffer(opts)
return verify_or_accept(opts, {
bufnr = { "number", true },
bufnr = { "number", optional = true },
})
end

Expand All @@ -67,7 +78,34 @@ end
---@return table (map) of updated user options if `opts` is provided, otherwise returns all possible accepted options as a table (list)
function M.file(opts)
return verify_or_accept(opts, {
filepath = { "string", false },
filepath = { "string", optional = false },
})
end

--- Validation for the "packer" search context
---@param opts table (map, optional) of user options
---@return table (map) of updated user options if `opts` is provided, otherwise returns all possible accepted options as a table (list)
function M.packer(opts)
return verify_or_accept(opts, {
include_branch = { "boolean", optional = true, default = config.default_include_branch },
})
end

--- Validation for the "lazy" search context
---@param opts table (map, optional) of user options
---@return table (map) of updated user options if `opts` is provided, otherwise returns all possible accepted options as a table (list)
function M.lazy(opts)
return verify_or_accept(opts, {
include_branch = { "boolean", optional = true, default = config.default_include_branch },
})
end

--- Validation for the "vimplug" search context
---@param opts table (map, optional) of user options
---@return table (map) of updated user options if `opts` is provided, otherwise returns all possible accepted options as a table (list)
function M.vimplug(opts)
return verify_or_accept(opts, {
include_branch = { "boolean", optional = true, default = config.default_include_branch },
})
end

Expand Down