Skip to content

Commit 13ad42c

Browse files
author
Agustin Jimenez
committed
feat: add Haddock documentation snippets with smart detection
Add two new snippets for generating Haddock documentation: fdoc - Function documentation snippet: - Auto-detects function name and type signature from line below cursor - Parses parameter types to generate example placeholders - Supports multiline type signatures (including name on separate line) - Strips forall quantifiers (including nested) - Strips type class constraints (single and tuple) - Falls back to static placeholders when no signature detected mdoc - Module documentation snippet: - Auto-detects module name via LSP codelens or filename fallback - Generates standard Haddock module header template New utility functions in util.lua: - strip_forall: Remove forall quantifiers from signatures - strip_constraints: Remove type class constraints - normalize_signature: Apply both transformations - parse_type_signature: Parse signatures into params and return type - parse_function_line: Parse function type declaration lines - is_signature_continuation: Detect multiline signature continuations - collect_multiline_signature: Join multiline signatures (supports both "name :: sig" and "name\n :: sig" formats) - get_function_context: Get function info from line below cursor Also fixes a bug where _indent_newline crashed with "bad argument #2 to 'rep'" when parent buffer position was unavailable. Includes 53 unit tests covering all new functionality.
1 parent cbe4e20 commit 13ad42c

File tree

5 files changed

+778
-9
lines changed

5 files changed

+778
-9
lines changed

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,32 @@ All notable changes to this project will be documented in this file.
66
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
77
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
88

9+
## [Unreleased]
10+
11+
### Added
12+
13+
- `fdoc` snippet: Haddock function documentation with smart signature detection.
14+
Automatically detects function name and type signature from the line below cursor,
15+
generating example placeholders with parameter types.
16+
- `mdoc` snippet: Haddock module documentation with smart module name detection.
17+
Uses LSP codelens or filename as fallback.
18+
- `util.parse_type_signature`: Parse Haskell type signatures into parameter types
19+
and return type, handling parentheses, brackets, and braces.
20+
- `util.parse_function_line`: Parse function type declaration lines.
21+
- `util.get_function_context`: Get function context from the line below cursor.
22+
- `util.strip_forall`: Strip forall quantifiers from type signatures.
23+
- `util.strip_constraints`: Strip type class constraints from type signatures.
24+
- `util.is_signature_continuation`: Detect multiline signature continuation lines.
25+
- `util.collect_multiline_signature`: Collect multiline type signatures.
26+
- Multiline type signature support for `fdoc` snippet.
27+
- Comprehensive tests for signature parsing, forall/constraint handling,
28+
multiline signatures, and function context detection (49 tests).
29+
30+
### Fixed
31+
32+
- Handle nil parent position in `_indent_newline` that caused
33+
"bad argument #2 to 'rep'" errors in snippets using dynamic indentation.
34+
935
## [1.5.0] - 2025-10-06
1036

1137
### Added

lua/haskell-snippets/functions.lua

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,48 @@ functions.lambda = s({
113113
})
114114
table.insert(functions.all, functions.lambda)
115115

116+
local function get_fdoc_nodes()
117+
local context = util.get_function_context()
118+
119+
if context then
120+
local nodes = {
121+
text('-- | `' .. context.name .. '` '),
122+
insert(1, 'description.'),
123+
text { '', '--', '-- Examples:', '--', '-- >>> ' .. context.name },
124+
}
125+
126+
-- Add each parameter as an insert node
127+
local idx = 2
128+
for _, param in ipairs(context.params) do
129+
table.insert(nodes, text(' '))
130+
table.insert(nodes, insert(idx, param))
131+
idx = idx + 1
132+
end
133+
134+
table.insert(nodes, text { '', '-- ' })
135+
table.insert(nodes, insert(idx, context.return_type))
136+
137+
return sn(nil, nodes)
138+
end
139+
140+
-- Fallback to placeholders
141+
return sn(nil, {
142+
text('-- | '),
143+
insert(1, 'Brief description.'),
144+
text { '', '--', '-- Examples:', '--', '-- >>> ' },
145+
insert(2, 'example'),
146+
text { '', '-- ' },
147+
insert(3, 'expected'),
148+
})
149+
end
150+
151+
---@type Snippet Haddock function documentation
152+
functions.fdoc = s({
153+
trig = 'fdoc',
154+
dscr = 'Haddock function documentation',
155+
}, {
156+
dynamic(1, get_fdoc_nodes),
157+
})
158+
table.insert(functions.all, functions.fdoc)
159+
116160
return functions

lua/haskell-snippets/module.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,27 @@ if has_haskell_parser then
174174
})
175175
table.insert(module.all, module.qualc)
176176
end
177+
178+
local function get_mdoc_module_name_node()
179+
local module_name = util.lsp_get_module_name() or get_buf_module_name()
180+
if module_name then
181+
return sn(nil, { text(module_name) })
182+
end
183+
return sn(nil, { insert(1, 'MyModule') })
184+
end
185+
186+
---@type Snippet Haddock module documentation
187+
module.mdoc = s({
188+
trig = 'mdoc',
189+
dscr = 'Haddock module documentation',
190+
}, {
191+
text { '-- |', '-- Module : ' },
192+
dynamic(1, get_mdoc_module_name_node),
193+
text { '', '-- Description : ' },
194+
insert(2, 'Short description here'),
195+
text { '', '--', '-- ' },
196+
insert(3, 'Longer description of the module.'),
197+
})
198+
table.insert(module.all, module.mdoc)
199+
177200
return module

0 commit comments

Comments
 (0)