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

Rewrite indentation code #31

Draft
wants to merge 87 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
7d6bdd7
Begin rewrite of indentation code
axvr Apr 21, 2023
5706ea3
Double (or better) indent performance!
axvr Apr 21, 2023
5f083ff
A bit of code clean up and minor optimisations
axvr Apr 21, 2023
f4e0689
Check for maps before vectors for further performance enhancement
axvr Apr 21, 2023
2627e1c
Add fallback for when Vim was not compiled with `searchpairpos`
axvr Apr 21, 2023
4a3cab7
Fix string detection when entering a newline while in insert mode
axvr Apr 26, 2023
d1ec02c
Minor performance improvement when file contains multi-line strings
axvr Apr 26, 2023
c3047be
Mimic multi-line string/regex indent behaviour of VS Code and Emacs
axvr Apr 27, 2023
eb0463e
When `clojure_align_multiline_strings` is `-1`, no indentation
axvr Apr 27, 2023
d69008f
Update indentation options sections of the README and vim help file
axvr Apr 27, 2023
d73e408
Improve some of the comments in the indentation code
axvr Apr 27, 2023
d177b3b
Move string indent picker to a separate function
axvr Apr 27, 2023
51e6a43
Fix false positive multi-line string detection
axvr Apr 28, 2023
e573da7
EDN files are unlikely to contain many lists, so check them last
axvr Apr 28, 2023
242dc9d
Yet more string detection fixes and slight code clean up
axvr Apr 28, 2023
342f35f
Initial work on list indentation
axvr Apr 28, 2023
51f5dcb
More indentation code clean up and readability improvements
axvr Apr 28, 2023
cc9cda7
Start of a small Clojure reader for indentation w/o syntax highlighting
axvr Apr 30, 2023
ee2acc2
Completed the mini Clojure reader as the core of the indentation system
axvr Apr 30, 2023
bdbc281
Reader indent algorithm perf has surpassed the prev syntax highlight one
axvr May 1, 2023
8ee73c5
Small refactor to improve code clarity in indentation code
axvr May 1, 2023
a4beb52
Fix indentation bug during comment detection
axvr May 29, 2023
3d8197e
Fix accidental detection of backslashes as tokens
axvr Jun 10, 2023
101c9a4
Update indent comments and move `s:Conf` function to the top
axvr Jun 26, 2023
35e0234
Add basic function parameter alignment indentation
axvr Jun 26, 2023
787e1e8
Replace `clojure_align_subforms` with `clojure_indent_style`
axvr Jun 26, 2023
bfce724
Update and add a bunch of indentation tests
axvr Jun 26, 2023
a2ffcba
Fix indentation for multibyte characters
axvr Jun 26, 2023
09720fe
Switch test runner to Kaocha for nicer output
axvr Jun 26, 2023
2728db2
Only run GitHub Actions workflow once for PRs
axvr Jun 26, 2023
d51154a
Neovim does not have a `state()` function
axvr Aug 12, 2023
f3d889f
Initial work on building up macro indent rules
axvr Aug 13, 2023
bf4cf3d
Fix false-positive comment detection within strings
axvr Aug 13, 2023
caef0c5
Improve accuracy of multiline string detection for indentation
axvr Aug 13, 2023
3dbc6dd
Fix indentation when file contains multibyte characters
axvr Aug 13, 2023
5550111
Add more indent test cases
axvr Aug 13, 2023
b8aef1b
Neovim has added the `state()` function; use it if available
axvr Dec 23, 2023
b2c392d
Fix application of inline comments during indentation
axvr Dec 23, 2023
4edeef0
Add tests to check that comments don't affect indentation
axvr Dec 23, 2023
0388414
Fix indentation of `with-*` macros
axvr Dec 23, 2023
41a45d4
Update comments and add `with-in-str` indent rule
axvr Dec 23, 2023
68999ca
Improve accuracy of function operand indenting
axvr Dec 25, 2023
8f38c11
Slight code refactor and added more comments
axvr Dec 26, 2023
7e90f09
When `lispoptions` feature is available, we can enable the `lisp` option
axvr Dec 26, 2023
0b388ae
Indent some macros a bit like functions
axvr Dec 26, 2023
289352d
More indent test cases
axvr Mar 9, 2024
cefb7bc
Fix escape character detection logic
axvr Mar 10, 2024
16026f7
Simplify character column resolution
axvr Mar 10, 2024
d87f254
Add some indent rules for more built in macros
axvr Mar 10, 2024
6a3d2d3
Don't use fn arg alignment indent when a keyword is in function position
axvr Sep 22, 2024
083f554
Merge 'origin/master' into indent-forms
axvr Sep 22, 2024
f271dca
Add extra indentation test cases for records and protocols
axvr Sep 22, 2024
b86a4c0
Begin refinements to configuration options
axvr Oct 4, 2024
01edfec
Fix config option lookup
axvr Oct 4, 2024
9b5e42c
Discovered a way to put comments within dict defs in Vim script
axvr Oct 4, 2024
a41fa1b
Improve indentation in "uniform" style and undo reader conditional work
axvr Oct 5, 2024
3487e07
Update README to better cover the new indentation options
axvr Oct 5, 2024
3c5258c
Replace the old multi-line string config option
axvr Oct 5, 2024
3b4dad8
Remove the link to the #vim IRC as the link is now dead
axvr Oct 5, 2024
117b082
Fix typos and re-add the insert-mode completion info to the README
axvr Oct 5, 2024
b26db95
Update the "About" section within the Vim help doc
axvr Oct 5, 2024
c4a25c5
Update indentation section of the Vim help doc
axvr Oct 5, 2024
1742549
Improve indentation style examples in Vim help doc
axvr Oct 5, 2024
9800368
Minor documentation and comment refinements
axvr Oct 5, 2024
69a0b6f
In README, mention the replacements for each old indent config option
axvr Oct 5, 2024
058b4a7
Add indentation tests covering keywords in function position
axvr Oct 6, 2024
0a835d8
Update indent regular expressions to set the required 'magic' mode
axvr Oct 6, 2024
0d865c5
Compress comments on indent code
axvr Oct 7, 2024
052a498
Compress more comments on indent code
axvr Oct 7, 2024
55543c4
Use `<kbd>` to show keyboard shortcuts in `README.md`
axvr Oct 13, 2024
208ff9f
Improved accuracy of first function argument detection in indentation
axvr Jan 18, 2025
968340e
Slightly improve keyboard shortcut formatting in `README.md`
axvr Jan 18, 2025
082120a
Set mode in new regexprs
axvr Jan 18, 2025
161ea5f
Make `ClojureIndent()` function public
axvr Jan 19, 2025
78ecad5
Indent `with-` macros and functions like cljfmt default
axvr Jan 19, 2025
6ce7017
Run indentation tests against Vim AND Neovim
axvr Jan 25, 2025
d2f39f9
Install latest Vim and Neovim in GitHub Actions
axvr Jan 25, 2025
8e9ed28
Merge latest changes from 'origin/master'
axvr Jan 25, 2025
e5f86af
New indentation test runner
axvr Jan 26, 2025
7659541
Improve new test runner output and detect script errors
axvr Jan 26, 2025
1ea333a
Speed up indentation tests on Vim
axvr Jan 26, 2025
aae9ae8
Move `indenttime` script to `dev` folder as `time-indent`
axvr Jan 26, 2025
1883215
Update GitHub Actions
axvr Jan 26, 2025
5f995a1
Kaocha not needed anymore, so removing dependency
axvr Jan 26, 2025
f3358f3
Bump copyright year
axvr Jan 26, 2025
13ca6fe
Remove unneeded config from `clj/profile.clj`
axvr Jan 26, 2025
5b277db
Run indentation tests in Vim's silent Ex-improved mode
axvr Jan 26, 2025
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
28 changes: 28 additions & 0 deletions .github/workflows/indent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Indent
on:
push: { branches: [ master ] }
pull_request:
workflow_dispatch:

