diff --git a/docs/pages/docs/components/prompt.mdx b/docs/pages/docs/components/prompt.mdx index 6fd4247..0da9f36 100644 --- a/docs/pages/docs/components/prompt.mdx +++ b/docs/pages/docs/components/prompt.mdx @@ -11,6 +11,7 @@ import { Property } from '../../../components/Property' ```lua n.prompt({ prefix = " > ", + placeholder = "Enter a command", border_label = { text = "Command", align = "center", @@ -25,31 +26,51 @@ n.prompt({ #### value - #### prefix - +#### placeholder + +> Optional placeholder text to show when the input is empty. +> Can be a string, a single virtual text chunk, or a list of virtual text chunks. + + + +A virtual text chunk is a tuple-like table where the first element +is the text and the second element is the highlight group. + +```lua +local placeholder = { + { "Hello", "Comment" }, + { "World", "String" }, +} +``` + #### on_change - #### on_submit - #### submit_key - diff --git a/docs/pages/docs/components/text-input.mdx b/docs/pages/docs/components/text-input.mdx index 0a6c0c0..cc8111d 100644 --- a/docs/pages/docs/components/text-input.mdx +++ b/docs/pages/docs/components/text-input.mdx @@ -3,14 +3,14 @@ import { Property } from '../../../components/Property' ## TextInput -`TextInput` is a component that allows you to enter any text. +`TextInput` is a component that allows you to enter any text. ![](/gifs/text-input-1.gif) ### Usage Example ```lua -local signal = n.create_signal({ +local signal = n.create_signal({ value = "hello world", }) @@ -20,6 +20,7 @@ n.text_input({ size = 1, value = signal.value, border_label = "Description", + placeholder = "Enter a description", max_lines = 5, on_change = function(value, component) signal.value = value @@ -38,7 +39,7 @@ n.text_input({ ### Properties -#### autoresize +#### autoresize #### value - +#### placeholder + +> Optional placeholder text to show when the input is empty. +> Can be a string, a single virtual text chunk, or a list of virtual text chunks. + + + +A virtual text chunk is a tuple-like table where the first element +is the text and the second element is the highlight group. + +```lua +local placeholder = { + { "Hello", "Comment" }, + { "World", "String" }, +} +``` + #### on_change - diff --git a/lua/nui-components/prompt.lua b/lua/nui-components/prompt.lua index 9497ada..3e5de83 100644 --- a/lua/nui-components/prompt.lua +++ b/lua/nui-components/prompt.lua @@ -46,6 +46,8 @@ function Prompt:_attach_change_listener() self:set_current_value(value) props.on_change(value, self) + self:_update_placeholder() + if prefix_length > 0 then vim.schedule(function() self._private.prefix:highlight(self.bufnr, self.ns_id, 1, 0) diff --git a/lua/nui-components/text-input.lua b/lua/nui-components/text-input.lua index a428e83..434ebe7 100644 --- a/lua/nui-components/text-input.lua +++ b/lua/nui-components/text-input.lua @@ -11,6 +11,7 @@ function TextInput:init(props, popup_options) autoresize = false, max_lines = nil, value = "", + placeholder = "", on_change = fn.ignore, border_style = "rounded", }, props) @@ -52,9 +53,39 @@ function TextInput:prop_types() autoresize = { "boolean", "nil" }, wrap = { "boolean", "nil" }, filetype = { "string", "nil" }, + placeholder = { "string", "table", "nil" }, } end +function TextInput:_update_placeholder() + local show = self:get_current_value() == "" + local props = self:get_props() + local placeholder = props.placeholder + if show and placeholder and placeholder ~= "" then + local virt_text + if type(placeholder) == "table" then + if type(placeholder[1]) == "table" then + -- multiple virt-text chunks + virt_text = placeholder + else + -- single virt-text chunk + virt_text = { placeholder } + end + else + -- string + virt_text = { { placeholder, "Comment" } } + end + self._private.placeholder_extmark = vim.api.nvim_buf_set_extmark(self.bufnr, self.ns_id, 0, 0, { + virt_text = virt_text, + virt_text_pos = "inline", + id = self._private.placeholder_extmark, + }) + elseif self._private.placeholder_extmark then + vim.api.nvim_buf_del_extmark(self.bufnr, self.ns_id, self._private.placeholder_extmark) + self._private.placeholder_extmark = nil + end +end + function TextInput:_attach_change_listener() local props = self:get_props() @@ -66,6 +97,8 @@ function TextInput:_attach_change_listener() self:set_current_value(value) props.on_change(value, self) + self:_update_placeholder() + if props.autoresize then self._private.text_input_signal.size = math.max(#lines, self._private.text_input_initial_size) end @@ -184,6 +217,7 @@ end function TextInput:on_mount() self:_attach_change_listener() + self:_update_placeholder() end return TextInput