Open-source project
mizlan/iswap.nvim avatar
mizlan/iswap.nvim

iswap.nvim swaps two arguments by hitting two keys

Interactively select and swap function arguments, list elements, and much more. Powered by tree-sitter.

525 stars22 forksLuaMIT

At a glance

What is it?
iswap.nvim is an MIT-licensed Neovim plugin that uses tree-sitter to find the list, call or parameter list under your cursor, then swaps two of its elements with two keystrokes. The selection keys, the greying, the highlight groups and the cursor behaviour are all configurable, and there is a move variant for reordering rather than exchanging.
Who is it for?
iswap.nvim is a good fit for a Neovim user who edits long argument lists and parameter lists by hand, since a two-key swap removes the most error-prone part of that edit without needing a text object selection first. It is a poor fit if you want a general-purpose refactoring tool, because the plugin swaps and moves, it does not rename, extract or restructure, and it is a poor fit for an editor without tree-sitter available for the language you are editing.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 148 days ago.
What is it written in?
Mainly Lua, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the plugin actually does

iswap.nvim lets you interactively select and swap function arguments, list elements, function parameters and more, and it is powered by tree-sitter. The mechanism is short. You put your cursor somewhere that makes sense to swap around, which the README lists as lists and arrays, function arguments, and parameters in function definitions. You run the :ISwap command, hit two keys corresponding to the two items you want exchanged, and the text swaps in the buffer immediately. There is a recorded demo of the flow. The reason tree-sitter matters is that the plugin is not matching brackets or commas with a regular expression; it is asking the parser for the structure under the cursor, so the items it offers to swap are the ones the language actually considers siblings rather than the ones that happen to be separated by a character.

The With variants, and the Node shortcuts

Four commands cover the variations. :ISwap is the two-key version where you pick both elements. :ISwapWith takes the element under your cursor as one of the two automatically, so you only need one keypress to complete the swap, which is the difference between two keystrokes and one on a call you are already pointing at. :ISwapNode swaps two arbitrary adjacent nodes, and :ISwapNodeWith again picks the cursor element for you. There are then two convenience shortcuts, :ISwapNodeWith{Left} and :ISwapNodeWith{Right}, which swap the cursor node with its immediate left or right neighbour. The set is coherent rather than arbitrary, because each variant removes exactly one selection step from the previous one, and the two letter forms exist for the case where the neighbour is obvious enough that naming it beats hitting a key.

Move is the same machinery without the exchange

For every command above there is an equivalent :IMove* command, and the difference is exactly what you would guess: a move puts the node at the chosen position rather than exchanging the two, and the README explains the mechanism as being equivalent to swapping the first node with all of the nodes up to and including the second node. That definition is the interesting part, because it means a move across three elements is not three separate swaps, it is one operation expressed as a rotation, so a moved element keeps its relative order with the ones it passes rather than being dragged through them. If you have ever reordered a long list by hand and found the middle elements ended up shuffled, that is the problem this framing is solving.

Installing it in vim-plug or lazy.nvim

Two plugin managers, two blocks. For vim-plug:

vim
Plug 'mizlan/iswap.nvim'

and for lazy.nvim:

lua
{
  "mizlan/iswap.nvim",
  event = "VeryLazy"
}

The lazy.nvim form is worth noting because of the event. VeryLazy means the plugin loads when Neovim becomes idle rather than at startup, which is the right default for a plugin whose only entry points are commands you invoke deliberately. There is a tip at the top of the README about an error when updating the repository, and it is unusual advice: if you hit an error updating, delete the plugin and install it again, with a link to issue 58 for the details. That is a specific packaging problem with a specific workaround rather than a general complaint, and the fact that it is documented that way tells you the plugin is small enough that reinstalling is cheap.

The configuration surface, key by key

The setup function is where the behaviour lives, and the defaults are documented inline in the block itself:

