-
-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathneogen.txt
469 lines (394 loc) · 17.6 KB
/
neogen.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
==============================================================================
------------------------------------------------------------------------------
Table of contents:
Neogen's purpose....................................................|neogen|
The setup function..........................................|neogen.setup()|
Usage.........................................................|neogen-usage|
Configure the setup...................................|neogen-configuration|
Generate annotations.....................................|neogen.generate()|
Contributing................................................|neogen-develop|
Changes in neogen plugin..................................|neogen-changelog|
Use popular snippet engines.....................|neogen-snippet-integration|
Configurations for the template table........|neogen-template-configuration|
How to create/customize an annotation....................|neogen-annotation|
------------------------------------------------------------------------------
*neogen*
What is Neogen ?
# Abstract~
Neogen is an extensible and extremely configurable annotation generator for your favorite languages
Want to know what the supported languages are ?
Check out the up-to-date readme section: https://github.com/danymat/neogen#supported-languages
# Concept~
- Create annotations with one keybind, and jump your cursor in the inserted annotation
- Defaults for multiple languages and annotation conventions
- Extremely customizable and extensible
- Written in lua (and uses Tree-sitter)
------------------------------------------------------------------------------
*neogen.setup()*
`neogen.setup`({opts})
Module setup
Parameters ~
{opts} `(table)` Config table (see |neogen.configuration|)
Usage ~
`require('neogen').setup({})` (replace `{}` with your `config` table)
------------------------------------------------------------------------------
*neogen-usage*
Neogen Usage
Neogen will use Treesitter parsing to properly generate annotations.
The basic idea is that Neogen will generate annotation to the type you're in.
For example, if you have a csharp function like (note the cursor position):
>
public class HelloWorld
{
public static void Main(string[] args)
{
# CURSOR HERE
Console.WriteLine("Hello world!");
return true;
}
public int someMethod(string str, ref int nm, void* ptr) { return 1; }
}
<
and you call `:Neogen class`, it will generate the annotation for the upper class:
>
/// <summary>
/// ...
/// </summary>
public class HelloWorld
{
<
Currently supported types are `func`, `class`, `type`, `file`.
Check out the up-to-date readme section: https://github.com/danymat/neogen#supported-languages
To know the supported types for a certain language
NOTE: calling `:Neogen` without any type is the same as `:Neogen func`
------------------------------------------------------------------------------
*neogen-configuration*
`neogen.configuration`
# Basic configurations~
Neogen provides those defaults, and you can change them to suit your needs
>lua
neogen.configuration = {
-- Enables Neogen capabilities
enabled = true,
-- Go to annotation after insertion, and change to insert mode
input_after_comment = true,
-- Configuration for default languages
languages = {},
-- Use a snippet engine to generate annotations.
snippet_engine = nil,
-- Enables placeholders when inserting annotation
enable_placeholders = true,
-- Placeholders used during annotation expansion
placeholders_text = {
["description"] = "[TODO:description]",
["tparam"] = "[TODO:tparam]",
["parameter"] = "[TODO:parameter]",
["return"] = "[TODO:return]",
["class"] = "[TODO:class]",
["throw"] = "[TODO:throw]",
["varargs"] = "[TODO:varargs]",
["type"] = "[TODO:type]",
["attribute"] = "[TODO:attribute]",
["args"] = "[TODO:args]",
["kwargs"] = "[TODO:kwargs]",
},
-- Placeholders highlights to use. If you don't want custom highlight, pass "None"
placeholders_hl = "DiagnosticHint",
}
<
# Notes~
- to configure a language, just add your configurations in the `languages` table.
For example, for the `lua` lang:
>
languages = {
lua = { -- Configuration here }
}
<
Default configurations for a languages can be found in `lua/neogen/configurations/<your_language>.lua`
- To know which snippet engines are supported, take a look at |neogen-snippet-integration|.
Example: `snippet_engine = "luasnip"`
------------------------------------------------------------------------------
*neogen.generate()*
`neogen.generate`({opts})
The only function required to use Neogen.
It'll try to find the first parent that matches a certain type.
For example, if you are inside a function, and called `generate({ type = "func" })`,
Neogen will go until the start of the function and start annotating for you.
Parameters ~
{opts} `(optional)` `(table)` Optional configs to change default behaviour of generation.
- {opts.type} `(string, default: "any")` Which type we are trying to use for generating annotations.
Currently supported: `any`, `func`, `class`, `type`, `file`
- {opts.annotation_convention} `(table)` convention to use for generating annotations.
This is language specific. For example, `generate({ annotation_convention = { python = 'numpydoc' } })`
If no convention is specified for a specific language, it'll use the default annotation convention for the language.
- {opts.return_snippet} `boolean` if true, will return 3 values from the function call.
This option is useful if you want to get the snippet to use with a unsupported snippet engine
Below are the returned values:
- 1: (type: `string[]`) the resulting lsp snippet
- 2: (type: `number`) the `row` to insert the annotations
- 3: (type: `number`) the `col` to insert the annotations
------------------------------------------------------------------------------
*neogen-develop*
Contribute to Neogen
* Want to add a new language?
1. Using the defaults to generate a new language support:
https://github.com/danymat/neogen/blob/main/docs/adding-languages.md
2. (advanced) Only if the defaults aren't enough, please see here:
https://github.com/danymat/neogen/blob/main/docs/advanced-integration.md
* Want to contribute to an existing language?
I guess you can still read the previous links, as they have some valuable knowledge inside.
You can go and directly open/edit the configuration file relative to the language you want to contribute to.
Feel free to submit a PR, I will be happy to help you !
------------------------------------------------------------------------------
*neogen-changelog*
`neogen.version`
We use semantic versioning ! (https://semver.org)
Here is the current Neogen version:
>lua
neogen.version = "2.20.0"
<
# Changelog~
Note: We will only document `major` and `minor` versions, not `patch` ones. (only X and Y in X.Y.z)
## 2.20.0~
- Add the `snippet_engine` parameter to `neogen.generator` (#202)
## 2.19.0~
- Add support for julia (`julia`) ! (#185)
## 2.18.0~
- Add tests cases to tests/ for annotation generation with basic support for python (#174)
## 2.17.1~
- Python raises now supports `raise foo.Bar()` syntax
## 2.17.0~
- Python now supports dataclass attributes (#126)
## 2.16.0~
- Add support for `nvim` snippet engine (default nvim snippet engine) ! (see |neogen-snippet-integration|)
## 2.15.0~
- Google docstrings now include "Yields:", whenever possible
## 2.14.0~
- Google docstrings now include "Raises:", whenever possible
## 2.13.0~
- Improve google docstrings template (#124)
- Fix minor python retriever issues (#124)
## 2.12.0~
- Fetch singleton methods in ruby (#121)
## 2.11.0~
- Calling `:Neogen` will try to find the best type used to generate annotations (#116)
It'll recursively go up the syntax tree from the cursor position.
For example, if a function is defined inside class and the cursor is inside the function,
the annotation will be generated for the function.
## 2.10.0~
- Add support for Throw statements in python
Note: only active for reST template as of right now (please open an issue request for more templates)
## 2.9.0~
- Add support for `vsnip` snippet engine ! (see |neogen-snippet-integration|)
## 2.8.0~
- Specify annotation convention on `generate()` method (see |neogen.generate()|)
## 2.7.0~
- Add support for `snippy` snippet engine ! (see |neogen-snippet-integration|)
## 2.6.0~
- Add support for placeholders in snippet insertion !
None: placeholders are automatically set when using a bundled snippet engine.
- Add `enable_placeholders` option (see |neogen-configuration|)
- Add `placeholders_text` option (see |neogen-configuration|)
- Add `placeholders_hl` option (see |neogen-configuration|)
Example placeholders:
>
--- [TODO:description]
---@param param1 [TODO:parameter] [TODO:description]
function test(param1) end
<
## 2.5.0~
- Ruby: Add support for `tomdoc` (http://tomdoc.org)
## 2.4.0~
- Improve godoc template (#75)
## 2.3.0~
- Added bundled support with snippet engines !
Check out |neogen-snippet-integration| for basic setup
## 2.2.0~
### Python~
- Add support for `*args` and `**kwargs`
- Fix python return annotations being inconsistent in numpydoc template
## 2.1.0~
- Add basic support for `kotlin` (`kdoc`).
## 2.0.0~
- We made the template API private, only for initial template configuration.
If you want to make a change to a template, please see:
|neogen-template-configuration| and |neogen-annotation|
## 1.0.0~
- Neogen is officially out ! We support 16 languages as of right now,
with multiple annotation conventions.
==============================================================================
------------------------------------------------------------------------------
*neogen-snippet-integration*
`snippet`
To use a snippet engine, pass the option into neogen setup:
>
require('neogen').setup({
snippet_engine = "luasnip",
...
})
<
Some snippet engines come out of the box bundled with neogen:
- `"luasnip"` (https://github.com/L3MON4D3/LuaSnip)
- `"snippy"` (https://github.com/dcampos/nvim-snippy)
- `"vsnip"` (https://github.com/hrsh7th/vim-vsnip)
- `"nvim"` (`:h vim.snippet`)
If you want to customize the placeholders, you can use `placeholders_text` option:
>
require('neogen').setup({
placeholders_text = {
['description'] = "[description]",
}
})
<
# Add support for snippet engines~
To add support to a snippet engine, go to `lua/neogen/snippet.lua`.
There's a table called `snippet.engines` that holds functions that will be called
depending of the snippet engine
Those functions have this signature:
`snippet_engine_name = function (snip, pos)` where
- `snip` is a lsp styled snippet (in table format)
- `pos` is a { row , col } table for placing the snippet
==============================================================================
------------------------------------------------------------------------------
*neogen-template-configuration*
Each filetype has a template configuration.
A template configuration is responsible for explicitely adding templates
corresponding to annotation conventions,
as well as providing custom configurations in order to be precise about
how to customize the annotations.
Type ~
neogen.TemplateConfig
Default values:
>lua
local neogen_template = {
annotation_convention = nil,
use_default_comment = false,
}
<
------------------------------------------------------------------------------
# neogen.TemplateConfig~
Class ~
{neogen.TemplateConfig} see |template_config|
Fields ~
{annotation_convention} `(string)` select which annotation convention to use
{use_default_comment} `(boolean)` Prepend default filetype comment before a annotation
{append} `(optional)` neogen.TemplateConfig.Append custom placement of the annotation
{position} `(fun(node: userdata, type: string): number,number)` Provide an absolute position for the annotation
If values are `nil`, use default positioning
Class ~
{neogen.TemplateConfig.Append}
{child_name} `(string)` Which child node to use for appending the annotation
{fallback} `(string)` Node to fallback if `child_name` is not found
{position} "'after'"|"'before'" Place the annotation relative to position with `child_name` or `fallback`
{disabled} `(optional)` `(table)` Disable custom placement for provided types
For example, to customize the placement for a python annotation, we can use `append`, like so:
>
python = {
template = {
append = {
child_name = "comment", fallback = "block", position = "after"
}
}
}
<
Here, we instruct the generator to place the annotation "after" the "comment" (if not found: "block") node
Results in:
>
def test():
""" """
pass
<
Or:
>
def test():
# This is a comment
""" """
pass
<
------------------------------------------------------------------------------
*neogen-annotation*
In this section, you'll learn how to create your own annotation convention
First of all, you need to know an annotation template behaves, with an example:
>
local i = require("neogen.types.template").item
annotation = {
{ nil, "- $1", { type = { "class", "func" } } },
{ nil, "- $1", { no_results = true, type = { "class", "func" } } },
{ nil, "-@module $1", { no_results = true, type = { "file" } } },
{ nil, "-@author $1", { no_results = true, type = { "file" } } },
{ nil, "-@license $1", { no_results = true, type = { "file" } } },
{ nil, "", { no_results = true, type = { "file" } } },
{ i.Parameter, "-@param %s $1|any" },
{ i.Vararg, "-@vararg $1|any" },
{ i.Return, "-@return $1|any" },
{ i.ClassName, "-@class $1|any" },
{ i.Type, "-@type $1" },
}
<
- `local i = require("neogen.types.template").item`
Stores every supported node name that you can use for a language.
A node name is found with Treesitter during the configuration of a language
- `{ nil, "- $1", { type = { "class", "func" } } }`
Here is an item of a annotation convention.
It consists of 2 required fields (first and second), and an optional third field
- The first field is a `string`, or `table`: this item will be used each time there is this node name.
If it is `nil`, then it'll not required a node name.
If you need a node name, we recommend using the items from `local i`, like so:
`{ i.Type, "-@type $1" },`
If it's a `table`, it'll be used for more advanced generation:
`{ { i.Parameter, i.Type }, " %s (%s): $1", { required = "typed_parameters", type = { "func" } } },`
Means: if there are `Parameters` and `Types` inside a node called `typed_parameters`,
these two nodes will be used in the generated line
- The second item is a `string`, and is the string that'll be written in output.
It'll be formatted with some important fields:
- `%s` will use the content from the node name
- `$1` will be replaced with a cursor position (so that the user can jump to)
Example: `{ i.Parameter, "-@param %s $1|any" },` will result in:
`-@param hello ` (will a parameter named `hello`)
- The third item is a `table` (optional), and are the local options for the line.
See below (`neogen.AnnotationLine.Opts`) for more information on what is required
Now that you know every field, let's see how we could generate a basic annotation for a python function:
>
# Desired output:
def test(param1, param2, param3):
"""
Parameters
----------
param1:
param2:
param3:
"""
pass
<
Will be very simply created with an convention like so:
local i = require("neogen.types.template").item
>
annotation = {
{ i.Parameter, "%s: $1", { before_first_item = { "Parameters", "----------" } } },
}
<
We recommend you look into the the content of `neogen/templates` for a list of the default annotation conventions.
Last step, if you want to use your own annotation convention for a language:
>
require('neogen').setup {
languages = {
python = {
template = {
annotation_convention = "my_annotation",
my_annotation = annotation
}
}
}
<
------------------------------------------------------------------------------
# neogen.AnnotationLine~
Class ~
{neogen.AnnotationLine.Opts}
Fields ~
{no_results} `(boolean)` If true, will only generate the line if there are no values returned by the configuration
{type} `(string[])` If specified, will only generate the line for the required types.
If not specified, will use this line for all types.
{before_first_item} `(string[])` If specified, will append these lines before the first found item of the configuration
{after_each} `(string)` If specified, append the line after each found item of the configuration
{required} `(string)` If specified, is used in if the first field of the table is a `table` (example above)
vim:tw=78:ts=8:noet:ft=help:norl: