-
Notifications
You must be signed in to change notification settings - Fork 0
/
DoxygenToolkit
executable file
·1181 lines (1078 loc) · 43.8 KB
/
DoxygenToolkit
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
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
" DoxygenToolkit.vim
" Brief: Usefull tools for Doxygen (comment, author, license).
" Version: 0.2.13
" Date: 2010/10/16
" Author: Mathias Lorente
"
" TODO: add automatically (option controlled) in/in out flags to function
" parameters
" TODO: (Python) Check default paramareters defined as list/dictionnary/tuple
"
" Note: Correct insertion position and 'xxx_post' parameters.
" - Insert position is correct when g:DoxygenToolkit_compactOneLineDoc = "yes"
" and let g:DoxygenToolkit_commentType = "C++" are set.
" - When you define:
" g:DoxygenToolkit_briefTag_pre = "@brief "
" g:DoxygenToolkit_briefTag_post = "<++>"
" g:DoxygenToolkit_briefTag_funcName = "yes"
" Documentation generated with these parameters is something like:
" /// @brief foo <++>
" You can configure similarly parameters to get something like:
" /// @brief foo <++>
" /// @param bar <++>
" /// @param baz <++>
"
" Note: Position the cursor at the right position for one line documentation.
"
" Note: Remove trailing blank characters where they are not needed.
"
" Note: 'extern' keyword added in list of values to ignore for return type.
"
" Note: Correct bugs related to templates and add support for throw statement
" (many thanks to Dennis Lubert):
" - Template parameter of different type from class and typename are
" recognized.
" - Indentation mistake while detecting template.
" - New option are available: g:DoxygenToolkit_throwTag_pre and
" g:DoxygenToolkit_throwTag_post
"
" Note: Add support for documentation of template parameters.
" Thanks to Dennis (plasmahh) and its suggestions.
" - New option are available: g:DoxygenToolkit_templateParamTag_pre
" and g:DoxygenToolkit_templateParamTag_post
"
" Note: Solve almost all compatibility problem with c/c++ IDE
"
" Note: Bug correction and improve compatibility with c/c++ IDE
" - Documentation of function with struct parameters are now allowed.
" - Comments are written in two steps to avoid conflicts with c/c++ IDE.
"
" Note: Bug correction (thanks to Jhon Do)
" - DoxygenToolkit_briefTag_funcName and other xxx_xxName parameters
" should work properly now.
"
" Note: Bug correction (thanks to Anders Bo Rasmussen)
" - C++: now functions like void foo(type &bar); are correctly documented.
" The parameter's name is bar (and no more &bar).
"
" Note: Added @version tag into the DocBlock generated by DoxygenAuthorFunc()
" (thanks to Dave Walter).
" The version string can be defines into your .vimrc file with
" g:DoxygenToolkit_versionString or it will be asked the first time the
" function is called (same behavior as @author tag). Example:
" /// \file foo.cpp
" /// \brief
" /// \author Dave Walter
" /// \version 1.0
" /// \date 2009-03-26
"
" Note: Comments are now allowed in function declaration. Example:
" - C/C++: void func( int foo, // first param
" int bar /* second param */ );
"
" - Python: def func( foo, # first param
" bar ) # second param
"
" Note: Bug correction (many thanks to Alexey Radkov)
" - C/C++: following function/method are now correctly documented:
" - operator(),
" - constructor with initialization parameter(s),
" - pure virtual method,
" - const method.
" - Python:
" - Single line function are now correctly documented.
"
" Note: The main function has been rewritten (I hope it is cleaner).
" - There is now support for function pointer as parameter (C/C++).
" - You can configure the script to get one line documentation (for
" attribute instance for example, you need to set
" g:DoxygenToolkit_compactOneLineDoc to "yes").
"
" - NEW: Support Python scripts:
" - Function/method are not scanned, so by default they are considered
" as if they always return something (modify this behavior by defining
" g:DoxygenToolkit_python_autoFunctionReturn to "no")
" - self parameter is automatically ignored when scanning function
" parameters (you can change this behavior by defining
" g:DoxygenToolkit_python_autoRemoveSelfParam to "no")
"
" Note: Number of lines scanned is now configurable. Default value is still 10
" lines. (Thanks to Spencer Collyer for this improvement).
"
" Note: Bug correction : function that returns null pointer are correctly
" documented (Thanks to Ronald WAHL for his report and patch).
"
" Note: Remove header and footer from doxygen documentation
" - Generated documentation with block header/footer activated (see
" parameters g:DoxygenToolkit_blockHeader and
" g:DoxygenToolkit_blockFooter) do not integrate header and footer
" anymore.
" Thanks to Justin RANDALL for this.
" Now comments are as following:
" /* --- My Header --- */ // --- My Header ---
" /** /// @brief ...
" * @brief ... or // --- My Footer ---
" */
" /* -- My Footer --- */
"
" Note: Changes to customize cinoptions
" - New option available for cinoptions : g:DoxygenToolkit_cinoptions
" (default value is still c1C1)
" Thanks to Arnaud GODET for this. Now comment can have the following
" look:
" /** /**
" * and not only *
" */ */
" Note: Changes for linux kernel comment style
" - New option are available for brief tag and parameter tag ! Now there is
" a pre and a post tag for each of these tag.
" - You can define 'let g:DoxygenToolkit_briefTag_funcName = "yes"' to add
" the name of commented function between pre-brief tag and post-brief tag.
" - With these new features you can get something like:
" /**
" * @brief MyFunction -
" *
" * @param foo:
" * @param bar:
" */
" Note: Changes suggested by Soh Kok Hong:
" - Fixed indentation in comments
" ( no more /** /**
" * but *
" */ */ )
" Note: Changes made by Jason Mills:
" - Fixed \n bug which resulted in comments being screwed up
" - Added use of doxygen /// comments.
" Note: Changes made by Mathias Lorente on 05/25/04
" - Fixed filename bug when including doxygen author comment whereas file
" has not been open directly on commamd line.
" - Now /// or /** doxygen comments are correctly integrated (except for
" license).
" Note: Changes made by Mathias Lorente on 08/02/04
" - Now include only filename in author comment (no more folder...)
" - Fixed errors with function with no indentation.
"
"
" Currently five purposes have been defined :
"
" Generates a doxygen license comment. The tag text is configurable.
"
" Generates a doxygen author skeleton. The tag text is configurable.
"
" Generates a doxygen comment skeleton for a C, C++ or Python function or class,
" including @brief, @param (for each named argument), and @return. The tag
" text as well as a comment block header and footer are configurable.
" (Consequently, you can have \brief, etc. if you wish, with little effort.)
"
" Ignore code fragment placed in a block defined by #ifdef ... #endif (C/C++). The
" block name must be given to the function. All of the corresponding blocks
" in all the file will be treated and placed in a new block DOX_SKIP_BLOCK (or
" any other name that you have configured). Then you have to update
" PREDEFINED value in your doxygen configuration file with correct block name.
" You also have to set ENABLE_PREPROCESSING to YES.
"
" Generate a doxygen group (begining and ending). The tag text is
" configurable.
"
" Use:
" - Type of comments (C/C++: /// or /** ... */, Python: ## and # ) :
" In vim, default C++ comments are : /** ... */. But if you prefer to use ///
" Doxygen comments just add 'let g:DoxygenToolkit_commentType = "C++"'
" (without quotes) in your .vimrc file
"
" - License :
" In vim, place the cursor on the line that will follow doxygen license
" comment. Then, execute the command :DoxLic. This will generate license
" comment and leave the cursor on the line just after.
"
" - Author :
" In vim, place the cursor on the line that will follow doxygen author
" comment. Then, execute the command :DoxAuthor. This will generate the
" skeleton and leave the cursor just after @author tag if no variable
" define it, or just after the skeleton.
"
" - Function / class comment :
" In vim, place the cursor on the line of the function header (or returned
" value of the function) or the class. Then execute the command :Dox. This
" will generate the skeleton and leave the cursor after the @brief tag.
"
" - Ignore code fragment :
" In vim, if you want to ignore all code fragment placed in a block such as :
" #ifdef DEBUG
" ...
" #endif
" You only have to execute the command :DoxUndoc(DEBUG) !
"
" - Group :
" In vim, execute the command :DoxBlock to insert a doxygen block on the
" following line.
"
" Limitations:
" - Assumes that the function name (and the following opening parenthesis) is
" at least on the third line after current cursor position.
" - Not able to update a comment block after it's been written.
" - Blocks delimiters (header and footer) are only included for function
" comment.
" - Assumes that cindent is used.
" - Comments in function parameters (such as void foo(int bar /* ... */, baz))
" are not yet supported.
"
"
" Example:
" Given:
" int
" foo(char mychar,
" int myint,
" double* myarray,
" int mask = DEFAULT)
" { //...
" }
"
" Issuing the :Dox command with the cursor on the function declaration would
" generate
"
" /**
" * @brief
" *
" * @param mychar
" * @param myint
" * @param myarray
" * @param mask
" *
" * @return
" */
"
"
" To customize the output of the script, see the g:DoxygenToolkit_*
" variables in the script's source. These variables can be set in your
" .vimrc.
"
" For example, my .vimrc contains:
" let g:DoxygenToolkit_briefTag_pre="@Synopsis "
" let g:DoxygenToolkit_paramTag_pre="@Param "
" let g:DoxygenToolkit_returnTag="@Returns "
" let g:DoxygenToolkit_blockHeader="--------------------------------------------------------------------------"
" let g:DoxygenToolkit_blockFooter="----------------------------------------------------------------------------"
" let g:DoxygenToolkit_authorName="Mathias Lorente"
" let g:DoxygenToolkit_licenseTag="My own license" <-- Does not end with
" "\<enter>"
" Verify if already loaded
"if exists("loaded_DoxygenToolkit")
" echo 'DoxygenToolkit Already Loaded.'
" finish
"endif
let loaded_DoxygenToolkit = 1
"echo 'Loading DoxygenToolkit...'
let s:licenseTag = "Copyright (C) \<enter>\<enter>"
let s:licenseTag = s:licenseTag . "This program is free software; you can redistribute it and/or\<enter>"
let s:licenseTag = s:licenseTag . "modify it under the terms of the GNU General Public License\<enter>"
let s:licenseTag = s:licenseTag . "as published by the Free Software Foundation; either version 2\<enter>"
let s:licenseTag = s:licenseTag . "of the License, or (at your option) any later version.\<enter>\<enter>"
let s:licenseTag = s:licenseTag . "This program is distributed in the hope that it will be useful,\<enter>"
let s:licenseTag = s:licenseTag . "but WITHOUT ANY WARRANTY; without even the implied warranty of\<enter>"
let s:licenseTag = s:licenseTag . "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\<enter>"
let s:licenseTag = s:licenseTag . "GNU General Public License for more details.\<enter>\<enter>"
let s:licenseTag = s:licenseTag . "You should have received a copy of the GNU General Public License\<enter>"
let s:licenseTag = s:licenseTag . "along with this program; if not, write to the Free Software\<enter>"
let s:licenseTag = s:licenseTag . "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\<enter>"
" Common standard constants
if !exists("g:DoxygenToolkit_briefTag_pre")
let g:DoxygenToolkit_briefTag_pre = "@brief "
endif
if !exists("g:DoxygenToolkit_briefTag_post")
let g:DoxygenToolkit_briefTag_post = ""
endif
if !exists("g:DoxygenToolkit_templateParamTag_pre")
let g:DoxygenToolkit_templateParamTag_pre = "@tparam "
endif
if !exists("g:DoxygenToolkit_templateParamTag_post")
let g:DoxygenToolkit_templateParamTag_post = ""
endif
if !exists("g:DoxygenToolkit_paramTag_pre")
let g:DoxygenToolkit_paramTag_pre = "@param "
endif
if !exists("g:DoxygenToolkit_paramTag_post")
let g:DoxygenToolkit_paramTag_post = ""
endif
if !exists("g:DoxygenToolkit_returnTag")
let g:DoxygenToolkit_returnTag = "@return "
endif
if !exists("g:DoxygenToolkit_throwTag_pre")
let g:DoxygenToolkit_throwTag_pre = "@throw " " @exception is also valid
endif
if !exists("g:DoxygenToolkit_throwTag_post")
let g:DoxygenToolkit_throwTag_post = ""
endif
if !exists("g:DoxygenToolkit_blockHeader")
let g:DoxygenToolkit_blockHeader = ""
endif
if !exists("g:DoxygenToolkit_blockFooter")
let g:DoxygenToolkit_blockFooter = ""
endif
if !exists("g:DoxygenToolkit_licenseTag")
let g:DoxygenToolkit_licenseTag = s:licenseTag
endif
if !exists("g:DoxygenToolkit_fileTag")
let g:DoxygenToolkit_fileTag = "@File "
endif
if !exists("g:DoxygenToolkit_authorTag")
let g:DoxygenToolkit_authorTag = "@Author "
endif
if !exists("g:DoxygenToolkit_dateTag")
let g:DoxygenToolkit_dateTag = "@Date "
endif
if !exists("g:DoxygenToolkit_versionTag")
let g:DoxygenToolkit_versionTag = "@Version "
endif
if !exists("g:DoxygenToolkit_undocTag")
let g:DoxygenToolkit_undocTag = "DOX_SKIP_BLOCK"
endif
if !exists("g:DoxygenToolkit_blockTag")
let g:DoxygenToolkit_blockTag = "@name "
endif
if !exists("g:DoxygenToolkit_classTag")
let g:DoxygenToolkit_classTag = "@class "
endif
if !exists("g:DoxygenToolkit_cinoptions")
let g:DoxygenToolkit_cinoptions = "c1C1"
endif
if !exists("g:DoxygenToolkit_startCommentTag ")
let g:DoxygenToolkit_startCommentTag = "/* "
let g:DoxygenToolkit_startCommentBlock = "/*"
endif
if !exists("g:DoxygenToolkit_interCommentTag ")
let g:DoxygenToolkit_interCommentTag = "* "
endif
if !exists("g:DoxygenToolkit_interCommentBlock ")
let g:DoxygenToolkit_interCommentBlock = "* "
endif
if !exists("g:DoxygenToolkit_endCommentTag ")
let g:DoxygenToolkit_endCommentTag = "*/"
let g:DoxygenToolkit_endCommentBlock = "*/"
endif
if exists("g:DoxygenToolkit_commentType")
if ( g:DoxygenToolkit_commentType == "C++" )
let g:DoxygenToolkit_startCommentTag = "/// "
let g:DoxygenToolkit_interCommentTag = "/// "
let g:DoxygenToolkit_endCommentTag = ""
let g:DoxygenToolkit_startCommentBlock = "// "
let g:DoxygenToolkit_interCommentBlock = "// "
let g:DoxygenToolkit_endCommentBlock = ""
else
let g:DoxygenToolkit_commentType = "C"
endif
else
let g:DoxygenToolkit_commentType = "C"
endif
" Compact documentation
" /**
" * \brief foo ---> /** \brief foo */
" */
if !exists("g:DoxygenToolkit_compactOneLineDoc")
let g:DoxygenToolkit_compactOneLineDoc = "no"
endif
" /**
" * \brief foo /**
" * * \brief foo
" * \param bar ---> * \param bar
" * * \return
" * \return */
" */
if !exists("g:DoxygenToolkit_compactDoc")
let g:DoxygenToolkit_compactDoc = "no"
endif
" Necessary '\<' and '\>' will be added to each item of the list.
let s:ignoreForReturn = ['template', 'explicit', 'inline', 'static', 'virtual', 'void\([[:blank:]]*\*\)\@!', 'const', 'volatile', 'struct', 'extern']
if !exists("g:DoxygenToolkit_ignoreForReturn")
let g:DoxygenToolkit_ignoreForReturn = s:ignoreForReturn[:]
else
let g:DoxygenToolkit_ignoreForReturn += s:ignoreForReturn
endif
unlet s:ignoreForReturn
" Maximum number of lines to check for function parameters
if !exists("g:DoxygenToolkit_maxFunctionProtoLines")
let g:DoxygenToolkit_maxFunctionProtoLines = 10
endif
" Add name of function/class/struct... after pre brief tag if you want
if !exists("g:DoxygenToolkit_briefTag_className")
let g:DoxygenToolkit_briefTag_className = "no"
endif
if !exists("g:DoxygenToolkit_briefTag_structName")
let g:DoxygenToolkit_briefTag_structName = "no"
endif
if !exists("g:DoxygenToolkit_briefTag_enumName")
let g:DoxygenToolkit_briefTag_enumName = "no"
endif
if !exists("g:DoxygenToolkit_briefTag_namespaceName")
let g:DoxygenToolkit_briefTag_namespaceName = "no"
endif
if !exists("g:DoxygenToolkit_briefTag_funcName")
let g:DoxygenToolkit_briefTag_funcName = "no"
endif
" Keep empty line (if any) between comment and function/class/...
if !exists("g:DoxygenToolkit_keepEmptyLineAfterComment")
let g:DoxygenToolkit_keepEmptyLineAfterComment = "no"
endif
" PYTHON specific
"""""""""""""""""
" Remove automatically self parameter from function to avoid its documantation
if !exists("g:DoxygenToolkit_python_autoRemoveSelfParam")
let g:DoxygenToolkit_python_autoRemoveSelfParam = "yes"
endif
" Consider functions as if they always return something (default: yes)
if !exists("g:DoxygenToolkit_python_autoFunctionReturn")
let g:DoxygenToolkit_python_autoFunctionReturn = "yes"
endif
""""""""""""""""""""""""""
" Doxygen license comment
""""""""""""""""""""""""""
function! <SID>DoxygenLicenseFunc()
call s:InitializeParameters()
" Test authorName variable
if !exists("g:DoxygenToolkit_authorName")
let g:DoxygenToolkit_authorName = input("Enter name of the author (generally yours...) : ")
endif
mark d
let l:date = strftime("%Y")
exec "normal O".strpart( s:startCommentBlock, 0, 1 )
exec "normal A".strpart( s:startCommentBlock, 1 ).substitute( g:DoxygenToolkit_licenseTag, "\<enter>", "\<enter>".s:interCommentBlock, "g" )
if( s:endCommentBlock != "" )
exec "normal o".s:endCommentBlock
endif
if( g:DoxygenToolkit_licenseTag == s:licenseTag )
exec "normal %jA".l:date." - ".g:DoxygenToolkit_authorName
endif
exec "normal `d"
call s:RestoreParameters()
endfunction
""""""""""""""""""""""""""
" Doxygen author comment
""""""""""""""""""""""""""
function! <SID>DoxygenAuthorFunc()
call s:InitializeParameters()
" Test authorName variable
if !exists("g:DoxygenToolkit_authorName")
let g:DoxygenToolkit_authorName = input("Enter name of the author (generally yours...) : ")
endif
" Test versionString variable
if !exists("g:DoxygenToolkit_versionString")
let g:DoxygenToolkit_versionString = input("Enter version string : ")
endif
" Get file name
let l:fileName = expand('%:t')
" Begin to write skeleton
" let l:insertionMode = s:StartDocumentationBlock()
exec "normal O".""
if(s:CheckFileType() == "python")
exec "normal A"."#*****************************************************************************************************"
else
exec "normal A"."/*****************************************************************************************************"
endif
exec "normal o".s:interCommentTag.g:DoxygenToolkit_fileTag." ".l:fileName
exec "normal o".s:interCommentTag.g:DoxygenToolkit_briefTag_pre
mark d
exec "normal o".s:interCommentTag.g:DoxygenToolkit_authorTag." ".g:DoxygenToolkit_authorName
exec "normal o".s:interCommentTag.g:DoxygenToolkit_versionTag." ".g:DoxygenToolkit_versionString
let l:date = strftime("%Y-%m-%d")
exec "normal o".s:interCommentTag.g:DoxygenToolkit_dateTag." ".l:date
if(s:CheckFileType() == "python")
exec "normal o"."#******************************************************************************************************"
else
exec "normal o"."******************************************************************************************************/"
endif
" if ( g:DoxygenToolkit_endCommentTag != "" )
" exec "normal o".s:endCommentTag
" endif
" Move the cursor to the rigth position
exec "normal `d"
exec "normal A"."@Desp"." "
call s:RestoreParameters()
startinsert!
endfunction
""""""""""""""""""""""""""
" Doxygen undocument function
" C/C++ only!
""""""""""""""""""""""""""
function! <SID>DoxygenUndocumentFunc(blockTag)
call s:InitializeParameters()
let l:search = "#ifdef " . a:blockTag
" Save cursor position and go to the begining of the file
mark d
exec "normal gg"
while ( search(l:search, 'W') != 0 )
exec "normal O#ifndef " . g:DoxygenToolkit_undocTag
exec "normal j^%"
if ( g:DoxygenToolkit_endCommentTag == "" )
exec "normal o#endif // " . g:DoxygenToolkit_undocTag
else
exec "normal o#endif /* " . g:DoxygenToolkit_undocTag . " */"
endif
endwhile
exec "normal `d"
call s:RestoreParameters()
endfunction
""""""""""""""""""""""""""
" DoxygenBlockFunc
""""""""""""""""""""""""""
function! <SID>DoxygenBlockFunc()
call s:InitializeParameters()
let l:insertionMode = s:StartDocumentationBlock()
exec "normal ".l:insertionMode.s:interCommentTag.g:DoxygenToolkit_blockTag
mark d
exec "normal o".s:interCommentTag."@{ ".s:endCommentTag
exec "normal o".strpart( s:startCommentTag, 0, 1 )
exec "normal A".strpart( s:startCommentTag, 1 )." @} ".s:endCommentTag
exec "normal `d"
call s:RestoreParameters()
startinsert!
endfunction
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Main comment function for class, attribute, function...
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! <SID>DoxygenCommentFunc()
" Initialize default templates.
" Assure compatibility with Python for classes (cf. endDocPattern).
let l:emptyLinePattern = '^[[:blank:]]*$'
let l:someNamePattern = '[_[:alpha:]][_[:alnum:]]*'
if( s:CheckFileType() == "cpp" )
let l:someNameWithNamespacePattern = l:someNamePattern.'\%(::'.l:someNamePattern.'\)*'
let l:endDocPattern = ';\|{\|\%([^:]\zs:\ze\%([^:]\|$\)\)'
let l:commentPattern = '\%(/*\)\|\%(//\)\'
let l:templateParameterPattern = "<[^<>]*>"
let l:throwPattern = '.*\<throw\>[[:blank:]]*(\([^()]*\)).*' "available only for 'cpp' type
let l:classPattern = '\<class\>[[:blank:]]\+\zs'.l:someNameWithNamespacePattern.'\ze.*\%('.l:endDocPattern.'\)'
let l:structPattern = '\<struct\>[[:blank:]]\+\zs'.l:someNameWithNamespacePattern.'\ze[^(),]*\%('.l:endDocPattern.'\)'
let l:enumPattern = '\<enum\>\%(\%([[:blank:]]\+\zs'.l:someNamePattern.'\ze[[:blank:]]*\)\|\%(\zs\ze[[:blank:]]*\)\)\%('.l:endDocPattern.'\)'
let l:namespacePattern = '\<namespace\>[[:blank:]]\+\zs'.l:someNamePattern.'\ze[[:blank:]]*\%('.l:endDocPattern.'\)'
let l:types = { "class": l:classPattern, "struct": l:structPattern, "enum": l:enumPattern, "namespace": l:namespacePattern }
else
let l:commentPattern = '#\|^[[:blank:]]*"""'
let l:classPattern = '\<class\>[[:blank:]]\+\zs'.l:someNamePattern.'\ze.*:'
let l:functionPattern = '\<def\>[[:blank:]]\+\zs'.l:someNamePattern.'\ze.*:'
let l:endDocPattern = '\%(\<class\>\|\<def\>[^:]*\)\@<!$'
let l:types = { "class": l:classPattern, "function": l:functionPattern }
endif
let l:lineBuffer = getline( line( "." ) )
let l:count = 1
let l:endDocFound = 0
let l:doc = { "type": "", "name": "None", "params": [], "returns": "" , "templates": [], "throws": [] }
" Mark current line for future use
mark d
" Look for function/method/... to document
" We look only on the first three lines!
while( match( l:lineBuffer, l:emptyLinePattern ) != -1 && l:count < 4 )
exec "normal j"
let l:lineBuffer = l:lineBuffer.' '.getline( line( "." ) )
let l:count = l:count + 1
endwhile
" Error message when the buffer is still empty.
if( match( l:lineBuffer, l:emptyLinePattern ) != -1 )
call s:WarnMsg( "Nothing to document here!" )
exec "normal `d"
return
endif
" Remove unwanted lines (ie: jump to the first significant line)
if( g:DoxygenToolkit_keepEmptyLineAfterComment == "no" )
" This erase previous mark
mark d
endif
" Look for the end of the function/class/... to document
" TODO does not work when function/class/... is commented out!
let l:readError = "Cannot reach end of function/class/... declaration!"
let l:count = 0
let l:throwCompleted = 0
let l:endReadPattern = l:endDocPattern
while( l:endDocFound == 0 && l:count < g:DoxygenToolkit_maxFunctionProtoLines )
let l:lineBuffer = s:RemoveComments( l:lineBuffer )
" Valid only for cpp. For Python it must be 'class ...:' or 'def ...:' or
" '... EOL'.
if( match( l:lineBuffer, l:endReadPattern ) != -1 )
" Look for throw statement at the end
if( s:CheckFileType() == "cpp" && l:throwCompleted == 0 )
" throw statement can have already been read or can be on next line
if( match( l:lineBuffer.' '.getline( line ( "." ) + 1 ), '.*\<throw\>.*' ) != -1 )
let l:endReadPattern = l:throwPattern
let l:throwCompleted = 1
let l:readError = "Cannot reach end of throw statement"
else
let l:endDocFound = 1
endif
else
let l:endDocFound = 1
endif
continue
endif
exec "normal j"
let l:lineBuffer = l:lineBuffer.' '.getline( line( "." ))
let l:count = l:count + 1
endwhile
" Error message when the end of the function(/...) has not been found
if( l:endDocFound == 0 )
if( match( l:lineBuffer, l:emptyLinePattern ) != -1 )
" Fall here when only comments have been found.
call s:WarnMsg( "Nothing to document here!" )
else
call s:WarnMsg( l:readError )
endif
exec "normal `d"
return
endif
" Trim the buffer
let l:lineBuffer = substitute( l:lineBuffer, "^[[:blank:]]*\|[[:blank:]]*$", "", "g" )
" Check whether it is a template definition
call s:ParseFunctionTemplateParameters( l:lineBuffer, l:doc )
" Remove any template parameter.
if( s:CheckFileType() == "cpp" )
while( match( l:lineBuffer, l:templateParameterPattern ) != -1 )
let l:lineBuffer = substitute( l:lineBuffer, l:templateParameterPattern, "", "g" )
endwhile
endif
" Look for the type
for key in keys( l:types )
"call s:WarnMsg( "[DEBUG] buffer:_".l:lineBuffer."_, test:_".l:types[key] )
let l:name = matchstr( l:lineBuffer, l:types[key] )
if( l:name != "" )
let l:doc.type = key
let l:doc.name = l:name
" Python only. Functions are detected differently for C/C++.
if( key == "function" )
"call s:WarnMsg( "HERE !!!".l:lineBuffer )
call s:ParseFunctionParameters( l:lineBuffer, l:doc )
endif
break
endif
endfor
if( l:doc.type == "" )
" Should be a function/method (cpp only) or an attribute.
" (cpp only) Can also be an unnamed enum/namespace... (or something else ?)
if( s:CheckFileType() == "cpp" )
if( match( l:lineBuffer, '(' ) == -1 )
if( match( l:lineBuffer, '\<enum\>' ) != -1 )
let l:doc.type = 'enum'
elseif( match( l:lineBuffer, '\<namespace\>' ) != -1 )
let l:doc.type = 'namespace'
else
" TODO here we get a class attribute of something like that.
" We probably just need a \brief statement...
let l:doc.type = 'attribute'
" TODO Retrieve the name of the attribute.
" Do we really need it? I'm not sure for the moment.
endif
else
let l:doc.type = 'function'
call s:ParseFunctionParameters( l:lineBuffer, l:doc )
if( l:throwCompleted == 1 )
call s:ParseThrowParameters( l:lineBuffer, l:doc, l:throwPattern )
endif
endif
" This is an attribute for Python
else
let l:doc.type = 'attribute'
endif
endif
" Remove the function/class/... name when it is not necessary
if( ( l:doc.type == "class" && g:DoxygenToolkit_briefTag_className != "yes" ) || ( l:doc.type == "struct" && g:DoxygenToolkit_briefTag_structName != "yes" ) || ( l:doc.type == "enum" && g:DoxygenToolkit_briefTag_enumName != "yes" ) || ( l:doc.type == "namespace" && g:DoxygenToolkit_briefTag_namespaceName != "yes" ) || ( l:doc.type == "function" && g:DoxygenToolkit_briefTag_funcName != "yes" ) )
let l:doc.name = "None"
" Remove namespace from the name of the class/function...
elseif( s:CheckFileType() == "cpp" )
let l:doc.name = substitute( l:doc.name, '\%('.l:someNamePattern.'::\)', '', 'g' )
endif
" Below, write what we have found
"""""""""""""""""""""""""""""""""
call s:InitializeParameters()
if( s:CheckFileType() == "python" && l:doc.type == "function" && g:DoxygenToolkit_python_autoFunctionReturn == "yes" )
let l:doc.returns = "yes"
endif
" Header
exec "normal `d"
if( g:DoxygenToolkit_blockHeader != "" )
exec "normal O".strpart( s:startCommentBlock, 0, 1 )
exec "normal A".strpart( s:startCommentBlock, 1 ).g:DoxygenToolkit_blockHeader.s:endCommentBlock
exec "normal `d"
endif
" Brief
if( g:DoxygenToolkit_compactOneLineDoc =~ "yes" && l:doc.returns != "yes" && len( l:doc.params ) == 0 )
let s:compactOneLineDoc = "yes"
exec "normal O".strpart( s:startCommentTag, 0, 1 )
exec "normal A".strpart( s:startCommentTag, 1 ).g:DoxygenToolkit_briefTag_pre
else
let s:compactOneLineDoc = "no"
let l:insertionMode = s:StartDocumentationBlock()
exec "normal ".l:insertionMode.s:interCommentTag.g:DoxygenToolkit_briefTag_pre
endif
if( l:doc.name != "None" )
exec "normal A".l:doc.name." "
endif
exec "normal A".g:DoxygenToolkit_briefTag_post
" Mark the line where the cursor will be positionned.
mark d
" Arguments/parameters
if( g:DoxygenToolkit_compactDoc =~ "yes" )
let s:insertEmptyLine = 0
else
let s:insertEmptyLine = 1
endif
for param in l:doc.templates
if( s:insertEmptyLine == 1 )
exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" )
let s:insertEmptyLine = 0
endif
exec "normal o".s:interCommentTag.g:DoxygenToolkit_templateParamTag_pre.param.g:DoxygenToolkit_templateParamTag_post
endfor
for param in l:doc.params
if( s:insertEmptyLine == 1 )
exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" )
let s:insertEmptyLine = 0
endif
exec "normal o".s:interCommentTag.g:DoxygenToolkit_paramTag_pre.param.g:DoxygenToolkit_paramTag_post
endfor
" Returned value
if( l:doc.returns == "yes" )
if( g:DoxygenToolkit_compactDoc != "yes" )
exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" )
endif
exec "normal o".s:interCommentTag.g:DoxygenToolkit_returnTag
endif
" Exception (throw) values (cpp only)
if( len( l:doc.throws ) > 0 )
if( g:DoxygenToolkit_compactDoc =~ "yes" )
let s:insertEmptyLine = 0
else
let s:insertEmptyLine = 1
endif
for param in l:doc.throws
if( s:insertEmptyLine == 1 )
exec "normal o".substitute( s:interCommentTag, "[[:blank:]]*$", "", "" )
let s:insertEmptyLine = 0
endif
exec "normal o".s:interCommentTag.g:DoxygenToolkit_throwTag_pre.param.g:DoxygenToolkit_throwTag_post
endfor
endif
" End (if any) of documentation block.
if( s:endCommentTag != "" )
if( s:compactOneLineDoc =~ "yes" )
let s:execCommand = "A"
exec "normal A "
exec "normal $md"
else
let s:execCommand = "o"
endif
exec "normal ".s:execCommand.s:endCommentTag
endif
" Footer
if ( g:DoxygenToolkit_blockFooter != "" )
exec "normal o".strpart( s:startCommentBlock, 0, 1 )
exec "normal A".strpart( s:startCommentBlock, 1 ).g:DoxygenToolkit_blockFooter.s:endCommentBlock
endif
exec "normal `d"
call s:RestoreParameters()
if( s:compactOneLineDoc =~ "yes" && s:endCommentTag != "" )
startinsert
else
startinsert!
endif
" DEBUG purpose only
"call s:WarnMsg( "Found a ".l:doc.type." named ".l:doc.name." (env: ".s:CheckFileType().")." )
"if( l:doc.type == "function" )
" let l:funcReturn = "returns something."
" if( l:doc.returns == "" )
" let l:funcReturn = "doesn't return anything."
" endif
" call s:WarnMsg( " - which ".l:funcReturn )
" call s:WarnMsg( " - which has following parameter(s):" )
" for param in l:doc.params
" call s:WarnMsg( " - ".param )
" endfor
"endif
endfunction
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Write the beginning of the documentation block:
" - C and Python format: insert '/**' and '##' respectively then a linefeed,
" - C++ insert '///' and continue on the same line
"
" This function return the insertion mode which should be used for the next
" call to 'normal'.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:StartDocumentationBlock()
" For C++ documentation format we do not need first empty line
if( s:startCommentTag != s:interCommentTag )
"exec "normal O".s:startCommentTag
exec "normal O".strpart( s:startCommentTag, 0, 1 )
exec "normal A".substitute( strpart( s:startCommentTag, 1 ), "[[:blank:]]*$", "", "" )
let l:insertionMode = "o"
else
let l:insertionMode = "O"
endif
return l:insertionMode
endfunction
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Remove comments from the given buffer.
" - Remove everything after '//' or '#'.
" - Remove everything between '/*' and '*/' or keep '/*' if '*/' is not present.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:RemoveComments( lineBuffer )
if( s:CheckFileType() == "cpp" )
" Remove C++ (//) comment.
let l:lineBuffer = substitute( a:lineBuffer, '[[:blank:]]*\/\/.*$', '', '')
" Remove partial C (/* ...) comment: /* foo bar --> /*
" '/*' is preserved until corresponding '*/' is found. Other part of the
" comment is discarded to prevent the case where it contains characters
" corresponding to the endDoc string.
let l:lineBuffer = substitute( l:lineBuffer, '\%(\/\*\zs.*\ze\)\&\%(\%(\/\*.*\*\/\)\@!\)', '', '')
" Remove C (/* ... */) comment.
let l:lineBuffer = substitute( l:lineBuffer, '\/\*.\{-}\*\/', '', 'g')
else
let l:lineBuffer = substitute( a:lineBuffer, '[[:blank:]]*#.*$', '', '')
endif
return l:lineBuffer
endfunction
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Retrieve file type.
" - Default type is still 'cpp'.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:CheckFileType()
if( &filetype == "python" )
let l:fileType = "python"
else
let l:fileType = "cpp"
endif
return l:fileType
endfunction
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Parse the buffer and set the doc parameter.
" - Functions which return pointer to function are not supported.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:ParseFunctionParameters( lineBuffer, doc )
"call s:WarnMsg( 'IN__'.a:lineBuffer )
let l:paramPosition = matchend( a:lineBuffer, 'operator[[:blank:]]*([[:blank:]]*)' )
if ( l:paramPosition == -1 )
let l:paramPosition = stridx( a:lineBuffer, '(' )
else
let l:paramPosition = stridx( a:lineBuffer, '(', l:paramPosition )
endif
" (cpp only) First deal with function name and returned value.
" Function name has already been retrieved for Python and we need to parse
" all the function definition to know whether a value is returned or not.
if( s:CheckFileType() == "cpp" )
let l:functionBuffer = strpart( a:lineBuffer, 0, l:paramPosition )
" Remove unnecessary elements
for ignored in g:DoxygenToolkit_ignoreForReturn
let l:functionBuffer = substitute( l:functionBuffer, '\<'.ignored.'\>', '', 'g' )
endfor
let l:functionReturnAndName = split( l:functionBuffer, '[[:blank:]*]' )
if( len( l:functionReturnAndName ) > 1 )
let a:doc.returns = 'yes'
endif
let a:doc.name = l:functionReturnAndName[-1]
endif
" Work on parameters.
let l:parametersBuffer = strpart( a:lineBuffer, l:paramPosition + 1 )
" Remove trailing closing bracket and everything that follows and trim.
if( s:CheckFileType() == "cpp" )
let l:parametersBuffer = substitute( l:parametersBuffer, ')[^)]*\%(;\|{\|\%([^:]:\%([^:]\|$\)\)\|\%(\<throw\>\)\).*', '', '' )
else
let l:parametersBuffer = substitute( l:parametersBuffer, ')[^)]*:.*', '', '' )
endif
let l:parametersBuffer = substitute( l:parametersBuffer, '^[[:blank:]]*\|[[:blank:]]*$', '', '' )
" Remove default parameter values (if any).
let l:index = stridx( l:parametersBuffer, '=' )
let l:startIndex = l:index
while( l:index != -1 )
" Look for the next colon...
let l:colonIndex = stridx( l:parametersBuffer, ',', l:startIndex )
if( l:colonIndex == -1 )
let l:colonIndex = strlen( l:parametersBuffer )
endif
let l:paramBuffer = strpart( l:parametersBuffer, l:index, l:colonIndex - l:index )
if( s:CountBrackets( l:paramBuffer ) == 0 )
" Everything in [l:index, l:colonIndex[ can be removed.
let l:parametersBuffer = substitute( l:parametersBuffer, l:paramBuffer, '', '' )
let l:index = stridx( l:parametersBuffer, '=' )
let l:startIndex = l:index
else
" Parameter initialization contains brakets and colons...
let l:startIndex = l:colonIndex + 1
endif
endwhile
"call s:WarnMsg( "[DEBUG]: ".l:parametersBuffer )
" Now, work on each parameter.
let l:params = []
let l:index = stridx( l:parametersBuffer, ',' )
while( l:index != -1 )
let l:paramBuffer = strpart( l:parametersBuffer, 0, l:index )
if( s:CountBrackets( l:paramBuffer ) == 0 )
let l:params = add( l:params, s:ParseParameter( l:paramBuffer ) )
let l:parametersBuffer = strpart( l:parametersBuffer, l:index + 1 )
let l:index = stridx( l:parametersBuffer, ',' )
else
let l:index = stridx( l:parametersBuffer, ',', l:index + 1 )
endif
endwhile
if( strlen( l:parametersBuffer ) != 0 )
let l:params = add( l:params, s:ParseParameter( l:parametersBuffer ) )
endif
if( s:CheckFileType() == "cpp" )
call filter( l:params, 'v:val !~ "void"' )
else