lua
require('iswap').setup{
  -- The keys that will be used as a selection, in order
  -- ('asdfghjklqwertyuiopzxcvbnm' by default)
  keys = 'qwertyuiop',

  -- Grey out the rest of the text when making a selection
  -- (enabled by default)
  grey = 'disable',

  -- Highlight group for the sniping value (asdf etc.)
  -- default 'Search'
  hl_snipe = 'ErrorMsg',

  -- Highlight group for the visual selection of terms
  -- default 'Visual'
  hl_selection = 'WarningMsg',

  -- Highlight group for the greyed background
  -- default 'Comment'
  hl_grey = 'LineNr',

  -- Post-operation flashing highlight style,
  -- either 'simultaneous' or 'sequential', or false to disable
  -- default 'sequential'
  flash_style = false,

  -- Highlight group for flashing highlight afterward
  -- default 'IncSearch'
  hl_flash = 'ModeMsg',

  -- Move cursor to the other element in ISwap*With commands
  -- default false
  move_cursor = true,

  -- Automatically swap with only two arguments
  -- default nil
  autoswap = true,

  -- Other default options you probably should not change:
  debug = nil,
  hl_grey_priority = '1000',
}

The keys option is the one that matters most, because it replaces the whole selection alphabet rather than adding to it, and the default set is a long run of the home row and the top row. The grey option controls whether the rest of the text is dimmed while you select, and the four highlight group options let you repaint every element of the interaction: the sniping key, the visual selection, the dimmed background and the post-swap flash. The defaults deliberately reuse standard groups, so on a default colourscheme the selection already looks like something you have seen before.

Where iswap.nvim is the wrong tool

Three cases. The first is if you want a real refactoring tool, because this one swaps and moves, and renaming a parameter, extracting an argument into a variable or turning a positional call into a named one is out of scope. The second is an editor or language where tree-sitter has no parser, since the whole selection mechanism depends on the parser producing a node structure, and the plugin ships queries/ at the top level, so the set of languages it handles well is the set of languages those queries cover. The third is a user who finds two keystrokes to select two elements too slow, because there is a faster path for the two-argument case through the autoswap option, and if you need something faster than that you are looking for a different tool. Against writing the swap by hand with motions, the difference in approach is that the plugin uses the parse tree to know what the siblings are, so you never have to specify a range, and the price is that the plugin can only act on structures the parser recognises.

Editorial conclusion

iswap.nvim is a good fit for a Neovim user who edits long argument lists and parameter lists by hand, since a two-key swap removes the most error-prone part of that edit without needing a text object selection first. It is a poor fit if you want a general-purpose refactoring tool, because the plugin swaps and moves, it does not rename, extract or restructure, and it is a poor fit for an editor without tree-sitter available for the language you are editing. Check three things before you rely on it: that tree-sitter parses the language you are working in, since the whole mechanism depends on it and the plugin is credited as being powered by tree-sitter, that the selection keys do not collide with the ones your own plugins use, since the default set takes a fixed run of the home row and the setup option replaces it wholesale, and that the highlighting groups you override are ones you have not already redefined, because the defaults deliberately reuse built-in groups like Search, Visual, Comment and LineNr.

Frequently asked questions

What does iswap.nvim do?

It lets you interactively select and swap function arguments, list elements, function parameters and more, powered by tree-sitter. You put the cursor in a suitable location, run :ISwap, and hit two keys for the items to exchange, and the text swaps immediately in the buffer.

How do I install iswap.nvim?

With vim-plug, using Plug 'mizlan/iswap.nvim', or with lazy.nvim using the plugin spec with the repository name and event = "VeryLazy" so the plugin loads when Neovim goes idle. The README also advises deleting and reinstalling the plugin if you hit an error while updating.

What is the difference between ISwap and ISwapWith?

ISwap needs you to hit two keys for the two elements. ISwapWith takes the element under your cursor as one of the two automatically, so you only need one keypress to complete the swap. There are also ISwapNode for adjacent nodes, ISwapNodeWith, and the ISwapNodeWith{Left} and ISwapNodeWith{Right} shortcuts.

How do the IMove commands differ from the swap commands?

A move puts the node at the chosen position instead of exchanging two, and the README describes it as equivalent to swapping the first node with all of the nodes up to and including the second node. Every swap command has an equivalent IMove variant.

Can I change the keys and colours used by iswap.nvim?

Yes, through require('iswap').setup. The keys option replaces the selection alphabet, the default being asdfghjklqwertyuiopzxcvbnm, and the grey option controls whether the rest of the text is dimmed during selection. Separate options set the highlight groups for the sniping value, the visual selection, the greyed background and the post-operation flash, and move_cursor and autoswap control cursor behaviour and the two-argument shortcut.

Official sources

  1. Issues
  2. License: MIT
  3. mizlan/iswap.nvim on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mizlan-iswap-nvim.svg)](https://hysenlabs.com/projects/mizlan-iswap-nvim)

Was this useful?