Skip to content

Commit 67b38d3

Browse files
authored
Merge pull request #7 from willothy/input-placeholder
feat: extmark-based placeholder for text inputs
2 parents 6202be4 + 2d8ec98 commit 67b38d3

File tree

4 files changed

+89
-11
lines changed

4 files changed

+89
-11
lines changed

docs/pages/docs/components/prompt.mdx

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Property } from '../../../components/Property'
1111
```lua
1212
n.prompt({
1313
prefix = " > ",
14+
placeholder = "Enter a command",
1415
border_label = {
1516
text = "Command",
1617
align = "center",
@@ -25,31 +26,51 @@ n.prompt({
2526

2627
#### value
2728

28-
<Property
29+
<Property
2930
types={["string"]}
3031
/>
3132

3233
#### prefix
3334

34-
<Property
35+
<Property
3536
types={["string"]}
3637
/>
3738

39+
#### placeholder
40+
41+
> Optional placeholder text to show when the input is empty.
42+
> Can be a string, a single virtual text chunk, or a list of virtual text chunks.
43+
44+
<Property
45+
defaultValue='nil'
46+
types={['string', '{ [1]: string, [2]: string }[]', 'nil']}
47+
/>
48+
49+
A virtual text chunk is a tuple-like table where the first element
50+
is the text and the second element is the highlight group.
51+
52+
```lua
53+
local placeholder = {
54+
{ "Hello", "Comment" },
55+
{ "World", "String" },
56+
}
57+
```
58+
3859
#### on_change
3960

40-
<Property
61+
<Property
4162
types={['fun(value: string, component: Prompt): nil']}
4263
/>
4364

4465
#### on_submit
4566

46-
<Property
67+
<Property
4768
types={['fun(value: string, component: Prompt): nil']}
4869
/>
4970

5071
#### submit_key
5172

52-
<Property
73+
<Property
5374
defaultValue="<CR>"
5475
types={["string[]", "string"]}
5576
/>

docs/pages/docs/components/text-input.mdx

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import { Property } from '../../../components/Property'
33

44
## TextInput
55

6-
`TextInput` is a component that allows you to enter any text.
6+
`TextInput` is a component that allows you to enter any text.
77

88
![](/gifs/text-input-1.gif)
99

1010
### Usage Example
1111

1212
```lua
13-
local signal = n.create_signal({
13+
local signal = n.create_signal({
1414
value = "hello world",
1515
})
1616

@@ -20,6 +20,7 @@ n.text_input({
2020
size = 1,
2121
value = signal.value,
2222
border_label = "Description",
23+
placeholder = "Enter a description",
2324
max_lines = 5,
2425
on_change = function(value, component)
2526
signal.value = value
@@ -38,7 +39,7 @@ n.text_input({
3839

3940
### Properties
4041

41-
#### autoresize
42+
#### autoresize
4243

4344
<Property
4445
defaultValue="false"
@@ -47,20 +48,40 @@ n.text_input({
4748

4849
#### max_lines
4950

50-
<Property
51+
<Property
5152
types={['number']}
5253
/>
5354

5455
#### value
5556

56-
<Property
57+
<Property
5758
defaultValue='""'
5859
types={['string']}
5960
/>
6061

62+
#### placeholder
63+
64+
> Optional placeholder text to show when the input is empty.
65+
> Can be a string, a single virtual text chunk, or a list of virtual text chunks.
66+
67+
<Property
68+
defaultValue='nil'
69+
types={['string', '{ [1]: string, [2]: string }[]', 'nil']}
70+
/>
71+
72+
A virtual text chunk is a tuple-like table where the first element
73+
is the text and the second element is the highlight group.
74+
75+
```lua
76+
local placeholder = {
77+
{ "Hello", "Comment" },
78+
{ "World", "String" },
79+
}
80+
```
81+
6182
#### on_change
6283

63-
<Property
84+
<Property
6485
types={['fun(value: string, component: TextInput): nil']}
6586
/>
6687

lua/nui-components/prompt.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ function Prompt:_attach_change_listener()
4646
self:set_current_value(value)
4747
props.on_change(value, self)
4848

49+
self:_update_placeholder()
50+
4951
if prefix_length > 0 then
5052
vim.schedule(function()
5153
self._private.prefix:highlight(self.bufnr, self.ns_id, 1, 0)

lua/nui-components/text-input.lua

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ function TextInput:init(props, popup_options)
1111
autoresize = false,
1212
max_lines = nil,
1313
value = "",
14+
placeholder = "",
1415
on_change = fn.ignore,
1516
border_style = "rounded",
1617
}, props)
@@ -52,9 +53,39 @@ function TextInput:prop_types()
5253
autoresize = { "boolean", "nil" },
5354
wrap = { "boolean", "nil" },
5455
filetype = { "string", "nil" },
56+
placeholder = { "string", "table", "nil" },
5557
}
5658
end
5759

60+
function TextInput:_update_placeholder()
61+
local show = self:get_current_value() == ""
62+
local props = self:get_props()
63+
local placeholder = props.placeholder
64+
if show and placeholder and placeholder ~= "" then
65+
local virt_text
66+
if type(placeholder) == "table" then
67+
if type(placeholder[1]) == "table" then
68+
-- multiple virt-text chunks
69+
virt_text = placeholder
70+
else
71+
-- single virt-text chunk
72+
virt_text = { placeholder }
73+
end
74+
else
75+
-- string
76+
virt_text = { { placeholder, "Comment" } }
77+
end
78+
self._private.placeholder_extmark = vim.api.nvim_buf_set_extmark(self.bufnr, self.ns_id, 0, 0, {
79+
virt_text = virt_text,
80+
virt_text_pos = "inline",
81+
id = self._private.placeholder_extmark,
82+
})
83+
elseif self._private.placeholder_extmark then
84+
vim.api.nvim_buf_del_extmark(self.bufnr, self.ns_id, self._private.placeholder_extmark)
85+
self._private.placeholder_extmark = nil
86+
end
87+
end
88+
5889
function TextInput:_attach_change_listener()
5990
local props = self:get_props()
6091

@@ -66,6 +97,8 @@ function TextInput:_attach_change_listener()
6697
self:set_current_value(value)
6798
props.on_change(value, self)
6899

100+
self:_update_placeholder()
101+
69102
if props.autoresize then
70103
self._private.text_input_signal.size = math.max(#lines, self._private.text_input_initial_size)
71104
end
@@ -184,6 +217,7 @@ end
184217

185218
function TextInput:on_mount()
186219
self:_attach_change_listener()
220+
self:_update_placeholder()
187221
end
188222

189223
return TextInput

0 commit comments

Comments
 (0)