Skip to content

Commit 6a31a6d

Browse files
author
Matthias Kastner
committed
add function comments
The comments above the function definition are displayed as help text. This feature uses QT's helptext and requires Igor Pro 8. The function marker description is added to the first column and the comment to the second. The output of the tooltip is formatted with basic html. The comment is enclosed in code tags to have equal line spacing. support for Doxygen comments: * @Keyword is emphasized italic * @param keyword is printed strong bold.
1 parent 4908ba8 commit 6a31a6d

File tree

3 files changed

+140
-26
lines changed

3 files changed

+140
-26
lines changed

procedures/CodeBrowser.ipf

Lines changed: 135 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ StrConstant pkgFolder = "root:Packages:CodeBrowser"
3737
// second column: full declaration of the function/macro
3838
// one row for each function/macro
3939
StrConstant declarations = "declarations"
40+
// 2D Wave
41+
// first column: marker description
42+
// second column: function comment
43+
StrConstant helpWave = "help"
4044
// 1D Wave in each row having the line of the function or -1 for macros
4145
StrConstant declarationLines = "lines"
4246
// database-like global multidimensional waves for storing parsing results to minimize time.
@@ -327,15 +331,17 @@ Function addDecoratedFunctions(module, procedure, declWave, lineWave)
327331

328332
String options, funcList
329333
string func, funcDec, fi
330-
string threadsafeTag, specialTag, params, subtypeTag, returnType
334+
string threadsafeTag, specialTag, params, subtypeTag, returnType, entityType
331335
variable i, idx, numMatches, numEntries
332336

337+
Wave/T helpWave = getHelpWave()
338+
333339
// list normal, userdefined, override and static functions
334340
options = "KIND:18,WIN:" + procedure
335341
funcList = FunctionList("*", ";", options)
336342
numMatches = ItemsInList(funcList)
337343
numEntries = DimSize(declWave, 0)
338-
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave
344+
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave, helpWave
339345