jobs:
vim-latest:
runs-on: ubuntu-latest
steps:
- name: Fetch source
uses: actions/checkout@v4
- name: Install Vim
uses: rhysd/action-setup-vim@v1
with: { version: stable }
- name: Run indentation tests
run: EDITOR=vim dev/do/test-indent

neovim-latest:
runs-on: ubuntu-latest
steps:
- name: Fetch source
uses: actions/checkout@v4
- name: Install Neovim
uses: rhysd/action-setup-vim@v1
with: { neovim: true, version: stable }
- name: Run indentation tests
run: EDITOR=nvim dev/do/test-indent
11 changes: 7 additions & 4 deletions .github/workflows/clojure.yml → .github/workflows/syntax.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: CI
on: [push, pull_request, workflow_dispatch]
name: Syntax
on:
push: { branches: [ master ] }
pull_request:
workflow_dispatch:

jobs:
lint:
Expand All @@ -10,7 +13,7 @@ jobs:
with:
clj-kondo: latest

- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Lint
working-directory: ./clj
Expand All @@ -19,7 +22,7 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: DeLaGuardo/[email protected]
with:
lein: 2.11.2
Expand Down
195 changes: 75 additions & 120 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,23 @@
# Clojure.vim

[Clojure][] syntax highlighting for Vim and Neovim, including:
**Configurable [Clojure][] syntax highlighting, indentation (and more) for Vim and Neovim!**

