--▽▽UTF-8▽▽ --[[ copyleft by jinzhongjie(xjinzhongjie@hotmail.com).any one who want change the code plese tell wirter. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. ]] --[[ This will make a menu item in your "Tools" menu, that can be used with Control+9 shortcut ]] scite_Command { 'Function Tree|localTree|Ctrl+9', 'All reference|allReference|Ctrl+8', --'ALL Function Tree|AllFunctionTree|Ctrl+8', --'Analysis Files|AnalysisFiles|Ctrl+7', } --local path='D:/DO_WORK/source/AGW/agw_ngn_trunk/src/tsw' --local path='D:/DO_WORK/source/AGW/agw_ngn_trunk/src/mng' --local path='D:/DO_WORK/source/AGW/agw_ngn_trunk/src/xml' --local path='D:/DO_WORK/source/AGW/fe_sp_trunk/src/apl/racoon2/iked' local analysis={} local not_analysis={} --local path='E:/tmp/aplsrc/src/mng' --local path='E:/tmp/aplsrc/src/tsw' --local path='E:/tmp/racoon2/iked' --not output the functions local exclude_func= { plog=1, printf=1, memset=1, memcmp=1, memcpy=1, htonl=1, strcpy=1, strcat=1, strlen=1, agwMngLogDebug=1, strtoul=1, c_str=1, strtok=1, strncmp=1, sprintf=1, agwMngLogError=1, agwMngOpeSysLogError=1, fopen=1, fwrite=1, fclose=1, agwTswMessageInfo=1, agwTswMessageWarning=1, agwTswMessageError=1, agwTswLogInit=1, agwTswLogOutPutDebug=1, agwTswLogOutPutInfo=1, agwTswLogOutPutWarn=1, agwTswLogOutPutError=1, agwTswLogOutPutSys=1, agwTswLogOutPutUsec=1, agwMngOpeSysLogInfo=1, agwXmlMessageInfo=1, agwXmlMessageWarning=1, agwXmlMessageError=1, agwXmlLogInit=1, agwXmlLogDebug=1, agwXmlLogInfo=1, agwXmlLogWarning=1, agwXmlLogError=1, agwXmlLogSys=1, } --not output under the functions local notRecursion_func= { agwMngWriteBackup=1, agwMngShmDetach=1, agwMngFlowEngineIoctlHa=1, agwMngIpsecRlyDel=1, agwMngIpsecRlyAdd=1, agwMngWriteBackupSlice=1, agwMngIpcSendResp=1, } local sub = string.sub local find = string.find local len = string.len local gsub = string.gsub local indent_var --local fucList --local fucTable local funcPath={} --local classList local funcTreeDirectory local classTable={} local recursion_func={} local noPrintAlreadyOutput=true local alreadyOutput_func={} local line_pos={} line_pos[1]=0 local allFuncList={} local rootFile local func_pos_start=-1 local funcLinestart local func_pos_end=-1 local location={} local alreadyLocation={} local active_already=nil local active_location=nil local active_location1=nil local active_location2=nil local active_now=nil local active_before1=nil local active_before2=nil local function TreeAdjust(diff) func_pos_start = func_pos_start + diff func_pos_end = func_pos_end + diff --funcLinestart=output:LineFromPosition(func_pos_start) end local function clearTreeParam() func_pos_start=-1 func_pos_end=-1 end scite_outputChange(function(pane,bPos,length) --print('start:'..output.SelectionStart..',end:'..output.SelectionEnd) if pane == output then --print("---"..keyval) RoutineAdjustChange(bPos,length,func_pos_start,func_pos_end,TreeAdjust,clearTreeParam) end return false end) ------------------------------------------------------------------- local function absolute_path(relative_path) local absPath if funcTreeDirectory~= "" then absPath=funcTreeDirectory.."\\"..relative_path else absPath=relative_path end return absPath end local function remove_tree() if func_pos_start>0 and func_pos_start < func_pos_end then local filePath=props['FilePath'] if active_now then output:MarkerDelete(active_now+funcLinestart-1,9) active_now=nil end if active_already then output:MarkerDelete(active_already+funcLinestart,8) active_already=nil end if active_before2 then output:MarkerDelete(active_before2+funcLinestart-1,11) active_before2=nil end if active_before1 then output:MarkerDelete(active_before1+funcLinestart-1,10) active_before1=nil end if active_location2 then scite.Open(absolute_path(active_location2[1])) editor:MarkerDelete(active_location2[2],9) active_location2=nil end if active_location1 then scite.Open(absolute_path(active_location1[1])) editor:MarkerDelete(active_location1[2],10) active_location1=nil end if active_location then scite.Open(absolute_path(active_location[1])) editor:MarkerDelete(active_location[2],11) active_location=nil end outputRemove(output,func_pos_start, func_pos_end) func_pos_start=-1 func_pos_end=-1 scite.Open(filePath) end end local function fuction_locate(Location) if Location[1] and Location[2] then if active_location2 then scite.Open(absolute_path(active_location2[1])) editor:MarkerDelete(active_location2[2],9) active_location2=nil end if active_location1 then scite.Open(absolute_path(active_location1[1])) editor:MarkerDelete(active_location1[2],10) active_location2=active_location1 editor:MarkerDefine(9,SC_MARK_FULLRECT) editor:MarkerSetBack(9,colour_parse('pink')) editor:MarkerAdd(active_location1[2],9) end if active_location then scite.Open(absolute_path(active_location[1])) editor:MarkerDelete(active_location[2],11) active_location1=active_location editor:MarkerDefine(10,SC_MARK_FULLRECT) editor:MarkerSetBack(10,colour_parse('green')) editor:MarkerAdd(active_location[2],10) end editor:MarkerDefine(11,SC_MARK_FULLRECT) editor:MarkerSetBack(11,colour_parse('blue')) scite.Open(absolute_path(Location[1] )) editor:GotoPos(Location[2] ) editor:MarkerAdd(Location[2],11) active_location=Location ctags_center_pos(Location[2]) end end local function readfunctree(filename, checkpaths) --print( '@@@'..filename) local f = io.open(filename) if not f then return nil end local clsTable = {} allFuncList={} for line in f:lines() do local claname, memtype, remain = line:match('^([^:]+):([^:]+):(.*)$') if claname=='0' then claname=0 end if not clsTable[claname] then clsTable[claname]={} clsTable[claname].memS={} end if remain=='' then --[[ elseif memtype=='o' then if not clsTable[claname].otherMemS then clsTable[claname].otherMemS={} end local l = 1 local pos=string.find(remain, ",", l) while pos do local field = string.sub(remain, l, pos - 1) local member,typ=field:match('^([^=]+)=([^=]+)$') clsTable[claname].otherMemS[member]=typ l = pos + 1 pos = string.find(remain, ",", l) end ]]-- elseif memtype=='m' then local l = 1 local pos=string.find(remain, ",", l) while pos do local field = string.sub(remain, l, pos - 1) local member,typ=field:match('^([^=]+)=([^=]+)$') clsTable[claname].memS[member]=typ l = pos + 1 pos = string.find(remain, ",", l) end elseif memtype=='f' then if not clsTable[claname].funcS then clsTable[claname].funcS={} end local funcname, path, spos,epos,remain1 = remain:match('^([^,]+),([^,]+),([^,]+),([^:]+):([^:]*)$') clsTable[claname].funcS[funcname]={name=funcname,root=1,Type='f',path=path,lineS=tonumber(spos),lineE=tonumber(epos),funcS={} } table.insert(allFuncList, {claname,funcname,tonumber(spos)}) local l = 1 local pos=string.find(remain1, ";", l) while pos do local field = string.sub(remain1, l, pos - 1) local cls,func,num=field:match('^([^,]+),([^,]+),([^,]+)$') if cls=='0' then cls=0 end table.insert(clsTable[claname].funcS[funcname].funcS, {cls,func,tonumber(num)}) l = pos + 1 pos = string.find(remain1, ";", l) end end end f:close() return clsTable end local function loadfunctree(file, force) if file and (force or not funcPath[file] ) then --print( '%%%'..file) funcPath[file] = readfunctree(file, true) end return funcPath[file] end local function locatefunctree(dir, filename) local filepath while dir do filepath = dir .. '/' .. (filename or 'functree') --print( '$$$'..filepath) if loadfunctree(filepath,nil) then return dir end dir = dir:match('(.+)/[^/]+$') end return nil end local clsSelect local ParseName function classAndFunction() local FileDir=props['FileDir']:gsub('\\','/') local tree_dir=locatefunctree(FileDir, 'functree') if tree_dir then funcTreeDirectory=tree_dir classTable=funcPath[tree_dir..'/functree'] else funcTreeDirectory="" ParseFile() end local filePath=props['FilePath'] if filePath~=ParseName then clsSelect=ParseFile('cls') ParseName=filePath end local cls=0 for k, name in pairs(clsSelect) do if editor.CurrentPosname[3] then cls=name[1] break end end local startPos=editor:WordStartPosition(editor.CurrentPos,true) local endPos=editor:WordEndPosition(editor.CurrentPos,true) local funcProperty=getFunctionProperty(startPos,endPos) local parent_type=funcProperty[1] local parent=funcProperty[2] local func=funcProperty[3] if not parent_type then if not parent then if classTable[cls].funcS[func] then parent_type=cls else parent_type=0 end elseif classTable[cls].memS then parent_type=classTable[cls].memS[parent] else parent_type=nil end if not parent_type and parent then parent_type=classTable[0].memS[parent] end end return parent_type,func end scite_OnDoubleClick(function () local sta=command_status() if output.Focus and output.CurrentPos >= func_pos_start and output.CurrentPos <= func_pos_end then funcLinestart=output:LineFromPosition(func_pos_start) local linePos= output:LineFromPosition(output.CurrentPos)+1-funcLinestart if location[linePos] then fuction_locate(location[linePos]) elseif alreadyLocation[linePos] then output:MarkerDefine(12,SC_MARK_FULLRECT) output:MarkerSetBack(12,colour_parse('vYellow')) if active_already then output:MarkerDelete(active_already+funcLinestart,12) end active_already=alreadyLocation[linePos] output:MarkerAdd(active_already+funcLinestart,12) end if active_before2 then output:MarkerDelete(active_before2+funcLinestart-1,9) active_before2=nil end if active_before1 then output:MarkerDelete(active_before1+funcLinestart-1,10) active_before2=active_before1 output:MarkerDefine(9,SC_MARK_FULLRECT) output:MarkerSetBack(9,colour_parse('vPink')) output:MarkerAdd(active_before2+funcLinestart-1,9) end if active_now then output:MarkerDelete(active_now+funcLinestart-1,11) active_before1=active_now output:MarkerDefine(10,SC_MARK_FULLRECT) output:MarkerSetBack(10,colour_parse('vGreen')) output:MarkerAdd(active_before1+funcLinestart-1,10) end output:MarkerDefine(11,SC_MARK_FULLRECT) output:MarkerSetBack(11,colour_parse('vBlue')) active_now=linePos output:MarkerAdd(active_now+funcLinestart-1,11) return true elseif editor.Focus and sta=='functree' then local cls,func=classAndFunction() functionTree(cls,func,'click') return true end return false end) dir_cmd='dir /b /s /a:-d ' function AnalysisFiles() for i, dirname in pairs(analysis) do funcTreeDirectory=dirname local FilePathTable={} classTable={} classTable[0]={} classTable[0].memS={} local content = scite_Popen(dir_cmd..'"'..dirname..'"') for line in content:lines() do local filePath=gsub(line,'\\','/') --print('@@'..filePath) local _,val for path, var in pairs(not_analysis) do --print('=='..path) _,_,val = find(filePath,path,0,true) if _ then break end end if not _ then FilePathTable[line]={dirname,true,} --print ('--'..line) end end content:close() local remainFiles={} for filename,flag in pairs(FilePathTable) do local isHead=string.match(filename, "^(.*%.[hH])$") if isHead then scite.Open(filename) local fList=ParseFile() for k, name in pairs(fList) do table.insert(allFuncList, name) end scite.MenuCommand(IDM_CLOSE) else table.insert(remainFiles, filename) end end for i, filename in pairs(remainFiles) do scite.Open(filename) local fList=ParseFile() for k, name in pairs(fList) do table.insert(allFuncList, name) end scite.MenuCommand(IDM_CLOSE) end funcPath[dirname.."/functree"]=classTable end for dirname,clsTable in pairs(funcPath) do local f = io.open(dirname, "w") if not f then return false end for cls,member in pairs(clsTable) do local line=cls..":".."m"..":" for var,typ in pairs(member.memS) do line=line..var.."="..typ.."," end f:write(line..'\n') --[[ if member.otherMemS then line=cls..":".."o"..":" for var,typ in pairs(member.otherMemS) do line=line..var.."="..typ.."," end f:write(line..'\n') end ]]-- if member.funcS then for func,property in pairs(member.funcS) do line=cls..":".."f"..":" line=line..property.name..","..property.path..","..property.lineS..","..property.lineE..":" for i,funcs in pairs(property.funcS) do line=line..funcs[1]..","..funcs[2]..","..funcs[3]..";" end f:write(line..'\n') end end end f:close() end print('Analysis Finished') end function AllFunctionTree() --[[ remove_tree() output:BeginUndoAction() print("------------------------------------") func_pos_start=output.CurrentPos indent_var=1 for k, name in pairs(allFuncList) do if classTable[ name[1] ].funcS[name[2] ].root == 1 then recursion_func={} local parent='' if name[1]~=0 then parent=name[1]..'::' end print('=='..parent..name[2]) local linePos= output:LineFromPosition(output.CurrentPos) local path=classTable[ name[1] ].funcS[name[2] ].path local line=classTable[name[1] ].funcS[name[2] ].lineS location[linePos]={path,line} print_func(name) end end func_pos_end=output.CurrentPos output:EndUndoAction() ]]-- end function allReference() local cls,func=classAndFunction() print("--all reference for"..":"..cls.."::"..func) for clsName, member in pairs(classTable) do if member.funcS then for funcName, property in pairs(member.funcS) do for i,funcs in pairs(property.funcS) do if cls==funcs[1] and func== funcs[2] then print(funcTreeDirectory..'\\'..property.path..":"..(funcs[3]+1)..":"..cls.."::"..func) end end end end end --functionTree(nil,nil,'oneFile') end function localTree() local cls,func=classAndFunction() functionTree(cls,func,'command') --functionTree(nil,nil,'oneFile') end --stat=click,command,all,oneFile function functionTree(className,funcName,stat) remove_tree() --fucTable={} --classList={} local fList={} rootFile={} local doParseFlag=false local funcTable={} if stat=='click' or stat=='command' then if #allFuncList == 0 then doParseFlag=true else funcTable=allFuncList doParseFlag=false end elseif stat=='oneFile' then doParseFlag=true elseif stat=='all' then fList=allFuncList doParseFlag=false end if doParseFlag then funcTreeDirectory="" ParseFile() local sourceFilename = props["FilePath"] local ctagsFilename = sourceFilename .. '.ctags' local makeCtagsCommand = '""'.. lua_Path() ..'/ctags" --fields=kn -u -f ' .. ctagsFilename .. ' ' .. sourceFilename ..' && type '..ctagsFilename..'"' local f = scite_Popen(makeCtagsCommand) for line in f:lines() do if not isCommentLine(line) then local cls,func=getLine(line) if func.Type=='f' then table.insert(funcTable, {cls,func.name}) end end end f:close() os.remove(ctagsFilename) end if stat=='click' or stat=='command' then for k, name in pairs(funcTable) do local same=false if className then if className == name[1] and funcName == name[2] then same=true end else if funcName == name[2] then same=true end end if same then fList={} table.insert(fList, {className,funcName}) break end end elseif doParseFlag then fList=funcTable end for k, name in pairs(fList) do if not rootFile[name[1]] then rootFile[name[1]]={} end rootFile[name[1]][name[2]]=1 end for k, name in pairs(fList) do recursion_func={} recursion_func[name[1]]={} recursion_func[name[1]][name[2]]=1 isRootFile(classTable[name[1]].funcS[name[2]].funcS) end location={} output:BeginUndoAction() func_pos_start=output.Length funcLinestart=output:LineFromPosition(func_pos_start) print("------------------------------------") indent_var=1 alreadyOutput_func={} for k, name in pairs(fList) do if rootFile[name[1]][name[2]] == 1 then recursion_func={} local parent='' if name[1]~=0 then parent=name[1]..'::' end print('=='..parent..name[2]) local linePos= output:LineFromPosition(output.CurrentPos)-funcLinestart local path=classTable[name[1]].funcS[name[2]].path local line=classTable[name[1]].funcS[name[2]].lineS location[linePos]={path,line} print_func(name) end end func_pos_end=output.CurrentPos output:EndUndoAction() end function isRootFile(fList) for k, name in pairs(fList) do if recursion_func[name[1]] and recursion_func[name[1]][name[2]]==1 then recursion_func[name[1]][name[2]]=0 return end if rootFile[name[1]] and rootFile[name[1]][name[2]] then rootFile[name[1]][name[2]]=0 end if not recursion_func[name[1]] then recursion_func[name[1]]={} end recursion_func[name[1]][name[2]]=1 if classTable[name[1]] and classTable[name[1]].funcS and classTable[name[1]].funcS[name[2]] and classTable[name[1]].funcS[name[2]].funcS then isRootFile(classTable[name[1]].funcS[name[2]].funcS) end end end function ParseFile(option) local fucList={} local fucList2={} editor:Colourise(0,-1) local sourceFilename = props["FilePath"] local ctagsFilename = sourceFilename .. '.ctags' local makeCtagsCommand = '""'.. lua_Path() ..'/ctags" --fields=kn -u -f ' .. ctagsFilename .. ' ' .. sourceFilename ..' && type '..ctagsFilename..'"' local f = scite_Popen(makeCtagsCommand) local funcName_old local isCls=nil local clsName=nil for line in f:lines() do if not isCommentLine(line) then --print(getFunctionName(line)) local cls,func=getLine(line) if funcName_old then classTable[funcName_old[1]].funcS[funcName_old[2]].lineE=func.lineS funcName_old=nil end if func.Type=='c' then isCls=true clsName=func.name if not classTable[clsName] then classTable[clsName] ={} classTable[clsName].funcS={} end classTable[clsName].memS={} elseif func.Type=='m' then if isCls then classTable[clsName].memS[func.name]=cls end elseif func.Type=='d' then elseif func.Type=='v' then isCls=nil --classTable[0].memS[func.name]=cls elseif func.Type=='f' then isCls=nil local set_func=nil if classTable[cls] then if func.Type=='f' then if not classTable[cls].funcS then set_func=true classTable[cls].funcS={} elseif not classTable[cls].funcS[func.name] then set_func=true end end elseif func.Type=='f' then classTable[cls]={} classTable[cls].funcS={} set_func=true end if set_func then classTable[cls].funcS[func.name]=func --table.insert(classTable[cls].funcS[func.name], func) table.insert(fucList, {cls,func.name,func.lineS}) funcName_old={cls,func.name} end table.insert(fucList2, {cls,func.name}) else isCls=nil end end end f:close() os.remove(ctagsFilename) if option== 'cls' then local classFuncList={} ParseName=sourceFilename for k, name in pairs(fucList2) do local startPos=editor:PositionFromLine(classTable[name[1]].funcS[name[2]].lineS-1) local endPos if classTable[name[1]].funcS[name[2]].lineE==0 then endPos=editor.TextLength else endPos=editor.LineEndPosition[classTable[name[1]].funcS[name[2]].lineE-1] end table.insert(classFuncList, {name[1],name[2],startPos,endPos}) end return classFuncList end for k, name in pairs(fucList) do --print(name..fucTable[name].num) Parse(name) end return fucList end function getLine(line) local t = splitCtagsLine(line) local functionName = t[1] local cls=string.match(t[3], "([%w_]+)%s*::\s*~?[%w_]+%s*%(") if not cls then cls=0 end local funType = t[4] if funType == 'm' or funType == 'v' then cls=string.match(t[3], "([%w_]+)[^%w_]+[%w_]+") end --exg line:6646 local filePath=props['FilePath'] if not funcTreeDirectory then funcTreeDirectory="" end local dirLen=funcTreeDirectory:len() if dirLen >0 then filePath="."..filePath:sub(dirLen+1) end local lineNumber = string.sub(t[5], 6, #t[5]) return cls,{name=functionName,root=1,Type=funType,path=filePath,lineS=tonumber(lineNumber),lineE=0,funcS={} } end function Parse(name) local cls=name[1] local func_name=name[2] if notRecursion_func[func_name] then return end if classTable[cls].funcS[func_name].lineE == 0 then pos_end=editor.TextLength else pos_end=editor:PositionFromLine(classTable[cls].funcS[func_name].lineE-1) end local next_s local next_e=editor.LineEndPosition[classTable[cls].funcS[func_name].lineS-1] next_s,next_e = editor:findtext('\\w+\\s*(',SCFIND_MATCHCASE+SCFIND_REGEXP,next_e) while next_e and next_e < pos_end do local style = editor.StyleAt[next_s] if style==SCE_C_IDENTIFIER then style = editor.StyleAt[next_e-1] if style == SCE_C_OPERATOR then --local sel = editor:textrange(next_s,next_e) local funcProperty=getFunctionProperty(next_s,next_e) local parent_type=funcProperty[1] local parent=funcProperty[2] local func=funcProperty[3] if not exclude_func[func] then if not parent_type then if not parent then if classTable[cls].funcS[func] then parent_type=cls else parent_type=0 end else if cls ~=0 then if classTable[cls].memS then parent_type=classTable[cls].memS[parent] end if not parent_type then if classTable[cls].otherMemS then parent_type=classTable[cls].otherMemS[parent] end end else if classTable[0].otherMemS and classTable[0].otherMemS[func_name] then parent_type=classTable[0].otherMemS[func_name][parent] end end if not parent_type then parent_type=research_type(parent) if cls ~=0 then if not classTable[cls].otherMemS then classTable[cls].otherMemS={} classTable[cls].otherMemS[parent]=parent_type end else if not classTable[0].otherMemS then classTable[0].otherMemS={} end if not classTable[0].otherMemS[func_name] then classTable[0].otherMemS[func_name]={} classTable[0].otherMemS[func_name][parent]=parent_type end end end end end local lineNum=editor:LineFromPosition(next_e) table.insert(classTable[cls].funcS[func_name].funcS, {parent_type,func,lineNum}) if classTable[parent_type] and classTable[parent_type].funcS and classTable[parent_type].funcS[func] then classTable[parent_type].funcS[func].root=0 end end end end next_s,next_e = editor:findtext('\\w+\\s*(',SCFIND_MATCHCASE+SCFIND_REGEXP,next_e) end end function print_func(func) local cls=func[1] local func_name=func[2] if recursion_func[cls] and recursion_func[cls][func_name] == 1 then indent_var=indent_var+1 line_pos[indent_var]=0 local inde=print_inde() print(inde..'|---'..'★Recursive') indent_var=indent_var-1 return end if not recursion_func[cls] then recursion_func[cls]={} end recursion_func[cls][func_name]=1 indent_var=indent_var+1 --local inde=string.rep("\t", indent_var) if classTable[cls] and classTable[cls].funcS and classTable[cls].funcS[func_name] then local tab_size=#classTable[cls].funcS[func_name].funcS if noPrintAlreadyOutput and tab_size>0 and alreadyOutput_func[cls] and alreadyOutput_func[cls][func_name] then line_pos[indent_var]=0 local inde=print_inde() print(inde..'|---'..'◎Already') recursion_func[cls][func_name]=0 indent_var=indent_var-1 local linePos= output:LineFromPosition(output.CurrentPos)-funcLinestart alreadyLocation[linePos]=alreadyOutput_func[cls][func_name] return end local alreadyLinePos= output:LineFromPosition(output.CurrentPos)-funcLinestart for k, name in pairs(classTable[cls].funcS[func_name].funcS) do if k==tab_size then line_pos[indent_var]=0 else line_pos[indent_var]=1 end local inde=print_inde() --print(inde..'|---'..name) local parent='' if name[1]~=0 then parent=name[1]..'::' end print(inde..'|---'..parent..name[2]) local linePos= output:LineFromPosition(output.CurrentPos)-funcLinestart local path=classTable[cls].funcS[func_name].path local line=name[3] location[linePos]={path,line} if name[1]~='?' and classTable[name[1]] and classTable[name[1]].funcS and classTable[name[1]].funcS[name[2]] then classTable[name[1]].funcS[name[2]].root = 0 end print_func(name) end if tab_size==0 then line_pos[indent_var]=0 local inde=print_inde() print(inde..'|---'..'(...)') local linePos= output:LineFromPosition(output.CurrentPos)-funcLinestart local path=classTable[cls].funcS[func_name].path local line=classTable[cls].funcS[func_name].lineS location[linePos]={path,line} else if not alreadyOutput_func[cls] then alreadyOutput_func[cls]={} end alreadyOutput_func[cls][func_name]=alreadyLinePos local inde=print_inde() print(inde) end end indent_var=indent_var-1 recursion_func[cls][func_name]=0 end function print_inde() local inde="" for i = 1,indent_var-1, 1 do if line_pos[i]==0 then inde=inde.." " else inde=inde.."| " end end return inde end function research_type(var) local pattern={ '\\w+[ *]+', '\\w+\\s*<.+>\\s*' } local style=SCE_C_OPERATOR local s,e for k, name in pairs(pattern) do local pat=name..var e=1 while e and style~=SCE_C_IDENTIFIER do s,e = editor:findtext(pat,SCFIND_MATCHCASE+SCFIND_REGEXP,e) if s then style= editor.StyleAt[s] end end if e then local def = editor:textrange(s,e) return string.match(def, "([%w_]+)[^%w_]+") end end return '?' end --[[ new class() class::func() point->func() ]]-- function getFunctionProperty(next_s,next_e) local parent_typ=nil local sel = editor:textrange(next_s,next_e) local func=string.match(sel, "([%w_]+)%s*%(") if not func then func=sel end local lineNum=editor:LineFromPosition(next_s) local pos_s=editor:PositionFromLine(lineNum) sel = editor:textrange(pos_s,next_e) local pattern='([%w_]+)([^%w_]+)'..func local parent,typ=string.match(sel, pattern) if parent then typ=string.match(typ, "(%S+)") if not typ then if parent == 'new' then parent_typ=func parent=nil elseif parent == 'return' then parent_typ=nil parent=nil else parent_typ=0 parent=nil end elseif typ == '::' then parent_typ=parent elseif typ =='.' or typ =='->' then parent_typ=nil else parent=nil end end return {parent_typ,parent,func} end --/////////////////////////////////////////////////////////////////////////////////////////////////////////////// funcTree_prompt='(function_tree)' local function functionTree_help() print("----[help for function tree]-----") print("clear -------clear all setting") print("del -------delete function tree") print("include path -------add directory for analysis files") print("except path -------add directory for unanalysis files") print("repeat [on|off] ------print function already outputed or not") print("status -------list all setting") print("read -------- running analysis ") print("tree [function] -------- ") print("[exit|quit] -- for exit function tree") print("-------------------------------") end local functree_status='dead' scite_OnOutputLine (function (line) local line = strip_prompt(line) local dir=string.match(line, "^%S+%s+(%S.+)$") local _,_,val = find(line,'^%s*([^=%s]+)%s*') local sta=command_status() if sta=='dead' then if val == 'functree' then sta=command_status(val) set_prompt(funcTree_prompt) end elseif sta=='functree' then if val == 'exit' or val == 'quit' then command_status('dead') return true elseif val == 'del' then remove_tree() elseif val == 'clear' then remove_tree() classTable={} classTable[0]={} classTable[0].memS={} allFuncList={} analysis={} not_analysis={} elseif val == 'repeat' then if dir == 'on' then noPrintAlreadyOutput=false else noPrintAlreadyOutput=true end elseif val == 'help' then functionTree_help() elseif val == 'status' then print("-------------------------------") if #allFuncList == 0 then print("-status:analysing not yet finished") else print("-status:analysing already finished") end if noPrintAlreadyOutput then print("-repeat off") else print("-repeat on") end if #funcPath ~= 0 then print("-read file:") end for filename,tbl in pairs(funcPath) do print(filename) end if #analysis ~= 0 then print("-directories for anallysis:") end for i, dirname in pairs(analysis) do print(dirname) end print() if #not_analysis ~= 0 then print("-directories for not anallysis:") end for dirname,val in pairs(not_analysis) do print(dirname) end print("-------------------------------") elseif val == 'include' then local path=gsub(dir,'/','\\') local endChr=path:sub(-1) --print(endChr) if endChr=="\\" then path=path:sub(1,-2) --print(path) end table.insert(analysis,path) elseif val == 'except' then local path=gsub(dir,'\\','/') not_analysis[path]=true elseif val == 'read' then AnalysisFiles() elseif val == 'tree' then local FileDir=props['FileDir']:gsub('\\','/') local tree_dir=locatefunctree(FileDir, 'functree') classTable=funcPath[tree_dir..'/functree'] if dir then local cls,func=string.match(dir, "^([%w_]+)::([%w_]+)%s*$") if not cls then func=string.match(dir, "^([%w_]+)%s*$") end if not cls and not func then functionTree(nil,nil,'oneFile') elseif not cls and func then functionTree(0,func,'command') else functionTree(cls,func,'command') end else functionTree(nil,nil,'oneFile') end end else return false end if sta=='functree' then print_prompt() return true end return false end)