UNPKG

lean4-code-actions

Version:

Refactorings and snippets for Lean 4

293 lines (184 loc) 8.28 kB
# VSCode Lean 4 Code Actions <p align="center"> <img src="./img/autoImport.gif"/> </p> <p align="center" style="padding: 20px 0"> <a href="https://marketplace.visualstudio.com/items?itemName=denis-gorbachev.lean4-code-actions&ssr=false"> <img src="https://img.shields.io/badge/Install-VSCode%20Marketplace-blue" /> </a> </p> ## Installation * [Install the extension](https://marketplace.visualstudio.com/items?itemName=denis-gorbachev.lean4-code-actions&ssr=false) * Add the keyboard shortcuts for [useful actions](#actions) Note: a custom language configuration is available as [a separate extension](https://github.com/DenisGorbachev/vscode-lean4-language-configuration#readme). ## Actions * [Create a new file](#create-a-new-file) * [Auto-import a definition](#auto-import) * [Update imports on rename](#update-imports-on-rename) * [Set argument style](#set-argument-style) * [Extract a definition to a separate file](#extract-a-definition-to-a-separate-file) * [Find-replace the current word within a code block](#find-replace-the-current-word-within-a-code-block) * [Convert a text block to a list of strings](#convert-a-text-block-to-a-list-of-strings) **Disclaimer:** the commands currently operate directly on text. As such, they have many limitations - for example, sometimes they don't properly detect Lean names. We have plans to reimplement the commands as proper code actions within LSP that operate on `Syntax` instead of text. ## Snippets * `imp` - expands to [configured imports](#configuration-options) * `op` - expands to [configured opens](#configuration-options) * `ns` - expands to `namespace ${currentFileName}` * `nsp` - expands to `namespace ${currentFilePath}` * `var` - expands to `variable (${name} : ${Type})` * `ind` - expands to `inductive` declaration * `struct` - expands to `structure` declaration * `cls` - expands to `class` declaration ## Configuration options * `lean4CodeActions.registerRenameProvider` - use this extension as a rename provider for `.lean` files * `lean4CodeActions.updateImportsOnFileRename` - update imports in other files when a file is renamed * `lean4CodeActions.namespace.prefix` - a prefix for top-level namespaces in generated code (added as `${prefix}.${body}`) * `lean4CodeActions.createNewFile.imports` - a list of Lean filenames to be imported. * `lean4CodeActions.createNewFile.opens` - a list of Lean namespaces to be opened. * `lean4CodeActions.createNewFile.derivings` - a list of Lean names to be derived. * `lean4CodeActions.defaultLib` - the default library to be used when creating a new file. If it's empty, the extension will ask you to choose the library interactively. ## Related work * [Std](https://github.com/leanprover/std4) already contains some [code actions](https://github.com/leanprover/std4/tree/main/Std/CodeAction) ### Create a new file <img src="./img/createNewFile.gif"/> **Before:** (Nothing) **After:** File: `CodeActions/Test/CreateNewFile/User.lean` ```lean namespace CodeActions.Test.CreateNewFile structure User where deriving Repr, Inhabited namespace User ``` **Notes:** * This command supports adding `import`, `open` and `deriving instance` commands via [configuration](#configuration-options). --- ### Auto-import <img src="./img/autoImport.gif" /> **Before:** ```lean def x : Rat := 1.0 ``` **After:** ```lean import Std.Data.Rat.Basic def x : Rat := 1.0 ``` **Gotchas:** * If you execute this command with an empty selection (just a cursor on the name), then only the part captured by [`getWordRangeAtPosition`](https://code.visualstudio.com/api/references/vscode-api#TextDocument.getWordRangeAtPosition) will be used. To import a hierarchical name, select it fully, then execute the command. Alternatively, you can enable detection of hierarchical names by installing [a custom language configuration](https://marketplace.visualstudio.com/items?itemName=denis-gorbachev.lean4-language-configuration). --- ### Update imports on rename <img src="./img/updateImports.gif" /> When you rename a file (or move it to another folder), it updates the imports in other files. **Before:** File 1: `CodeActions/Test/UpdateImports/Child.lean` ```lean namespace CodeActions.Test.UpdateImports.Child def x : Nat := 1 ``` File 2: `CodeActions/Test/UpdateImports/Parent.lean` ```lean import CodeActions.Test.UpdateImports.Child namespace CodeActions.Test.UpdateImports.Parent def y : Nat := 2 * Child.x ``` **After:** File 1: `CodeActions/Test/UpdateImports/Nested/RenamedChild.lean` ```lean namespace CodeActions.Test.UpdateImports.Child def x : Nat := 1 ``` File 2: `CodeActions/Test/UpdateImports/Parent.lean` ```lean import CodeActions.Test.UpdateImports.Nested.RenamedChild namespace CodeActions.Test.UpdateImports.Parent def y : Nat := 2 * Child.x ``` **Notes:** * This is a listener, not a command - it is executed automatically upon a file rename. It works even if you rename a file via another extension ([File Utils](https://marketplace.visualstudio.com/items?itemName=sleistner.vscode-fileutils), [File Bunny](https://marketplace.visualstudio.com/items?itemName=robole.file-bunny)). * It doesn't update the namespaces (should be done manually). * It can be disabled by setting `lean4CodeActions.updateImportsOnFileRename` to `false` --- ### Set argument style <img src="./img/setArgumentStyle.gif" /> **Before:** ```lean (α : Type u) ``` **After:** ```lean {α : Type u} ``` **Notes:** * The command supports four argument styles: [explicit](https://leanprover.github.io/theorem_proving_in_lean4/dependent_type_theory.html#function-abstraction-and-evaluation), [implicit strong](https://leanprover.github.io/theorem_proving_in_lean4/dependent_type_theory.html#implicit-arguments), [implicit weak](https://leanprover.github.io/theorem_proving_in_lean4/interacting_with_lean.html?#more-on-implicit-arguments), [typeclass](https://leanprover.github.io/theorem_proving_in_lean4/type_classes.html) (`()`, `{}`, `⦃⦄`, `[]`). --- ### Extract a definition to a separate file <img src="./img/extractDefinitionToSeparateFile.gif"/> **Before:** File 1: `CodeActions/Test/ExtractDefinition/Book.lean` ```lean namespace CodeActions.Test.ExtractDefinition structure Author where name : String structure Book where authors : List Author ``` **After:** File 1: `CodeActions/Test/ExtractDefinition/Book.lean` ```lean import CodeActions.Test.ExtractDefinition.Author namespace CodeActions.Test.ExtractDefinition structure Book where authors : List Author ``` File 2: `CodeActions/Test/ExtractDefinition/Author.lean` ```lean namespace CodeActions.Test.ExtractDefinition structure Author where name : String namespace Author ``` **How it works:** * It extracts a definition into a separate file * It adds an import to the original file **Gotchas:** * It doesn't add the `open` command yet --- ### Find-replace the current word within a code block <img src="./img/rename.gif" /> **Before:** ```lean def foo : IO String := do let text ← IO.FS.readFile "/tmp/secrets" return text ``` **After:** ```lean def foo : IO String := do let secrets ← IO.FS.readFile "/tmp/secrets" return secrets ``` You can use it to rename a local binding (if the variable name is a unique string of characters across the code block). **Gotchas:** * It's a simple find-replace: it doesn't distinguish between variables and text within strings, for example. * It's activated via "Rename Symbol" native command. If it causes problems, you can disable it by setting `lean4CodeActions.registerRenameProvider` to `false` in the extension configuration. * It relies on [`getWordRangeAtPosition`](https://code.visualstudio.com/api/references/vscode-api#TextDocument.getWordRangeAtPosition) to detect the word under cursor. You can improve the detection by installing [a custom language configuration](https://marketplace.visualstudio.com/items?itemName=denis-gorbachev.lean4-language-configuration). **Notes:** * A code block is defined as a continuous list of non-blank lines. --- ### Convert a text block to a list of strings <img src="./img/convertTextToList.gif" /> **Before:** ```text foo bar xyz ``` **After:** ```text "foo", "bar", "xyz" ``` Each line becomes an element of the list.