• Stars
    star
    256
  • Rank 158,379 (Top 4 %)
  • Language
    Lua
  • License
    MIT License
  • Created over 3 years ago
  • Updated 6 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

neovim support for the Lean theorem prover

lean.nvim

neovim support for the Lean Theorem Prover.

Screen.Recording.2022-04-03.at.21.13.28.mov

Prerequisites

lean.nvim supports the latest stable neovim release (currently 0.8.x) as well as the latest nightly.

(This matches what neovim itself supports upstream, which often guides what plugins end up working with).

Installation

Install via your favorite plugin manager. E.g., with vim-plug via:

Plug 'Julian/lean.nvim'
Plug 'neovim/nvim-lspconfig'
Plug 'nvim-lua/plenary.nvim'

" Optional Dependencies:

Plug 'hrsh7th/nvim-cmp'        " For LSP completion
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/vim-vsnip'       " For snippets
Plug 'andrewradev/switch.vim'  " For Lean switch support
Plug 'tomtom/tcomment_vim'     " For commenting motions

Both Lean 3 and Lean 4 are supported.

lean.nvim already includes syntax highlighting and Lean filetype support, so installing the lean.vim (i.e. non-neovim) plugin is not required or recommended.

Lean 3

For Lean 3 support, in addition to the instructions above, you should install lean-language-server, which can be done via e.g.:

$ npm install -g lean-language-server

Given that Lean 3's language server is separate from Lean itself, also ensure you've installed Lean 3 itself.

Lean 4

For Lean 4 support, a recent Lean 4 nightly build is recommended (one at least from late 2022).

Features

  • Abbreviation (unicode character) insertion (in insert mode & the command window accessible via q/)
  • An infoview which can show persistent goal, term & tactic state, as well as interactive widget support (which should function for most widgets renderable as text)
  • Hover (preview) commands:
    • :LeanGoal for showing goal state in a preview window
    • :LeanTermGoal for showing term-mode type information in a preview window
  • switch.vim base definitions for Lean
  • Simple snippets (in VSCode-compatible format, usable with e.g. vim-vsnip)
  • Lean library search path access via lean.current_search_path(), suitable for use with e.g. telescope.nvim for live grepping. See the wiki for a sample configuration.
  • Simple implementations of some editing helpers, such as try this suggestion replacement

Configuration & Usage

The short version -- after following the installation instructions above, add the below to ~/.config/nvim/plugin/lean.lua or an equivalent:

require('lean').setup{
  abbreviations = { builtin = true },
  lsp = { on_attach = on_attach },
  lsp3 = { on_attach = on_attach },
  mappings = true,
}

where on_attach should be your preferred LSP attach handler.

If you do not already have a preferred setup which includes LSP key mappings and (auto)completion, you may find the fuller example here in the wiki helpful. More detail on the full list of supported configuration options can be found below.

Semantic Highlighting

Lean 4 supports semantic highlighting, in which the Lean server itself will signal how to highlight terms and symbols within the editor using information available to it.

Semantic highlighting support in neovim is still being merged in upstream and is likely to be available in version 0.9 (or shortly thereafter), at which point this functionality will be usable in neovim.

If you're impatient or eager however, you can enable the functionality immediately by installing a plugin for semantic highlighting such as this one.

Note that if you do so, you still will want to map the semantic highlighting groups to your color scheme appropriately. For a sample setup, see the wiki.

Mappings

If you've set mappings = true in your configuration (or have called lean.use_suggested_mappings() explicitly), a number of keys will be mapped either within Lean source files or within Infoview windows:

In Lean Files

The key binding <LocalLeader> below refers to a configurable prefix key within vim (and neovim). You can check what this key is set to within neovim by running the command :echo maplocalleader. An error like E121: Undefined variable: maplocalleader indicates that it may not be set to any key. This can be configured by putting a line in your ~/.config/nvim/init.vim of the form let maplocalleader = "\<Space>" (in this example, mapping <LocalLeader> to <Space>).

Key Function
<LocalLeader>i toggle the infoview open or closed
<LocalLeader>p pause the current infoview
<LocalLeader>x place an infoview pin
<LocalLeader>c clear all current infoview pins
<LocalLeader>dx place an infoview diff pin
<LocalLeader>dc clear current infoview diff pin
<LocalLeader>dd toggle auto diff pin mode
<LocalLeader>dt toggle auto diff pin mode without clearing diff pin
<LocalLeader>s insert a sorry for each open goal
<LocalLeader>t replace a "try this:" suggestion under the cursor
<LocalLeader><Tab> jump into the infoview window associated with the current lean file
<LocalLeader>\\ show what abbreviation produces the symbol under the cursor

Note