340346
idx = numEntries
341347
for(i = 0; i < numMatches; i += 1)
@@ -352,8 +358,11 @@ Function addDecoratedFunctions(module, procedure, declWave, lineWave)
352358
specialTag = interpretSpecialTag(StringByKey("SPECIAL", fi))
353359
subtypeTag = interpretSubtypeTag(StringByKey("SUBTYPE", fi))
354360
params = interpretParameters(fi)
355-
declWave[idx][0] = createMarkerForType("function" + specialTag + threadsafeTag)
361+
entityType = "function" + specialTag + threadsafeTag
362+
declWave[idx][0] = createMarkerForType(entityType)
356363
declWave[idx][1] = formatDecl(func, params, subtypeTag, returnType)
364+
helpWave[idx][0] = entityType
365+
helpWave[idx][1] = AddHTML(TrimFunctionComment(getFunctionLine(-inf, fi)))
357366
lineWave[idx] = NumberByKey("PROCLINE", fi)
358367
idx += 1
359368
endfor
@@ -372,6 +381,8 @@ Function addDecoratedConstants(module, procedureWithoutModule, declWave, lineWav
372381
Variable numLines, i, idx, numEntries, numMatches
373382
String procText, re, def, name
374383

384+
Wave/T helpWave = getHelpWave()
385+
375386
// get procedure code
376387
procText = getProcedureText("", 0, module, procedureWithoutModule)
377388
numLines = ItemsInList(procText, "\r")
@@ -392,7 +403,7 @@ Function addDecoratedConstants(module, procedureWithoutModule, declWave, lineWav
392403

393404
numMatches = DimSize(wavLineNumber, 0)
394405
numEntries = DimSize(declWave, 0)
395-
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave
406+
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave, helpWave
396407

397408
idx = numEntries
398409
for(i = 0; i < numMatches; i += 1)
@@ -415,6 +426,8 @@ Function addDecoratedMacros(module, procedureWithoutModule, declWave, lineWave)
415426
Variable numLines, idx, numEntries, numMatches
416427
String procText, re, def, name, arguments, type
417428

429+
Wave/T helpWave = getHelpWave()
430+
418431
// get procedure code
419432
procText = getProcedureText("", 0, module, procedureWithoutModule)
420433
numLines = ItemsInList(procText, "\r")
@@ -437,7 +450,7 @@ Function addDecoratedMacros(module, procedureWithoutModule, declWave, lineWave)
437450

438451
numMatches = DimSize(wavLineNumber, 0)
439452
numEntries = DimSize(declWave, 0)
440-
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave
453+
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave, helpWave
441454

442455
for(idx = numEntries; idx < (numEntries + numMatches); idx += 1)
443456
SplitString/E=re text[wavLineNumber[(idx - numEntries)]], def, name, arguments, type
@@ -461,6 +474,8 @@ Function addDecoratedStructure(module, procedureWithoutModule, declWave, lineWav
461474
variable numLines, idx, numEntries, numMatches
462475
string procText, reStart, reEnd, name, StaticKeyword
463476

477+
Wave/T helpWave = getHelpWave()
478+
464479
// get procedure code
465480
procText = getProcedureText("", 0, module, procedureWithoutModule)
466481
numLines = ItemsInList(procText, "\r")
@@ -502,7 +517,7 @@ Function addDecoratedStructure(module, procedureWithoutModule, declWave, lineWav
502517
endif
503518

504519
numEntries = DimSize(declWave, 0)
505-
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave
520+
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave, helpWave
506521

507522
for(idx = numEntries; idx < (numEntries + numMatches); idx +=1)
508523
SplitString/E=reStart text[wavStructureStart[(idx - numEntries)]], StaticKeyword, name
@@ -531,6 +546,8 @@ Function addDecoratedMenu(module, procedureWithoutModule, declWave, lineWave)
531546
String procText, re, def, name, type
532547
String currentMenu = ""
533548

549+
Wave/T helpWave = getHelpWave()
550+
534551
// get procedure code
535552
procText = getProcedureText("", 0, module, procedureWithoutModule)
536553
numLines = ItemsInList(procText, "\r")
@@ -551,7 +568,7 @@ Function addDecoratedMenu(module, procedureWithoutModule, declWave, lineWave)
551568

552569
numMatches = DimSize(wavLineNumber, 0)
553570
numEntries = DimSize(declWave, 0)
554-
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave
571+
Redimension/N=(numEntries + numMatches, -1) declWave, lineWave, helpWave
555572

556573
for(idx = numEntries; idx < (numEntries + numMatches); idx += 1)
557574
SplitString/E=re text[wavLineNumber[(idx - numEntries)]], def, name, type
@@ -646,15 +663,18 @@ Function/S getVariableName(strDefinition)
646663
return strVariableName
647664
End
648665

649-
static Function resetLists(decls, lines)
666+
static Function resetLists(decls, lines, helps)
650667
Wave/T decls
651668
Wave/D lines
652-
Redimension/N=(0, -1) decls, lines
669+
Wave/T helps
670+
Redimension/N=(0, -1) decls, lines, helps
653671
End
654672

655-
static Function sortListByLineNumber(decls, lines)
673+
// @todo IgorPro >= 7 supports SortColumns
674+
static Function sortListByLineNumber(decls, lines, helps)
656675
Wave/T decls
657676
Wave/D lines
677+
Wave/T helps
658678

659679
// check if sort is necessary
660680
if(Dimsize(decls, 0) * Dimsize(lines, 0) == 0)
@@ -663,14 +683,20 @@ static Function sortListByLineNumber(decls, lines)
663683

664684
Duplicate/T/FREE/R=[][0] decls, declCol0
665685
Duplicate/T/FREE/R=[][1] decls, declCol1
666-
Sort/A lines, lines, declCol0, declCol1
686+
Duplicate/T/FREE/R=[][0] helps, helpCol0
687+
Duplicate/T/FREE/R=[][1] helps, helpCol1
688+
Sort/A lines, lines, declCol0, declCol1, helpCol0, helpCol1
667689
decls[][0] = declCol0[p][0]
668690
decls[][1] = declCol1[p][0]
691+
helps[][0] = helpCol0[p][0]
692+
helps[][1] = helpCol1[p][0]
669693
End
670694

671-
static Function sortListByName(decls, lines)
695+
// @todo IgorPro >= 7 supports SortColumns
696+
static Function sortListByName(decls, lines, helps)
672697
Wave/T decls
673698
Wave/D lines
699+
Wave/T helps
674700

675701
// check if sort is necessary
676702
if(Dimsize(decls, 0) * Dimsize(lines, 0) == 0)
@@ -679,9 +705,13 @@ static Function sortListByName(decls, lines)
679705

680706
Duplicate/T/FREE/R=[][0] decls, declCol0
681707
Duplicate/T/FREE/R=[][1] decls, declCol1
682-
Sort/A declCol1, lines, declCol0, declCol1
708+
Duplicate/T/FREE/R=[][0] helps, helpCol0
709+
Duplicate/T/FREE/R=[][1] helps, helpCol1
710+
Sort/A declCol1, lines, declCol0, declCol1, helpCol0, helpCol1
683711
decls[][0] = declCol0[p][0]
684712
decls[][1] = declCol1[p][0]
713+
helps[][0] = helpCol0[p][0]
714+
helps[][1] = helpCol1[p][0]
685715
End
686716

687717
// Parses all procedure windows and write into the decl and line waves
@@ -702,9 +732,10 @@ Function/S parseProcedure(procedure, [checksumIsCalculated])
702732
// load global lists
703733
Wave/T decls = getDeclWave()
704734
Wave/I lines = getLineWave()
735+
Wave/T helps = getHelpWave()
705736

706737
// scan and add elements to lists
707-
resetLists(decls, lines)
738+
resetLists(decls, lines, helps)
708739
addDecoratedFunctions(procedure.module, procedure.fullName, decls, lines)
709740
addDecoratedConstants(procedure.module, procedure.name, decls, lines)
710741
addDecoratedMacros(procedure.module, procedure.name, decls, lines)
@@ -721,6 +752,7 @@ static Function saveResults(procedure)
721752

722753
Wave/T declWave = getDeclWave()
723754
Wave/I lineWave = getLineWave()
755+
Wave/T helpWave = getHelpWave()
724756

725757
Wave/WAVE SaveWavesWave = getSaveWaves()
726758
Wave/T SaveStringsWave = getSaveStrings()
@@ -745,10 +777,12 @@ static Function saveResults(procedure)
745777
// save Results. Waves as References to free waves and the Id-Identifier
746778
Duplicate/FREE declWave myFreeDeclWave
747779
Duplicate/FREE lineWave myFreeLineWave
780+
Duplicate/FREE helpWave myFreeHelpWave
748781
SaveStringsWave[procedure.row][0] = procedure.id
749782
SaveStringsWave[procedure.row][1] = getChecksum()
750783
SaveWavesWave[procedure.row][0] = myFreeDeclWave
751784
SaveWavesWave[procedure.row][1] = myFreeLineWave
785+
SaveWavesWave[procedure.row][2] = myFreeHelpWave
752786
SaveVariablesWave[procedure.row][0] = 1 // mark as valid
753787
SaveVariablesWave[procedure.row][1] = getParsingTime() // time in micro seconds
754788
SaveVariablesWave[procedure.row][2] = getCheckSumTime() // time in micro seconds
@@ -776,6 +810,7 @@ static Function saveLoad(procedure)
776810

777811
Wave/T declWave = getDeclWave()
778812
Wave/I lineWave = getLineWave()
813+
Wave/T helpWave = getHelpWave()
779814

780815
Wave/WAVE SaveWavesWave = getSaveWaves()
781816
Wave/T SaveStringsWave = getSaveStrings()
@@ -808,16 +843,18 @@ static Function saveLoad(procedure)
808843
endif
809844

810845
numResults = Dimsize(SaveWavesWave[procedure.row][0], 0)
811-
Redimension/N=(numResults, -1) declWave, lineWave
846+
Redimension/N=(numResults, -1) declWave, lineWave, helpWave
812847
if(numResults == 0)
813848
debugPrint("no elements in save state")
814849
return 0
815850
endif
816851

817852
WAVE/T load0 = SaveWavesWave[procedure.row][0]
818853
WAVE/I load1 = SaveWavesWave[procedure.row][1]
854+
WAVE/T load2 = SaveWavesWave[procedure.row][2]
819855
declWave[][0, 1] = load0[p][q]
820856
lineWave[] = load1[p]
857+
helpWave[][0, 1] = load2[p][q]
821858

822859
debugPrint("save state loaded successfully")
823860
return 1
@@ -958,6 +995,56 @@ Function/S getFunctionLine(lineNo, funcInfo)
958995
return StringFromList(lineNo, context, "\r")
959996
End
960997

998+
// return only fully-commented lines from the given input
999+
Function/S TrimFunctionComment(context)
1000+
string context
1001+
1002+
string comment = GrepList(context, "^(?i)//.*$", 0, "\r")
1003+
return RemoveEnding(comment, "\r")
1004+
End
1005+
1006+
// add basic html
1007+
Function/S AddHTML(context)
1008+
string context
1009+
1010+
string line, html, re
1011+
string str0, str1, str2, str3, str4
1012+
variable n, lines
1013+
1014+
html = ""
1015+
lines = ItemsInList(context, "\r")
1016+
for(n = 0; n < lines; n += 1)
1017+
line = StringFromList(n, context, "\r")
1018+
re = "\s*([\/]{2,})\s?(.*)"
1019+
SplitString/E=(re) line, str0, str1
1020+
if(V_flag != 2)
1021+
break
1022+
endif
1023+
line = str1
1024+
if(strlen(str0) == 3) // Doxygen comments
1025+
re = "(?i)(.*@param(?:\[(?:in|out)\])?\s+)(\w+)(\s.*)"
1026+
SplitString/E=(re) line, str0, str1, str2
1027+
if(V_flag == 3)
1028+
line = str0
1029+
line += "<b>" + str1 + "</b> "
1030+
line += str2
1031+
endif
1032+
re = "(?i)(.*)@(\w+)(\s.*)"
1033+
SplitString/E=(re) line, str0, str1, str2
1034+
if(V_flag == 3)
1035+
line = str0
1036+
line += "<b>@</b><i>" + str1 + "</i>"
1037+
line += str2
1038+
endif
1039+
endif
1040+
html += line + "<br>"
1041+
endfor
1042+
html = RemoveEnding(html, "<br>")
1043+
html = "<code>" + html + "</code>"
1044+
1045+
return html
1046+
End
1047+
9611048
// get code of procedure in module
9621049
//
9631050
// see `DisplayHelpTopic("ProcedureText")`
@@ -990,6 +1077,7 @@ Function updateListBoxHook()
9901077
// load global lists (for sort)
9911078
Wave/T decls = getDeclWave()
9921079
Wave/I lines = getLineWave()
1080+
Wave/T helps = getHelpWave()
9931081

9941082
// get procedure information
9951083
procedure.fullName = getCurrentItem(procedure = 1)
@@ -1014,22 +1102,23 @@ Function updateListBoxHook()
10141102
// check if search is necessary
10151103
searchString = getGlobalStr("search")
10161104
if(strlen(searchString) > 0)
1017-
searchAndDelete(decls, lines, searchString)
1105+
searchAndDelete(decls, lines, helps, searchString)
10181106
endif
10191107

10201108
// switch sort type
10211109
if(returnCheckBoxSort())
1022-
sortListByName(decls, lines)
1110+
sortListByName(decls, lines, helps)
10231111
else
1024-
sortListByLineNumber(decls, lines)
1112+
sortListByLineNumber(decls, lines, helps)
10251113
endif
10261114

10271115
return DimSize(decls, 0)
10281116
End
10291117

1030-
Function searchAndDelete(decls, lines, searchString)
1118+
Function searchAndDelete(decls, lines, helps, searchString)
10311119
Wave/T decls
10321120
Wave/I lines
1121+
Wave/T helps
10331122
String searchString
10341123

10351124
Variable i, numEntries
@@ -1041,16 +1130,16 @@ Function searchAndDelete(decls, lines, searchString)
10411130

10421131
for(i = numEntries - 1; i > 0; i -= 1)
10431132
if(strsearch(decls[i][1], searchString, 0, 2) == -1)
1044-
DeletePoints/M=0 i, 1, decls, lines
1133+
DeletePoints/M=0 i, 1, decls, lines, helps
10451134
endif
10461135
endfor
10471136

10481137
// prevent loss of dimension if no match was found at all.
10491138
if(strsearch(decls[0][1], searchString, 0, 2) == -1)
10501139
if(Dimsize(decls, 0) == 1)
1051-
Redimension/N=(0, -1) decls, lines
1140+
Redimension/N=(0, -1) decls, lines, helps
10521141
else
1053-
DeletePoints/M=0 i, 1, decls, lines
1142+
DeletePoints/M=0 i, 1, decls, lines, helps
10541143
endif
10551144
endif
10561145
End
@@ -1129,6 +1218,20 @@ Function/S getModuleList()
11291218
return moduleList
11301219
End
11311220

1221+
// get help wave: after parsing the function comment is stored here
1222+
//
1223+
// Return refrence to (text) Wave/T
1224+
Function/Wave getHelpWave()
1225+
DFREF dfr = createDFWithAllParents(pkgFolder)
1226+
WAVE/Z/T/SDFR=dfr wv = $helpWave
1227+
1228+
if(!WaveExists(wv))
1229+
Make/T/N=(128, 2) dfr:$helpWave/Wave=wv
1230+
endif
1231+
1232+
return wv
1233+
End
1234+
11321235
// Returns declarations: after parsing the object names and variables are stored in this wave.
11331236
// Return refrence to (text) Wave/T
11341237
Function/Wave getDeclWave()
@@ -1177,11 +1280,18 @@ static Function/Wave getSaveWaves()
11771280
DFREF dfr = createDFWithAllParents(pkgFolder)
11781281
WAVE/Z/WAVE/SDFR=dfr wv = $CsaveWaves
11791282

1180-
if(!WaveExists(wv))
1181-
Make/WAVE/N=(0,2) dfr:$CsaveWaves/Wave=wv // wave of wave references
1283+
if(WaveExists(wv))
1284+
if(DimSize(wv, 1) == 2)
1285+
// update version 0 to 1
1286+
Redimension/N=(-1, 3) wv
1287+
endif
1288+
elseif(!WaveExists(wv))
1289+
//version 1
1290+
Make/WAVE/N=(0,3) dfr:$CsaveWaves/Wave=wv // wave of wave references
11821291
// Wave with Free Waves:
11831292
// Column 1: decl (a (text) Wave/T with the results of parsing the procedure file)
1184-
// Column 1: line (a (integer) Wave/I with the corresponding line numbers within the procedure file)
1293+
// Column 2: line (a (integer) Wave/I with the corresponding line numbers within the procedure file)
1294+
// Column 3: help (a (text) Wave/T with the corresponding function comment)
11851295
endif
11861296

11871297
return wv

0 commit comments

Comments
 (0)