diff --git a/README.md b/README.md index 133e7c6..a248d7c 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ * open links without `netrw` * normal and visual mode support -* open links with/without an explicit protocol (e.g. `google.com` will open `https://google.com`) +* links with/without an explicit protocol (e.g. `google.com` will open `https://google.com`) * open plugins in the browser with a single command (e.g. in lazy, packer you can hover over a plugin name, simply press `gx` and you get to the github page of the plugin) * open github issues directly in the browser (e.g. `Fixes #22` opens `https://github.com/chrishrb/gx.nvim/issues/22`) +* plugins from `package.json` (e.g. line `"express": "^4.18.2",` in the `package.json` opens `https://www.npmjs.com/package/vue-router`) * more to come (jira issues, ..) ## ⚡️ Requirements @@ -26,6 +27,7 @@ require("lazy").setup({ { "chrishrb/gx.nvim", event = { "BufEnter" }, + dependencies = { "nvim-lua/plenary.nvim" }, config = true, -- default settings -- you can specify also another config if you want @@ -34,6 +36,7 @@ require("lazy").setup({ handlers = { plugin = true, -- open plugin links in lua (e.g. packer, lazy, ..) github = true, -- open github issues + package_json = true, -- open plugins from package.json }, } end, }, @@ -50,5 +53,4 @@ When your cursor is over a link or you mark a link or part of a link with the vi ## 📄 Acknowledgements -* Source code of `shell.lua` is partly from [lua-shell](https://github.com/ncopa/lua-shell) * lua functions library [plenary.nvim](https://github.com/nvim-lua/plenary.nvim) diff --git a/lua/gx/handler.lua b/lua/gx/handler.lua index e4cb14e..0d6be18 100644 --- a/lua/gx/handler.lua +++ b/lua/gx/handler.lua @@ -1,36 +1,33 @@ +local helper = require("gx.helper") +local package_json_handler = require("gx.handlers.package_json") local plugin_handler = require("gx.handlers.plugin") local url_handler = require("gx.handlers.url") local github_handler = require("gx.handlers.github") local M = {} -local function is_correct_filetype(handler_filetype, file_filetype) - if not handler_filetype then - return true - end - if handler_filetype == file_filetype then - return true - end - return false -end - -local function add_handler(handlers, handler, file_filetype, active) - if not active or not is_correct_filetype(handler.filetype, file_filetype) then +local function add_handler(handlers, handler, active) + if + not active + or not helper.check_filetype(handler.filetype) + or not helper.check_filename(handler.filename) + then return end table.insert(handlers, handler) end -- handler function -function M.get_url(mode, line, file_filetype, activated_handlers) +function M.get_url(mode, line, activated_handlers) local url local handlers = {} local tkeys = {} -- ### add here new handlers - add_handler(handlers, plugin_handler, file_filetype, activated_handlers.plugin) - add_handler(handlers, github_handler, file_filetype, activated_handlers.github) - add_handler(handlers, url_handler, file_filetype, true) + add_handler(handlers, package_json_handler, activated_handlers.package_json) + add_handler(handlers, plugin_handler, activated_handlers.plugin) + add_handler(handlers, github_handler, activated_handlers.github) + add_handler(handlers, url_handler, true) -- ### for k in pairs(handlers) do diff --git a/lua/gx/handlers/github.lua b/lua/gx/handlers/github.lua index 368a1ce..2b24a57 100644 --- a/lua/gx/handlers/github.lua +++ b/lua/gx/handlers/github.lua @@ -3,8 +3,9 @@ local git = require("gx.git") local M = {} --- every filetype +-- every filetype and filename M.filetype = nil +M.filename = nil -- navigate to neovim github plugin url function M.handle(mode, line) diff --git a/lua/gx/handlers/package_json.lua b/lua/gx/handlers/package_json.lua new file mode 100644 index 0000000..05b2938 --- /dev/null +++ b/lua/gx/handlers/package_json.lua @@ -0,0 +1,19 @@ +local helper = require("gx.helper") + +local M = {} + +-- only package.json +M.filetype = "json" +M.filename = "package.json" + +-- navigate to neovim github plugin url +function M.handle(mode, line) + local pattern = '["]([^%s]*)["]:' + local npm_package = helper.find(line, mode, pattern) + if not npm_package then + return + end + return "https://www.npmjs.com/package/" .. npm_package +end + +return M diff --git a/lua/gx/handlers/plugin.lua b/lua/gx/handlers/plugin.lua index 91b9ff0..c07ff3d 100644 --- a/lua/gx/handlers/plugin.lua +++ b/lua/gx/handlers/plugin.lua @@ -2,7 +2,9 @@ local helper = require("gx.helper") local M = {} +-- every filename but only lua M.filetype = "lua" +M.filename = nil -- navigate to neovim github plugin url function M.handle(mode, line) diff --git a/lua/gx/handlers/url.lua b/lua/gx/handlers/url.lua index f389c37..09fe606 100644 --- a/lua/gx/handlers/url.lua +++ b/lua/gx/handlers/url.lua @@ -4,15 +4,16 @@ local M = {} -- every filetype M.filetype = nil +M.filename = nil -- get url from line (with http/s) function M.handle(mode, line) - local pattern = "(https?://[a-zA-Z0-9_/%-%.~@\\+#]+)" + local pattern = "(https?://[a-zA-Z0-9_/%-%.~@\\+#=?&]+)" local url = helper.find(line, mode, pattern) -- match url without http(s) if not url then - pattern = "([a-zA-Z0-9_/%-%.~@\\+#]+%.[a-zA-Z0-9_/%-%.~@\\+#]+)" + pattern = "([a-zA-Z0-9_/%-%.~@\\+#]+%.[a-zA-Z0-9_/%-%.~@\\+#%=?&]+)" url = helper.find(line, mode, pattern) if url then return "https://" .. url diff --git a/lua/gx/helper.lua b/lua/gx/helper.lua index 2fcbbb2..c3f77b3 100644 --- a/lua/gx/helper.lua +++ b/lua/gx/helper.lua @@ -60,4 +60,33 @@ function M.ternary(cond, T, F) end end +-- check for filetype +function M.check_filetype(handler_filetype) + local file_filetype = vim.bo.filetype + if not handler_filetype then + return true + end + if handler_filetype == file_filetype then + return true + end + return false +end + +-- get filename +function M.get_filename() + return vim.fn.expand("%:t") +end + +-- check for filename +function M.check_filename(handler_filename) + local filename = M.get_filename() + if not handler_filename then + return true + end + if handler_filename == filename then + return true + end + return false +end + return M diff --git a/lua/gx/init.lua b/lua/gx/init.lua index 1a8cdcb..5dff664 100644 --- a/lua/gx/init.lua +++ b/lua/gx/init.lua @@ -12,13 +12,12 @@ local M = {} local function search_for_url() local line = vim.api.nvim_get_current_line() local mode = vim.api.nvim_get_mode().mode - local filetype = vim.bo.filetype -- cut if in visual mode line = helper.cut_with_visual_mode(mode, line) -- search for url - local url = handler.get_url(mode, line, filetype, M.options.handlers) + local url = handler.get_url(mode, line, M.options.handlers) if not url then return @@ -56,6 +55,11 @@ local function with_defaults(options) handlers = { plugin = helper.ternary(options.handlers.plugin ~= nil, options.handlers.plugin, true), github = helper.ternary(options.handlers.github ~= nil, options.handlers.github, true), + package_json = helper.ternary( + options.handlers.package_json ~= nil, + options.handlers.package_json, + true + ), }, } end diff --git a/test/spec/gx/handler_spec.lua b/test/spec/gx/handler_spec.lua index 91ffed5..af39c9a 100644 --- a/test/spec/gx/handler_spec.lua +++ b/test/spec/gx/handler_spec.lua @@ -1,79 +1,97 @@ +local helper = require("gx.helper") local handler = require("gx.handler") +local stub = require("luassert.stub") describe("test handler", function() local activated_handlers = { plugin = false, + github = false, + package_json = false, } + before_each(function() + before_mock_filetype = vim.bo.filetype + end) + + after_each(function() + vim.bo.filetype = before_mock_filetype + end) + it("no extra handlers on", function() - local filetype = "lua" + -- mock filetype + vim.bo.filetype = "lua" + assert.equals("https://github.com", handler.get_url("v", "github.com", activated_handlers)) assert.equals( "https://github.com", - handler.get_url("v", "github.com", filetype, activated_handlers) + handler.get_url("v", "https://github.com", activated_handlers) ) - assert.equals( - "https://github.com", - handler.get_url("v", "https://github.com", filetype, activated_handlers) - ) - assert.equals( - nil, - handler.get_url("v", '"example_user/example_plugin"', "lua", activated_handlers) - ) - assert.equals(nil, handler.get_url("v", "Fixes #22", filetype, activated_handlers)) + assert.equals(nil, handler.get_url("v", '"example_user/example_plugin"', activated_handlers)) + assert.equals(nil, handler.get_url("v", "Fixes #22", activated_handlers)) end) it("plugin handler on", function() - local filetype = "lua" activated_handlers.plugin = true + -- mock filetype + vim.bo.filetype = "lua" + + assert.equals("https://github.com", handler.get_url("v", "github.com", activated_handlers)) assert.equals( "https://github.com", - handler.get_url("v", "github.com", filetype, activated_handlers) - ) - assert.equals( - "https://github.com", - handler.get_url("v", "https://github.com", filetype, activated_handlers) + handler.get_url("v", "https://github.com", activated_handlers) ) assert.equals( "https://github.com/example_user/example_plugin", - handler.get_url("v", '"example_user/example_plugin"', filetype, activated_handlers) + handler.get_url("v", '"example_user/example_plugin"', activated_handlers) ) end) it("plugin handler on wrong filetype", function() - local filetype = "java" activated_handlers.plugin = true + -- mock filetype + vim.bo.filetype = "java" + + assert.equals("https://github.com", handler.get_url("v", "github.com", activated_handlers)) assert.equals( "https://github.com", - handler.get_url("v", "github.com", filetype, activated_handlers) - ) - assert.equals( - "https://github.com", - handler.get_url("v", "https://github.com", filetype, activated_handlers) - ) - assert.equals( - nil, - handler.get_url("v", '"example_user/example_plugin"', filetype, activated_handlers) + handler.get_url("v", "https://github.com", activated_handlers) ) + assert.equals(nil, handler.get_url("v", '"example_user/example_plugin"', activated_handlers)) end) it("plugin handler on", function() - local filetype = "lua" activated_handlers.github = true + -- mock filetype + vim.bo.filetype = "lua" + + assert.equals("https://github.com", handler.get_url("v", "github.com", activated_handlers)) assert.equals( "https://github.com", - handler.get_url("v", "github.com", filetype, activated_handlers) + handler.get_url("v", "https://github.com", activated_handlers) ) assert.equals( - "https://github.com", - handler.get_url("v", "https://github.com", filetype, activated_handlers) + "https://github.com/chrishrb/gx.nvim/issues/22", + handler.get_url("v", "Fixes #22", activated_handlers) ) + end) + + it("package_json handler on", function() + activated_handlers.package_json = true + + -- mock filetype + vim.bo.filetype = "json" + + stub(helper, "get_filename") + helper.get_filename.on_call_with().returns("package.json") + assert.equals( - "https://github.com/chrishrb/gx.nvim/issues/22", - handler.get_url("v", "Fixes #22", filetype, activated_handlers) + "https://www.npmjs.com/package/@rushstack/eslint-patch", + handler.get_url("v", '"@rushstack/eslint-patch": "^1.2.0",', activated_handlers) ) + + helper.get_filename:revert() end) end) diff --git a/test/spec/gx/handlers/package_json_handler_spec.lua b/test/spec/gx/handlers/package_json_handler_spec.lua new file mode 100644 index 0000000..f59a672 --- /dev/null +++ b/test/spec/gx/handlers/package_json_handler_spec.lua @@ -0,0 +1,22 @@ +local handler = require("gx.handlers.package_json") + +describe("package_json_handler_does_work", function() + it("package_json", function() + assert.equals( + "https://www.npmjs.com/package/@cucumber/cucumber", + handler.handle("v", '"@cucumber/cucumber": "^9.0.1",') + ) + assert.equals( + "https://www.npmjs.com/package/@prisma/client", + handler.handle("v", '"@prisma/client": "^4.11.0",') + ) + assert.equals( + "https://www.npmjs.com/package/express", + handler.handle("v", '"express": "^4.18.2",') + ) + assert.equals( + "https://www.npmjs.com/package/vue-router", + handler.handle("v", '"vue-router": "^4.1.6"') + ) + end) +end) diff --git a/test/spec/gx/handlers/url_handler_spec.lua b/test/spec/gx/handlers/url_handler_spec.lua index 6399060..b246615 100644 --- a/test/spec/gx/handlers/url_handler_spec.lua +++ b/test/spec/gx/handlers/url_handler_spec.lua @@ -26,6 +26,13 @@ describe("url_parser_does_work", function() "https://github.com/chrishrb/gx.nvim/#-installation", handler.handle("v", "github.com/chrishrb/gx.nvim/#-installation") ) + assert.equals( + "https://signin.aws.amazon.com/switchrole?roleName=my-role&account=111111111", + handler.handle( + "v", + "https://signin.aws.amazon.com/switchrole?roleName=my-role&account=111111111" + ) + ) end) it("urls in markdown", function() diff --git a/test/spec/gx/helper_spec.lua b/test/spec/gx/helper_spec.lua index 096a849..7695e69 100644 --- a/test/spec/gx/helper_spec.lua +++ b/test/spec/gx/helper_spec.lua @@ -3,15 +3,15 @@ local mock = require("luassert.mock") describe("gx.nvim:", function() before_each(function() - get_filetype_mock = mock(vim.api, true) + m = mock(vim.api, true) end) after_each(function() - mock.revert(get_filetype_mock) + mock.revert(m) end) it("cursor is on url", function() - get_filetype_mock.nvim_win_get_cursor.on_call_with(0).returns({ _, 5 }) + m.nvim_win_get_cursor.on_call_with(0).returns({ _, 5 }) assert.True(helper.check_if_cursor_on_url("n", 1, 10)) assert.True(helper.check_if_cursor_on_url("n", 1, 6))