-
-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow different insertion points for each standard #52
Conversation
pattern['comment']['insert'] can be defined as a dictionary, so that each b:doge_doc_standard can behave differently in this regard
@mg979 Is this something you need or has this a specific reason? I don't think this is useful, since documentation is written in the same positioning for every doc standard. For example: Python will always be inside the function instead of above the function, no matter the doc standard. I don't see any logical reason to alter this for a specific doc standard. |
Python is a special case because it has a well defined doc standard, other languages don't have one. In such languages, one could have (for example) a doc standard for important functions and one for helpers, or depending on the type of script, one may want to put the docstring in different positions. It's something I was using for vimscript. Still, if you don't think it's useful, no problem. If you're unsure you can leave it for later. |
If you can give me a scenario you would use it for I will consider implementing it. |
Looking back at it, the way I did it is really ugly. The problem is that it's not easy to do it cleanly with the way buffer doc standards are implemented right now. At the same time I think this should be addressed, considering also #60. How can you implement custom doc standards, if they aren't allowed to set their insert point? I think the main problem is how b:doge_patterns is implemented, as a list and not as a dictionary of doc standards. Each doc standard should be a self-contained unity, but they're not. Example from lua doc standard: let b:doge_patterns = []
call add(b:doge_patterns, {
\ 'match': '\m^\%(local\s*\)\?function\s*\%([[:alnum:]_:.]\+[:.]\)\?\%([[:alnum:]_]\+\)\s*(\(.\{-}\))',
\ 'match_group_names': ['parameters'],
\ 'parameters': {
\ 'match': s:parameters_match_pattern,
\ 'match_group_names': ['name'],
\ 'format': {
\ 'ldoc': '@param {name} !description',
\ },
\ },
\ 'comment': {
\ 'insert': 'above',
\ 'template': {
\ 'ldoc': [
\ '-- !summary',
\ '-- !description',
\ '%(parameters|-- {parameters})%',
\ ],
\ },
\ },
\}) You define Instead I think it would be better like: " just extend the current dict, if it's already existing
let b:doge_doc_standards = get(b:, 'doge_doc_standards', {})
let b:doge_doc_standards.ldoc = [{
\ 'match': '\m^\%(local\s*\)\?function\s*\%([[:alnum:]_:.]\+[:.]\)\?\%([[:alnum:]_]\+\)\s*(\(.\{-}\))',
\ 'match_group_names': ['parameters'],
\ 'parameters': {
\ 'match': s:parameters_match_pattern,
\ 'match_group_names': ['name'],
\ 'format': '@param {name} !description',
\ },
\ 'comment': {
\ 'insert': 'above',
\ 'template': [
\ '-- !summary',
\ '-- !description',
\ '%(parameters|-- {parameters})%',
\ ],
\ },
\}] That is, each doc standard as a list with its own patterns, and everything that concerns a specific doc standard is isolated from the rest. You can't use 2 doc standards at the same time anyway. This allows doc standards to be defined in a custom ftplugin, and doge will just pick them up and use them as it finds them, when they are requested. I'm closing this PR because definitely there is more to it and I think it would need a different approach. |
@mg979 I am indeed looking for something that could solve issue #60 and I remember again why I choose this. It's A or B I had to choose. I had to duplicate doc standards (current version) or I had to duplicate patterns and their regex (your suggestion). I'd be more than happy to get your second thought on this. My suggestion is that we use dictionaries indeed and use a Current implementation call add(b:doge_patterns, {
\ 'match': '\m^def\s\+\%([^(]\+\)\s*(\(.\{-}\))\%(\s*->\s*\(.\{-}\)\)\?\s*:',
\ 'match_group_names': ['parameters', 'returnType'],
\ 'parameters': {
\ 'match': '\m\([[:alnum:]_]\+\)\%(\s*:\s*\([[:alnum:]_.]\+\%(\[[[:alnum:]_[\],[:space:]]*\]\)\?\)\)\?\%(\s*=\s*\([^,]\+\)\)\?',
\ 'match_group_names': ['name', 'type', 'default'],
\ 'format': {
\ 'reST': ':param {name} {type|!type}: !description',
\ 'numpy': [
\ '{name} : {type|!type}',
\ '\t!description',
\ ],
\ },
\ },
\ 'comment': {
\ 'insert': 'below',
\ 'template': {
\ 'reST': [
\ '"""',
\ '!description',
\ '',
\ '%(parameters|{parameters})%',
\ '%(returnType|:rtype {returnType}: !description)%',
\ '"""',
\ ],
\ 'numpy': [
\ '"""',
\ '!summary',
\ '',
\ '!description',
\ '%(parameters|)%',
\ '%(parameters|Parameters)%',
\ '%(parameters|----------)%',
\ '%(parameters|{parameters})%',
\ '%(returnType|)%',
\ '%(returnType|Returns)%',
\ '%(returnType|-------)%',
\ '%(returnType|{returnType}:)%',
\ '%(returnType|\t!description)%',
\ '"""',
\ ],
\ },
\ },
\}) Newer implementation " This is our base for the "functions" pattern.
" Every doc standard will at least extend this.
let s:func_pattern_base = {
\ 'match': '\m^def\s\+\%([^(]\+\)\s*(\(.\{-}\))\%(\s*->\s*\(.\{-}\)\)\?\s*:',
\ 'match_group_names': ['parameters', 'returnType'],
\ 'parameters': {
\ 'match': '\m\([[:alnum:]_]\+\)\%(\s*:\s*\([[:alnum:]_.]\+\%(\[[[:alnum:]_[\],[:space:]]*\]\)\?\)\)\?\%(\s*=\s*\([^,]\+\)\)\?',
\ 'match_group_names': ['name', 'type', 'default'],
\ },
\ 'comment': {
\ 'insert': 'below',
\ },
\}
" Here we only have to add the parameters and comment.
let b:doge_patterns.reST = map([
\ {
\ 'parameters': {
\ 'format': ':param {name} {type|!type}: !description'
\ },
\ 'comment': {
\ 'template': [
\ '"""',
\ '!description',
\ '',
\ '%(parameters|{parameters})%',
\ '%(returnType|:rtype {returnType}: !description)%',
\ '"""',
\ ],
\ },
\ },
\], {_, pattern -> extend(s:func_pattern_base, pattern)})
" Here we only have to add the parameters and comment.
let b:doge_patterns.numpy = map([
\ {
\ 'parameters': {
\ 'format': [
\ '{name} : {type|!type}',
\ '\t!description',
\ ],
\ },
\ 'comment': {
\ 'template': [
\ '"""',
\ '!description',
\ '',
\ '%(parameters|{parameters})%',
\ '%(returnType|:rtype {returnType}: !description)%',
\ '"""',
\ ],
\ },
\ },
\], {_, pattern -> extend(s:func_pattern_base, pattern)}) Note that I use NOTE when we implement a Another thing I would like to change (but not sure if this is the way to go) is instead of making This: let b:doge_patterns.numpy = map([
\ {
\ 'parameters': {
\ 'format': [
\ '{name} : {type|!type}',
\ '\t!description',
\ ],
\ },
\ 'comment': {
\ 'template': [
\ '"""',
\ '!description',
\ '',
\ '%(parameters|{parameters})%',
\ '%(returnType|:rtype {returnType}: !description)%',
\ '"""',
\ ],
\ },
\ },
\ {
\ " ...
\ },
\], {_, pattern -> extend(s:func_pattern_base, pattern)}) will become this: let b:doge_patterns.numpy = map({
\ 'functions': {
\ 'parameters': {
\ 'format': [
\ '{name} : {type|!type}',
\ '\t!description',
\ ],
\ },
\ 'comment': {
\ 'template': [
\ '"""',
\ '!description',
\ '',
\ '%(parameters|{parameters})%',
\ '%(returnType|:rtype {returnType}: !description)%',
\ '"""',
\ ],
\ },
\ },
\ 'class_methods': {
\ " ...
\ },
\}, {_, pattern -> extend(s:func_pattern_base, pattern)}) I think this is already a solid solution and I am looking forward to implement this. Let me know if you have any other suggestions or things that should be different from your point of view. |
In the stock doc standards (the ones you provide) you can organize the code as you wish. Personally I'd prefer a more linear implementation (without nested dictionaries, that can be easily extended), but that would require other changes. Anyway I don't mind some code repetition, in the end, each ftplugin does its own thing, even if there's some repeated code it's hard to get lost. But the main thing is: that structure will have to be used by custom doc standards as well, so in my opinion it's better to keep things easy. Personally I don't see the need for nested dictionaries. Then, A non-nested template would be like: let s:template = {
\ 'match': ...,
\ 'match_group_names': ...,
\ 'parameters': ...,
\ 'parameters_group_names': ...,
\ 'parameters_format': ...,
\ 'insert': ...,
\ 'template': ...,
\} where the For example, a non-nested implementation based on your python snippet: " This is our base for the "functions" pattern.
" Every doc standard will at least extend this.
let s:func_template = {
\ 'match': '\m^def\s\+\%([^(]\+\)\s*(\(.\{-}\))\%(\s*->\s*\(.\{-}\)\)\?\s*:',
\ 'match_group_names': ['parameters', 'returnType'],
\ 'parameters': '\m\([[:alnum:]_]\+\)\%(\s*:\s*\([[:alnum:]_.]\+\%(\[[[:alnum:]_[\],[:space:]]*\]\)\?\)\)\?\%(\s*=\s*\([^,]\+\)\)\?',
\ 'parameters_group_names': ['name', 'type', 'default'],
\ 'insert': 'below',
\}
" Here we only have to add the parameters and comment.
let b:doge_doc_standards.reST = [
\ extend({
\ 'parameters_format': ':param {name} {type|!type}: !description'
\ 'template': [
\ '"""',
\ '!description',
\ '',
\ '%(parameters|{parameters})%',
\ '%(returnType|:rtype {returnType}: !description)%',
\ '"""',
\ ],
\ }, s:func_template),
\]
" Here we only have to add the parameters and comment.
let b:doge_doc_standards.numpy = [
\ extend({
\ 'parameters_format': [
\ '{name} : {type|!type}',
\ '\t!description',
\ ],
\ 'template': [
\ '"""',
\ '!description',
\ '',
\ '%(parameters|{parameters})%',
\ '%(returnType|:rtype {returnType}: !description)%',
\ '"""',
\ ],
\ }, s:func_template),
\] |
About the thought of making a doc standard a dict: I'm not sure it's a good idea, because:
|
I agree with both suggestions. I also prefer linear pattern structures (which also prevents us from creating the I'll start implementing it. Thanks for your feedback. |
Maybe I was too harsh about nested dicts, also structures with short names like this would be fine let s:template = {
\ 'primary': { 'match': ..., 'groups': ...},
\ 'parameters': { 'match': ..., 'groups': ..., 'format': ...},
\ 'insert': ...,
\ 'template': ...,
\} But there's no need for that 'comment' nested dict. In scripts repeated patterns can also be stored in script variables if you want to avoid repetitions but also |
No worries. It can be nested and I will adjust the structure partially, yes, since some properties do not need to be nested. The only ones I will keep nested will be Something else I thought about today is that: I don't want people to copy-paste patterns, then I have to do a bug fix later and then they're stuck with the old regex. I don't want people to manage the regex patterns. I will document this part as well, but my goal is that every |
First: one can use the I would do it like this, to ensure that all doc standards (stock and custom) Assuming you have a single buffer variable In each ftplugin, yours or custom: " pick up what has been defined already
let b:doge_doc_standards = get(b:, 'doge_doc_standards', {})
" only set the active doc standard if not done yet
let b:doge_doc_standard = get(b:, 'doge_doc_standard', default)
" define the doc standards in a temporary script variable
let s:doc_standards = {
\'reST' : ...,
\'numpy': ...
\}
" loop defined doc standards and populate the buffer variable, only if they
" have not been previously defined
for doc in keys(s:doc_standards)
if !has_key(b:doge_doc_standards, doc)
let b:doge_doc_standards[doc] = s:doc_standards[doc]
endif
endfor If there is only one doc standard to define it's easier because you can just In this way you ensure that your ftplugins don't overwrite a custom ftplugin. Then, you get the doc standards when running |
Ah, forgot about the
Agree. I'll take this into consideration when rewriting, thanks! |
@mg979 What about this part? Because my suggestion is for the user that they can extend patterns via the " ==============================================================================
"
" Define our base for every pattern.
"
" ==============================================================================
let b:pattern_base = {
\ 'parameters': {
\ 'match': '\m\([^,]\+\)',
\ 'match_group_names': ['name'],
\ 'format': '@param {name} !description',
\ },
\ 'insert': 'above',
\}
" ==============================================================================
"
" Define the pattern types.
"
" ==============================================================================
" ------------------------------------------------------------------------------
" Matches regular function expressions and class methods.
" ------------------------------------------------------------------------------
" function new_function(p1, p2, p3, p4)
" local function new_function(p1, p2, p3)
" function BotDetectionHandler:access(p1, p2, p3)
" function a.b:c (p1, p2) body end
" a.b.c = function (self, p1, p2) body end
" ------------------------------------------------------------------------------
let b:function_and_class_method_pattern = doge#helpers#deepextend(b:pattern_base, {
\ 'match': '\m^\%(local\s*\)\?function\s*\%([[:alnum:]_:.]\+[:.]\)\?\%([[:alnum:]_]\+\)\s*(\(.\{-}\))',
\ 'match_group_names': ['parameters'],
\})
" ------------------------------------------------------------------------------
" Matches regular function expressions as a variable value.
" ------------------------------------------------------------------------------
" myprint = function(p1, p2)
" local myprint = function(p1, p2, p3, p4, p5)
" ------------------------------------------------------------------------------
let b:variable_function_pattern = doge#helpers#deepextend(b:pattern_base, {
\ 'match': '\m^\%(local\s*\)\?\%([[:alnum:]_:.]\+[:.]\)\?\([[:alnum:]_]\+\)\s*=\s*\%(\s*function\s*\)\?(\(.\{-}\))',
\ 'match_group_names': ['funcName', 'parameters'],
\})
" ==============================================================================
"
" Define the doc standards.
"
"==============================================================================
let b:doge_patterns.ldoc = [
\ doge#helpers#deepextend(b:function_and_class_method_pattern, {
\ 'template': [
\ '-- !summary',
\ '-- !description',
\ '%(parameters|-- {parameters})%',
\ ],
\ }),
\ doge#helpers#deepextend(b:variable_function_pattern, {
\ 'template': [
\ '-- !summary',
\ '-- !description',
\ '%(parameters|-- {parameters})%',
\ ],
\ }),
\] The structure is as follows:
This is a setup that works for multiple doc standards and multiple pattern types (for example: C++ has If the user want to create a custom doc standard they can do the following: " ~/.vim/after/ftplugin/lua.vim
let b:doge_supported_doc_standards = ['test']
let b:doge_doc_standard = 'test'
let b:doge_patterns = doge#buffer#get_patterns()
let b:doge_patterns.ldoc = [
\ doge#helpers#deepextend(b:function_and_class_method_pattern, {
\ 'template': [
\ '-- I want every function to have this summary', " <-- added this
\ '-- !summary',
\ '-- !description',
\ '%(parameters|-- {parameters})%',
\ ],
\ }),
\ doge#helpers#deepextend(b:variable_function_pattern, {
\ 'template': [
\ '-- I want every function to have this summary', " <-- added this
\ '-- !summary',
\ '-- !description',
\ '%(parameters|-- {parameters})%',
\ ],
\ }),
\] The thing I also doubt about is whether to add I think this is a good rewrite that solves #60 and also removes redundant code. Any feedback? |
Just one thing here: it's a very bad idea to use multiple buffer variables, especially with those generic names. Totally unneeded, in the case that somebody wants to change only a regex pattern, without writing a whole doc standard, he doesn't even need to open the source, he just needs to do
and paste and change it in his own
Just use script variables for templates, don't expect somebody may want to use them. Note that custom docstandard in ftplugins already work up to a certain measure (I have my vimscript patterns modeled on the script lua), the main thing here is to make the process safe. The only needed buffer variable is Also, why don't you use a shorter name like |
This won't work, because
This is working now. The plugin will persist existing
This was the name I came up with when I created it. The The idea of doge is: match a pattern -> extract the data -> create tokens from the data -> use the tokens in a template. |
pattern['comment']['insert'] can be defined as a dictionary, so that
each b:doge_doc_standard can behave differently in this regard
Prelude
Thank you for helping out DoGe!
By contributing to DoGe you agree to the following statements (Replace
[ ]
with[x]
with those you agree with):Why this PR?
If different doc standards are supported, they could insert the documentation in different positions.