Refactoring.nvim
The Refactoring library based off the Refactoring book by Martin Fowler
Install / Use
/learn @ThePrimeagen/Refactoring.nvimREADME
Table of Contents
- Installation
- Features
- Configuration
Installation<a name="installation"></a>
Requirements<a name="requirements"></a>
- Neovim 0.10
- Treesitter
- Plenary
Setup Using Packer<a name="packer"></a>
use {
"ThePrimeagen/refactoring.nvim",
requires = {
{"nvim-lua/plenary.nvim"},
{"nvim-treesitter/nvim-treesitter"}
}
}
Setup Using Lazy<a name="lazy"></a>
{
"ThePrimeagen/refactoring.nvim",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-treesitter/nvim-treesitter",
},
lazy = false,
opts = {},
},
Quickstart<a name="quickstart"></a>
require('refactoring').setup()
Features<a name="features"></a>
Supported Languages<a name="supported-languages"></a>
Given that this is a work in progress, the languages supported for the operations listed below is constantly changing. As of now, these languages are supported (with individual support for each function may vary):
- TypeScript
- JavaScript
- Lua
- C/C++
- Golang
- Python
- Java
- PHP
- Ruby
- C#
- Vimscript (only debugging features)
- Powershell (only debugging features)
Refactoring Features<a name="refactoring-features"></a>
- Support for various common refactoring operations
- 106: Extract Function
- Extracts the last highlighted code from visual mode to a separate function
- Optionally prompts for function param types and return types (see configuration for type prompt operations)
- Also possible to Extract Block.
- Both Extract Function and Extract Block have the capability to extract to a separate file.
- 115: Inline Function
- Inverse of extract function
- In normal mode, inline occurrences of the function under the cursor
- The function under the cursor has to be the declaration of the function
- 119: Extract Variable
- In visual mode, extracts occurrences of a selected expression to its own variable, replacing occurrences of that expression with the variable
- 123: Inline Variable
- Inverse of extract variable
- Replaces all occurrences of a variable with its value
- Can be used in normal mode or visual mode
- Using this function in normal mode will automatically find the variable under the cursor and inline it
- Using this function in visual mode will find the variable(s) in the
visual selection.
- If there is more than one variable in the selection, the plugin will prompt for which variable to inline,
- If there is only one variable in the visual selection, it will automatically inline that variable
- 106: Extract Function
Debug Features<a name="debug-features"></a>
- Also comes with various useful features for debugging
- Printf: Automated insertion of print statement to mark the calling of a
function
- dot-repeatable
- Print var: Automated insertion of print statement to print a variable
at a given point in the code. This map can be made with either visual or
normal mode:
- Using this function in visual mode will print out whatever is in the visual selection.
- Using this function in normal mode will print out the identifier under the cursor
- dot-repeatable
- Cleanup: Automated cleanup of all print statements generated by the plugin
- Printf: Automated insertion of print statement to mark the calling of a
function
Configuration<a name="configuration"></a>
There are many ways to configure this plugin. Below are some example configurations.
Setup Function
No matter which configuration option you use, you must first call the setup function.
require('refactoring').setup({})
Here are all the available options for the setup function and their defaults:
require('refactoring').setup({
prompt_func_return_type = {
go = false,
java = false,
cpp = false,
c = false,
h = false,
hpp = false,
cxx = false,
},
prompt_func_param_type = {
go = false,
java = false,
cpp = false,
c = false,
h = false,
hpp = false,
cxx = false,
},
printf_statements = {},
print_var_statements = {},
show_success_message = false, -- shows a message with information about the refactor on success
-- i.e. [Refactor] Inlined 3 variable occurrences
})
See each of the sections below for details on each configuration option.
Configuration for Refactoring Operations<a name="config-refactoring"></a>
Ex Commands <a name="config-refactoring-command"></a>
The plugin offers the :Refactor command as an alternative to the Lua API.
The first argument to the command selects the type of refactor to perform.
Additional arguments will be passed to each refactor if needed (e.g. the name
of the extracted function for extract).
The first argument can be tab completed, so there is no need to memorize them all.
(e.g. :Refactor e<tab> will suggest extract_block_to_file, extract, extract_block,
extract_var and extract_to_file).
The main advantage of using an Ex command instead of the Lua API is that you will be able to preview the changes made by the refactor before committing to them.
https://github.com/ThePrimeagen/refactoring.nvim/assets/53507599/6ad58376-c503-4504-ab07-3590ae9a6c75
The command can also be used in mappings:
vim.keymap.set("x", "<leader>re", ":Refactor extract ")
vim.keymap.set("x", "<leader>rf", ":Refactor extract_to_file ")
vim.keymap.set("x", "<leader>rv", ":Refactor extract_var ")
vim.keymap.set({ "n", "x" }, "<leader>ri", ":Refactor inline_var")
vim.keymap.set( "n", "<leader>rI", ":Refactor inline_func")
vim.keymap.set("n", "<leader>rb", ":Refactor extract_block")
vim.keymap.set("n", "<leader>rbf", ":Refactor extract_block_to_file")
The (space) at the end of some mappings is intentional because those
mappings expect an additional argument (all of these mappings leave the user in
command mode to utilize the preview command feature).
Lua API <a name="config-refactoring-direct"></a>
If you want to make remaps for a specific refactoring operation, you can do so by configuring the plugin like this:
vim.keymap.set({ "n", "x" }, "<leader>re", function() return require('refactoring').refactor('Extract Function') end, { expr = true })
vim.keymap.set({ "n", "x" }, "<leader>rf", function() return require('refactoring').refactor('Extract Function To File') end, { expr = true })
vim.keymap.set({ "n", "x" }, "<leader>rv", function() return require('refactoring').refactor('Extract Variable') end, { expr = true })
vim.keymap.set({ "n", "x" }, "<leader>rI", function() return require('refactoring').refactor('Inline Function') end, { expr = true })
vim.keymap.set({ "n", "x" }, "<leader>ri", function() return require('refactoring').refactor('Inline Variable') end, { expr = true })
vim.keymap.set({ "n", "x" }, "<leader>rbb", function() return require('refactoring').refactor('Extract Block') end, { expr = true })
vim.keymap.set({ "n", "x" }, "<leader>rbf", function() return require('refactoring').refactor('Extract Block To File') end, { expr = true })
IMPORTANT: the keymaps MUST to be created using the { expr = true } option and return the value of the require('refactoring').refactor function (like in the example above).
Using Built-In Neovim Selection<a name="config-refactoring-builtin"></a>
You can also set up the plugin to prompt for a refactoring operation to apply
using Neovim's built in selection API (:h vim.ui.select(), the kind "refactoring.nvim" is used to allow user customization). Here is an example remap to demonstrate
this functionality:
-- prompt for a refactor to apply when the remap is triggered
vim.keymap.set(
{"n", "x"},
"<leader>rr",
function() require('refactoring').select_refactor() end
)
-- Note that not all refactor support both normal and visual mode
select_refactor() uses vim.ui.input by default to input the arguments (if
needed). If you want to use the Ex command to get the preview of the changes
you can use the prefer_ex_cmd option.
require('refactoring').select_refactor({prefer_ex_cmd = true})
Using Telescope<a name="config-refactoring-telescope"></a>
If you would prefe
