Skip to content

Commit

Permalink
Add README section on auto-indentation
Browse files Browse the repository at this point in the history
  • Loading branch information
julienvincent committed Sep 10, 2023
1 parent 19a2e7b commit e3aa905
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,27 @@ require("nvim-paredit").setup({
-- defaults to all supported file types including custom lang
-- extensions (see next section)
filetypes = { "clojure" },

-- This controls where the cursor is placed when performing slurp/barf operations
--
-- - "remain" - It will never change the cursor position, keeping it in the same place
-- - "follow" - It will always place the cursor on the form edge that was moved
-- - "auto" - A combination of remain and follow, it will try keep the cursor in the original position
-- unless doing so would result in the cursor no longer being within the original form. In
-- this case it will place the cursor on the moved edge
cursor_behaviour = "auto", -- remain, follow, auto

indent = {
-- This controls how nvim-paredit handles indentation when performing operations which
-- should change the indentation of the form (such as when slurping or barfing).
--
-- When set to true then it will attempt to fix the indentation of nodes operated on.
enabled = false,
-- A function that will be called after a slurp/barf if you want to provide a custom indentation
-- implementation.
indentor = require("nvim-paredit.indentation.native").indentor,
},

-- list of default keybindings
keys = {
[">)"] = { paredit.api.slurp_forwards, "Slurp forwards" },
Expand Down Expand Up @@ -112,6 +132,65 @@ require("nvim-paredit").setup({
})
```

## Auto Indentation

Nvim-paredit comes with built-in support for fixing form indentation when performing slurp and barf operations. By default this behaviour is disabled and can be enabled by setting `indent.enabled = true` in the [configuration](#configuration)

The main goal of this implementation is to provide a visual aid to the user, allowing them to confirm they are operating on the correct node and to know when to stop when performing recursive slurp/barf operations. This implementation is fast and does not result in any UI lag or jitter.

The goal is _not_ to be 100% correct. The implementation follows a simple set of rules which account for most scenarios but not all. If a more correct implementation is needed then the native implementation can be replaced by setting the configuration property `intent.indentor`. For example an implementation using `vim.lsp.buf.format` could be built if the user doesn't mind sacrificing performance for correctness.

### Recipes

<details>
<summary><code>vim.lsp.buf.format</code></summary>

Below is a reference implementation for using `vim.lsp.buf.format` to replace the native implementation. This implementation won't be nearly as performant but it will be more correct.

```lua
local function lsp_indent(event, opts)
local traversal = require("nvim-paredit.utils.traversal")
local utils = require("nvim-paredit.indentation.utils")
local langs = require("nvim-paredit.lang")

local lang = langs.get_language_api()

local parent = event.parent

local child
if event.type == "slurp-forwards" then
child = parent:named_child(parent:named_child_count() - 1)
elseif event.type == "slurp-backwards" then
child = parent:named_child(1)
elseif event.type == "barf-forwards" then
child = traversal.get_next_sibling_ignoring_comments(event.parent, { lang = lang })
elseif event.type == "barf-backwards" then
child = event.parent
else
return
end

local child_range = { child:range() }
local lines = utils.find_affected_lines(child, utils.get_node_line_range(child_range))

vim.lsp.buf.format({
bufnr = opts.buf or 0,
range = {
["start"] = { lines[1] + 1, 0 },
["end"] = { lines[#lines] + 1, 0 },
},
})
end

require("nvim-paredit").setup({
indent = {
enabled = true,
indentor = lsp_indent
}
})
```
</details>

## Language Support

As this is built using Treesitter it requires that you have the relevant Treesitter grammar installed for your language of choice. Additionally `nvim-paredit` will need explicit support for the treesitter grammar as the node names and metadata of nodes vary between languages.
Expand Down Expand Up @@ -270,6 +349,7 @@ The main reasons you might want to consider `nvim-paredit` instead are:
- Easier configuration and an exposed lua API
- Control over how the cursor is moved during slurp/barf. (For example if you don't want the cursor to always be moved)
- Recursive slurp/barf operations. If your cursor is in a nested form you can still slurp from the forms parent(s)
- Automatic form/element indentations on slurp/barf
- Subjectively better out-of-the-box keybindings

### [vim-sexp-mappings-for-regular-people](https://github.com/tpope/vim-sexp-mappings-for-regular-people)
Expand Down
2 changes: 1 addition & 1 deletion lua/nvim-paredit/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ M.defaults = {
use_default_keys = true,
cursor_behaviour = "auto", -- remain, follow, auto
indent = {
enabled = true,
enabled = false,
indentor = require("nvim-paredit.indentation.native").indentor,
},
keys = {},
Expand Down

0 comments on commit e3aa905

Please sign in to comment.