- [Augmentable](#syntax-options) syntax highlighting.
- [Configurable](#indent-options) indentation.
- Basic insert-mode completion of special forms and public vars in
`clojure.core`. (Invoke with `<C-x><C-o>` or `<C-x><C-u>`.)
> [!TIP]
> This plugin comes packaged with Vim and Neovim. However if you would like to
> always use the latest version, you can install this plugin like you would any
> other.


## Installation

These files are included in both Vim and Neovim. However if you would like the
latest changes just install this repository like any other plugin.

Make sure that the following options are set in your vimrc so that all features
are enabled:
Make sure your vimrc contains the following options to enable all features:

```vim
syntax on
filetype plugin indent on
```


## Configuration

### Folding

Setting `g:clojure_fold` to `1` will enable the folding of Clojure code. Any
list, vector or map that extends over more than one line can be folded using
the standard Vim fold commands.

(Note that this option will not work with scripts that redefine the bracket
regions, such as rainbow parenphesis plugins.)


### Syntax options
## Syntax highlighting

#### `g:clojure_syntax_keywords`
### `g:clojure_syntax_keywords`

Syntax highlighting of public vars in `clojure.core` is provided by default,
but additional symbols can be highlighted by adding them to the
Expand All @@ -60,127 +41,104 @@ will not be highlighted by default. This is useful for namespaces that have
set `(:refer-clojure :only [])`.


#### `g:clojure_discard_macro`
### `g:clojure_discard_macro`

Set this variable to `1` to enable highlighting of the
"[discard reader macro](https://clojure.org/guides/weird_characters#_discard)".
Due to current limitations in Vim's syntax rules, this option won't highlight
stacked discard macros (e.g. `#_#_`). This inconsitency is why this option is
stacked discard macros (e.g. `#_#_`). This inconsistency is why this option is
disabled by default.


### Indent options

Clojure indentation differs somewhat from traditional Lisps, due in part to
the use of square and curly brackets, and otherwise by community convention.
These conventions are not universally followed, so the Clojure indent script
offers a few configuration options.

(If the current Vim does not include `searchpairpos()`, the indent script falls
back to normal `'lisp'` indenting, and the following options are ignored.)


#### `g:clojure_maxlines`
## Indentation

Sets maximum scan distance of `searchpairpos()`. Larger values trade
performance for correctness when dealing with very long forms. A value of
0 will scan without limits. The default is 300.
Clojure indentation differs somewhat from traditional Lisps, due in part to the
use of square and curly brackets, and otherwise by community convention. As
these conventions are not universally followed, the Clojure indent script
offers ways to adjust the indentation.

> [!WARNING]
> The indentation code has recently been rebuilt which included the
> removal/replacement of the following configuration options:
>
> | Config option | Replacement (if any) |
> |-----------------------------------|------------------------------------|
> | `clojure_maxlines` | |
> | `clojure_cljfmt_compat` | `clojure_indent_style` |
> | `clojure_align_subforms` | `clojure_indent_style` |
> | `clojure_align_multiline_strings` | `clojure_indent_multiline_strings` |
> | `clojure_fuzzy_indent` | |
> | `clojure_fuzzy_indent_blacklist` | |
> | `clojure_special_indent_words` | `clojure_indent_rules` |
> | `'lispwords'` | `clojure_indent_rules` |

#### `g:clojure_fuzzy_indent`, `g:clojure_fuzzy_indent_patterns`, `g:clojure_fuzzy_indent_blacklist`

The `'lispwords'` option is a list of comma-separated words that mark special
forms whose subforms should be indented with two spaces.
### Indentation style

For example:
The `clojure_indent_style` config option controls the general indentation style
to use. Choose from several common presets:

```clojure
(defn bad []
"Incorrect indentation")

(defn good []
"Correct indentation")
```

If you would like to specify `'lispwords'` with a pattern instead, you can use
the fuzzy indent feature:
| Value | Default | Description |
|-------|---------|-------------|
| `standard` | ✅ | Conventional Clojure indentation. ([_Clojure Style Guide_](https://guide.clojure.style/).) |
| `traditional` | | Indent like traditional Lisps. (Earlier versions of Clojure.vim indented like this.) |
| `uniform` | | Indent uniformly to 2 spaces with no alignment (a.k.a. [_Tonsky_ indentation](https://tonsky.me/blog/clojurefmt/)). |

```vim
" Default
let g:clojure_fuzzy_indent = 1
let g:clojure_fuzzy_indent_patterns = ['^with', '^def', '^let']
let g:clojure_fuzzy_indent_blacklist = ['-fn$', '\v^with-%(meta|out-str|loading-context)$']
let g:clojure_indent_style = 'uniform' " Set the default...
let b:clojure_indent_style = 'traditional' " ...or override it per-buffer.
```

`g:clojure_fuzzy_indent_patterns` and `g:clojure_fuzzy_indent_blacklist` are
lists of patterns that will be matched against the unqualified symbol at the
head of a list. This means that a pattern like `"^foo"` will match all these
candidates: `foobar`, `my.ns/foobar`, and `#'foobar`.

Each candidate word is tested for special treatment in this order:

1. Return true if word is literally in `'lispwords'`
2. Return false if word matches a pattern in `g:clojure_fuzzy_indent_blacklist`
3. Return true if word matches a pattern in `g:clojure_fuzzy_indent_patterns`
4. Return false and indent normally otherwise
### Indentation rules

> [!NOTE]
> These options are ignored if an indentation style of "uniform" is selected.

#### `g:clojure_special_indent_words`
<!-- TODO: write this section. -->

Some forms in Clojure are indented such that every subform is indented by only
two spaces, regardless of `'lispwords'`. If you have a custom construct that
should be indented in this idiosyncratic fashion, you can add your symbols to
the default list below.
`clojure_indent_rules` & `clojure_fuzzy_indent_patterns`

```vim
" Default
let g:clojure_special_indent_words = 'deftype,defrecord,reify,proxy,extend-type,extend-protocol,letfn'
```

### Multi-line strings

#### `g:clojure_align_multiline_strings`
Control alignment of _new_ lines within Clojure multi-line strings and regular
expressions with `clojure_indent_multiline_strings`.

Align subsequent lines in multi-line strings to the column after the opening
quote, instead of the same column.
> [!NOTE]
> Indenting with <kbd>=</kbd> will not alter the indentation within multi-line
> strings, as this could break intentional formatting.

For example:
Pick from the following multi-line string indent styles:

```clojure
(def default
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.")
| Value | Default | Description |
|-------|---------|-------------|
| `standard` | ✅ | Align to the _front_ of the `"` or `#"` delimiter. Ideal for doc-strings. |
| `pretty` | | Align to the _back_ of the `"` or `#"` delimiter. |
| `traditional` | | No indent: align to left edge of file. |

(def aligned
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.")
```vim
let g:clojure_indent_multiline_strings = 'pretty' " Set the default...
let b:clojure_indent_multiline_strings = 'traditional' " ...or override it per-buffer.
```


#### `g:clojure_align_subforms`
## Code folding

By default, parenthesized compound forms that look like function calls and
whose head subform is on its own line have subsequent subforms indented by
two spaces relative to the opening paren:
Setting `g:clojure_fold` to `1` will enable the folding of Clojure code. Any
list, vector or map that extends over more than one line can be folded using
the standard Vim fold commands.

```clojure
(foo
bar
baz)
```
(Note that this option will not work with scripts that redefine the bracket
regions, such as rainbow parenthesis plugins.)

Setting this option to `1` changes this behaviour so that all subforms are
aligned to the same column, emulating the default behaviour of
[clojure-mode.el](https://github.com/clojure-emacs/clojure-mode):

```clojure
(foo
bar
baz)
```
## Insert-mode completion

Very basic insert-mode completion of special forms and public vars from
`clojure.core` is included in Clojure.vim. Invoke it with
<kbd>Ctrl</kbd> <kbd>x</kbd> <kbd>Ctrl</kbd> <kbd>o</kbd> or
<kbd>Ctrl</kbd> <kbd>x</kbd> <kbd>Ctrl</kbd> <kbd>u</kbd>.


## Contribute
Expand All @@ -195,18 +153,15 @@ Pull requests are welcome! Make sure to read the
_Vim-clojure-static_ was created by [Sung Pae](https://github.com/guns). The
original copies of the packaged runtime files came from
[Meikel Brandmeyer](http://kotka.de/)'s [VimClojure][] project with permission.

Thanks to [Tim Pope](https://github.com/tpope/) for advice in
[#vim](https://www.vi-improved.org/).
Thanks to [Tim Pope](https://github.com/tpope/) for advice in `#vim` on IRC.


## License

Clojure.vim is licensed under the [Vim
License](http://vimdoc.sourceforge.net/htmldoc/uganda.html#license) for
distribution with Vim.
Clojure.vim is licensed under the [Vim License](http://vimdoc.sourceforge.net/htmldoc/uganda.html#license)
for distribution with Vim.

- Copyright © 2020–2021, The clojure-vim contributors.
- Copyright © 2020–2025, The clojure-vim contributors.
- Copyright © 2013–2018, Sung Pae.
- Copyright © 2008–2012, Meikel Brandmeyer.
- Copyright © 2007–2008, Toralf Wittner.
Expand Down
5 changes: 0 additions & 5 deletions clj/resources/indent-test-cases/basic-sexp/in.clj

This file was deleted.

5 changes: 0 additions & 5 deletions clj/resources/indent-test-cases/basic-sexp/out.clj

This file was deleted.

29 changes: 0 additions & 29 deletions clj/resources/indent-test-cases/dispach-macro/in.clj

This file was deleted.

29 changes: 0 additions & 29 deletions clj/resources/indent-test-cases/dispach-macro/out.clj

This file was deleted.

This file was deleted.

Loading
Loading