Skip to content

Commit 0c11b53

Browse files
committed
Add support for conv? widgets.
1 parent 509eff4 commit 0c11b53

8 files changed

Lines changed: 189 additions & 6 deletions

File tree

demos/project/lake-manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "git",
66
"subDir": null,
77
"scope": "",
8-
"rev": "537a98e0c053976429d5fe61d843c5c8ac2c892e",
8+
"rev": "30ae5addc4aba5803b38de4777e03f3a720a9dea",
99
"name": "mathlib",
1010
"manifestFile": "lake-manifest.json",
1111
"inputRev": null,
@@ -75,7 +75,7 @@
7575
"type": "git",
7676
"subDir": null,
7777
"scope": "leanprover-community",
78-
"rev": "9f34f4e523881779f8ba46c394c28571c4999db7",
78+
"rev": "795ab4977cc1b41273258b736585b9b3def9081c",
7979
"name": "batteries",
8080
"manifestFile": "lake-manifest.json",
8181
"inputRev": "main",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---@brief [[
2+
--- The `conv?` Mathlib widget.
3+
---
4+
--- (It's not namespaced, so it shows up here "globally".)
5+
---@brief ]]
6+
7+
local Html = require 'proofwidgets.html'
8+
local widgets = require 'lean.widgets'
9+
10+
---The `conv?` Mathlib widget.
11+
---@param ctx RenderContext
12+
---@param params PanelWidgetProps
13+
return widgets.panel(function(ctx, params)
14+
local response, err = ctx:rpc_call('ConvSelectionPanel.rpc', params)
15+
if err then
16+
return err
17+
end
18+
return Html(response, ctx)
19+
end)

lua/proofwidgets/html.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local inductive = require 'std.inductive'
22

33
local Element = require('lean.tui').Element
44
local InteractiveCode = require 'lean.widget.interactive_code'
5+
local MakeEditLink = require 'proofwidgets.make_edit_link'
56
local Tag = require('tui.html').Tag
67

78
---@class HtmlElement
@@ -43,6 +44,8 @@ local Html = inductive('Html', {
4344
Element:new { children = children },
4445
},
4546
}
47+
elseif props.edit then
48+
return MakeEditLink(props, children, ctx)
4649
end
4750

4851
return Element:new {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
local position_to_byte0 = require('std.lsp').position_to_byte0
2+
3+
local Element = require('lean.tui').Element
4+
5+
local hl_ns = vim.api.nvim_create_namespace 'proofwidgets.make_edit_link'
6+
7+
---@class MakeEditLinkProps
8+
---@field edit lsp.TextDocumentEdit The edit to perform on the file.
9+
---@field newSelection? lsp.Range Which textual range to select after the edit.
10+
--- The range is interpreted in the file that `edit` applies to.
11+
--- If present and `start == end`, the cursor is moved to `start`
12+
--- and nothing is selected.
13+
--- If not present, the selection is not changed.
14+
---@field title? string
15+
16+
---@param props MakeEditLinkProps
17+
---@param children Element[]
18+
---@param ctx RenderContext
19+
return function(props, children, ctx)
20+
return Element:new {
21+
children = children,
22+
highlightable = true,
23+
hlgroup = 'widgetLink',
24+
events = {
25+
click = function()
26+
local bufnr = vim.uri_to_bufnr(props.edit.textDocument.uri)
27+
if not vim.api.nvim_buf_is_loaded(bufnr) then
28+
return
29+
end
30+
vim.lsp.util.apply_text_document_edit(props.edit, nil, 'utf-16')
31+
if props.newSelection then
32+
local start = position_to_byte0(props.newSelection.start, bufnr)
33+
if vim.deep_equal(props.newSelection.start, props.newSelection['end']) then
34+
local last_window = ctx.get_last_window()
35+
if not last_window then
36+
return
37+
end
38+
last_window:make_current()
39+
last_window:set_cursor(start)
40+
else
41+
vim.hl.range(
42+
bufnr,
43+
hl_ns,
44+
'widgetChangedText',
45+
start,
46+
position_to_byte0(props.newSelection['end'], bufnr),
47+
{ timeout = 1000 }
48+
)
49+
end
50+
end
51+
end,
52+
},
53+
}
54+
end

lua/tui/html.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function html.Tag.div(children)
3636
text = '\n', -- TODO: clearly this isn't fully "block" element-y
3737
children = {
3838
Element:new { children = children },
39-
Element:new { text = '\n' },
39+
-- Element:new { text = '\n' },
4040
},
4141
}
4242
end

spec/fixtures/example-project/lake-manifest.json

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
{"version": "1.1.0",
22
"packagesDir": ".lake/packages",
33
"packages":
4-
[{"url": "https://github.com/leanprover-community/ProofWidgets4",
4+
[{"url": "https://github.com/leanprover-community/mathlib4",
5+
"type": "git",
6+
"subDir": null,
7+
"scope": "leanprover-community",
8+
"rev": "30ae5addc4aba5803b38de4777e03f3a720a9dea",
9+
"name": "mathlib",
10+
"manifestFile": "lake-manifest.json",
11+
"inputRev": "master",
12+
"inherited": false,
13+
"configFile": "lakefile.lean"},
14+
{"url": "https://github.com/leanprover-community/ProofWidgets4",
515
"type": "git",
616
"subDir": null,
717
"scope": "leanprover-community",
@@ -28,14 +38,54 @@
2838
"inherited": false,
2939
"dir": "foo",
3040
"configFile": "lakefile.toml"},
41+
{"url": "https://github.com/leanprover-community/plausible",
42+
"type": "git",
43+
"subDir": null,
44+
"scope": "leanprover-community",
45+
"rev": "304c5e2f490d546134c06bf8919e13b175272084",
46+
"name": "plausible",
47+
"manifestFile": "lake-manifest.json",
48+
"inputRev": "main",
49+
"inherited": true,
50+
"configFile": "lakefile.toml"},
51+
{"url": "https://github.com/leanprover-community/LeanSearchClient",
52+
"type": "git",
53+
"subDir": null,
54+
"scope": "leanprover-community",
55+
"rev": "25078369972d295301f5a1e53c3e5850cf6d9d4c",
56+
"name": "LeanSearchClient",
57+
"manifestFile": "lake-manifest.json",
58+
"inputRev": "main",
59+
"inherited": true,
60+
"configFile": "lakefile.toml"},
61+
{"url": "https://github.com/leanprover-community/aesop",
62+
"type": "git",
63+
"subDir": null,
64+
"scope": "leanprover-community",
65+
"rev": "76a782b161da3faacc43aa5471bbd2e1d262970a",
66+
"name": "aesop",
67+
"manifestFile": "lake-manifest.json",
68+
"inputRev": "master",
69+
"inherited": true,
70+
"configFile": "lakefile.toml"},
71+
{"url": "https://github.com/leanprover-community/quote4",
72+
"type": "git",
73+
"subDir": null,
74+
"scope": "leanprover-community",
75+
"rev": "36ce5e17d6ab3c881e0cb1bb727982507e708130",
76+
"name": "Qq",
77+
"manifestFile": "lake-manifest.json",
78+
"inputRev": "master",
79+
"inherited": true,
80+
"configFile": "lakefile.toml"},
3181
{"url": "https://github.com/leanprover-community/batteries",
3282
"type": "git",
3383
"subDir": null,
3484
"scope": "leanprover-community",
35-
"rev": "cb53cd3f2958ee503f97ea6162929cabaf96bde9",
85+
"rev": "795ab4977cc1b41273258b736585b9b3def9081c",
3686
"name": "batteries",
3787
"manifestFile": "lake-manifest.json",
38-
"inputRev": "v4.20.0-rc2",
88+
"inputRev": "main",
3989
"inherited": true,
4090
"configFile": "lakefile.toml"},
4191
{"url": "https://github.com/leanprover/lean4-cli",

spec/fixtures/example-project/lakefile.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,9 @@ scope = "leanprover-community"
1313
name = "proofwidgets"
1414
scope = "leanprover-community"
1515

16+
[[require]]
17+
name = "mathlib"
18+
scope = "leanprover-community"
19+
1620
[[lean_lib]]
1721
name = "Test"

spec/widgets/mathlib_spec.lua

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---@brief [[
2+
--- Tests for widgets from Mathlib.
3+
---@brief ]]
4+
5+
local helpers = require 'spec.helpers'
6+
local infoview = require 'lean.infoview'
7+
8+
require('lean').setup {}
9+
10+
describe('Mathlib widgets', function()
11+
it(
12+
'supports conv? widgets',
13+
helpers.clean_buffer(
14+
[[
15+
import Mathlib.Tactic.Widget.Conv
16+
17+
example {n : Nat} : n = n := by
18+
conv?
19+
]],
20+
function()
21+
helpers.search 'conv?'
22+
assert.infoview_contents.are [[
23+
n : Nat
24+
⊢ n = n
25+
26+
Nothing selected. You can use gK in the infoview to select expressions in the goal.
27+
]]
28+
29+
infoview.go_to()
30+
helpers.feed 'gK'
31+
32+
assert.infoview_contents.are [[
33+
n : Nat
34+
⊢ n = n
35+
36+
▼ Conv 🔍
37+
Generate conv
38+
]]
39+
40+
helpers.search 'Generate'
41+
helpers.feed '<CR>'
42+
43+
assert.infoview_contents.are [[
44+
n : Nat
45+
| n = n
46+
]]
47+
48+
-- We've jumped to the Lean window.
49+
assert.current_line.is ' conv =>'
50+
end
51+
)
52+
)
53+
end)

0 commit comments

Comments
 (0)