See :help <LocalLeader> if you haven't previously interacted with the local leader key. Some vim users remap this key to make it easier to reach, so you may want to consider what key that means for your own keyboard layout. My (Julian's) <Leader> is set to <Space>, and my <LocalLeader> to <Space><Space>, which may be a good choice for you if you have no other preference.

In Infoview Windows

Key Function
<CR> click a widget or interactive area of the infoview
K click a widget or interactive area of the infoview
<Tab> jump into a tooltip (from a widget click)
<Shift-Tab> jump out of a tooltip and back to its parent
<Esc> clear all open tooltips
J jump into a tooltip (from a widget click)
C clear all open tooltips
I mouse-enter what is under the cursor
i mouse-leave what is under the cursor
gd go-to-definition of what is under the cursor
gD go-to-declaration of what is under the cursor
gy go-to-type of what is under the cursor
<LocalLeader><Tab> jump to the lean file associated with the current infoview window

Full Configuration & Settings Information

require('lean').setup{
  -- Enable the Lean language server(s)?
  --
  -- false to disable, otherwise should be a table of options to pass to
  --  `leanls` and/or `lean3ls`.
  --
  -- See https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#leanls for details.

  -- Lean 4  (on_attach is as above, your LSP handler)
  lsp = { on_attach = on_attach },

  -- Lean 3  (on_attach is as above, your LSP handler)
  lsp3 = { on_attach = on_attach },

  -- mouse_events = true will simulate mouse events in the Lean 3 infoview, this is buggy at the moment
  -- so you can use the I/i keybindings to manually trigger these
  lean3 = { mouse_events = false },

  ft = {
    -- What filetype should be associated with standalone Lean files?
    -- Can be set to "lean3" if you prefer that default.
    -- Having a leanpkg.toml or lean-toolchain file should always mean
    -- autodetection works correctly.
    default = "lean",

    -- A list of patterns which will be used to protect any matching
    -- Lean file paths from being accidentally modified (by marking the
    -- buffer as `nomodifiable`).
    nomodifiable = {
        -- by default, this list includes the Lean standard libraries,
        -- as well as files within dependency directories (e.g. `_target`)
        -- Set this to an empty table to disable.
    }
  },

  -- Abbreviation support
  abbreviations = {
    -- Enable expanding of unicode abbreviations?
    enable = true,
    -- additional abbreviations:
    extra = {
      -- Add a \wknight abbreviation to insert ♘
      --
      -- Note that the backslash is implied, and that you of
      -- course may also use a snippet engine directly to do
      -- this if so desired.
      wknight = '',
    },
    -- Change if you don't like the backslash
    -- (comma is a popular choice on French keyboards)
    leader = '\\',
  },

  -- Enable suggested mappings?
  --
  -- false by default, true to enable
  mappings = false,

  -- Infoview support
  infoview = {
    -- Automatically open an infoview on entering a Lean buffer?
    -- Should be a function that will be called anytime a new Lean file
    -- is opened. Return true to open an infoview, otherwise false.
    -- Setting this to `true` is the same as `function() return true end`,
    -- i.e. autoopen for any Lean file, or setting it to `false` is the
    -- same as `function() return false end`, i.e. never autoopen.
    autoopen = true,

    -- Set infoview windows' starting dimensions.
    -- Windows are opened horizontally or vertically depending on spacing.
    width = 50,
    height = 20,

    -- Put the infoview on the top or bottom when horizontal?
    -- top | bottom
    horizontal_position = "bottom",

    -- Always open the infoview window in a separate tabpage.
    -- Might be useful if you are using a screen reader and don't want too
    -- many dynamic updates in the terminal at the same time.
    -- Note that `height` and `width` will be ignored in this case.
    separate_tab = false,

    -- Show indicators for pin locations when entering an infoview window?
    -- always | never | auto (= only when there are multiple pins)
    indicators = "auto",
  },

  -- Progress bar support
  progress_bars = {
    -- Enable the progress bars?
    enable = true,
    -- Use a different priority for the signs
    priority = 10,
  },

  -- Redirect Lean's stderr messages somehwere (to a buffer by default)
  stderr = {
    enable = true,
    -- height of the window
    height = 5,
    -- a callback which will be called with (multi-line) stderr output
    -- e.g., use:
    --   on_lines = function(lines) vim.notify(lines) end
    -- if you want to redirect stderr to `vim.notify`.
    -- The default implementation will redirect to a dedicated stderr
    -- window.
    on_lines = nil,
  },
}

Other Plugins

Particularly if you're also a VSCode user, there may be other plugins you're interested in. Below is a (hopelessly incomplete) list of a few:

Contributing

Contributions are most welcome. Feel free to send pull requests for anything you'd like to see, or open an issue if you'd like to discuss.

Running the tests can be done via the Makefile:

$ make test

which will execute against a minimal vimrc isolated from your own setup.

$ TEST_FILE=lua/tests/foo_spec.lua make test

can be used to run just one specific test file, which can be faster.

Some linting and style checking is done via pre-commit, which once installed (via the linked instructions) is run via:

$ make lint

or on each commit automatically if you have run pre-commit install in your repository checkout.

You can also use

$ make nvim SETUP_TABLE='{ lsp3 = { enable = true }, mappings = true }'

to get a normal running neovim (again isolated from your own configuration), where SETUP_TABLE is a (Lua) table like one would pass to lean.setup.

More Repositories

1

vim-textobj-variable-segment

A text object to turn foo_bar_baz into foo_baz *and* quuxSpamEggs into quuxEggs *and* shine your shoes
Vim Script
147
star
2

awesome-bugs

A collection of bizarre, funny or obscure bugs in our software and hardware
122
star
3

Ivoire

A simple BDD testing framework for Python
Python
60
star
4

dotfiles

A work in progress. Forever.
Vim Script
43
star
5

tree-sitter-lean

Experimental tree-sitter parser for the Lean (4) Theorem Prover
C
28
star
6

Seep

A transformation and data extraction language on top of JSON Schema
Python
25
star
7

avif

Python (CFFI) bindings for libavif
Python
16
star
8

venvs

venvs creates virtualenvs
Python
16
star
9

regret

You made a thing, but now you wish it'd go away... Deprecations, a love story.
Python
14
star
10

vim-textobj-brace

A text object for the closest inner () {} *or* []
Vim Script
13
star
11

PyVi

A library for integrating Vim-like buffers, windows, and keybindings into your Python application.
Python
11
star
12

lftim

Mathematical learnings with Lean, for those of us who wish we knew more of both!
Lean
10
star
13

til

Joining the TIL bandwagon
CSS
8
star
14

homebrew-tap

Homebrew Formulae I'm Tired of Maintainin'
Ruby
7
star
15

cardboard

Cardboard is a Magic: The Gathering game engine written in Python.
Python
7
star
16

Minion

A microframework based on evil intentions and whatever else you've got
Python
6
star
17

veb

Dynamically allocated van Emde Boas trees
Python
5
star
18

python-musicalsort

A *very* basic musical sort decorator / demo module
Python
4
star
19

lean-unicode.vim

Unicode translation (of e.g. \l to ← as in other Lean environments), for (n)vim
Vim Snippet
3
star
20

findme

CLI for hypothesis.find
Python
3
star
21

hypothesis-protobuf

Hypothesis support for generating Protobuf Messages and instances thereof
Python
3
star
22

lean-across-the-board

An attempt to learn Lean via implementing a theorem (hopefully more) from Across the Board. Progress will be... slow.
Lean
3
star
23

txdatadog

Datadog statsd APIs for Twisted
Python
2
star
24

txjsonrpc-tcp

A TCP implementation of JSON RPC for Twisted
Python
2
star
25

ml-crash-course

Materials for a Machine Learning Crash Course Given at Columbia University
Jupyter Notebook
2
star
26

Filesystems

A filesystem abstraction layer
Python
2
star
27

BuildingAnInterpreter

2
star
28

Virtue

A modern, extensible, unittest-compliant test runner.
Python
2
star
29

setup-lean

Set up your GitHub Actions workflow with elan and/or a specific version of Lean
Python
2
star
30

Great

A ratings aggregator
Python
1
star
31

cast-cli

A simple CLI for pychromecast.
Python
1
star
32

L

In 2015, another `ls`
Python
1
star
33

libopenzwave-cffi

OpenZWave CFFI Bindings
Python
1
star
34

composition

What You Crave
Python
1
star
35

regress

Python bindings to the Rust regress crate (for Javascript regular expressions)
Python
1
star
36

sphinxcontrib-githubcomments

Clojure
1
star
37

Pi

Installation and setup for my RPi
Dockerfile
1
star
38

pb

Python
1
star
39

giraffe

A small python graph library.
C
1
star
40

eocs

Python
1
star
41

svmlight-loader

A Cython-less implementation of the svmlight / libsvm sparse data format
Python
1
star
42

libraw-cffi

CFFI bindings for LibRaw
Python
1
star
43

vim-textobj-assignment

A text object for variable assignments
Vim Script
1
star
44

Stylish

CSS User Styles
CSS
1
star
45

Condent

A quick hack I threw together to reindent and respace containers the way I like them (e.g. for equalprg in Vim)
Python
1
star
46

Movies

Movie lists
1
star
47

named-branch-action

hg-style named branches via a GitHub action
Dockerfile
1
star
48

people-I-mostly-admire

1
star
49

aiodocker-test

Python
1
star