你是不是有时候很困惑,需要实现一个功能, 只知道模糊概念或某个关键词,但不知道它具体在哪个库里实现?
要手动去遍历查看每个库,每个函数,是不是很麻烦?
这个工具,为此而生。
把代码文件放到 aardio\tools\ 目录下,在aardio右方工具里面就看到了,双击即可运行。
运行效果:
使用方法:
1、先更新数据(以后更新库后适当的更新一下数据)。3.0版用sqlite数据库代替access,开启事务,大大提高了保存速度,用我的破电脑测试,最快可达13秒。
2、输入关键词进行查找。可以查函数名称、常量名称(=左侧的部分),可以查函数描述、常量值(=右边的部分)。本程序采用IDE.doc进行数据提取分析,与官方库函数文档提取的资料完全一致。
3、资料内容分为“函数”和“常量”两种类型。“函数”包含文件名、函数所属对象、函数名、函数描述四部分。“常量”包含文件名、常量名、常量值三部分。
4、关键词可以写多个,多个关键词用分号、逗号、空格分隔。关键词以@开头表示全部内容作为一个关键词进行搜索。可以指定多个关键词是属于“与”还是“或”关系。“与”是一个函数必须同时包含所有关键词,“或”是一个函数包含多个关键词中的一个即可。
5、部分识别不准确的库文件,只需要用aardio打开,重新保存一下,再重新更新即可。此法对于官方《库函数文档》同样有效。
6、加入了内核函数库(global)支持。
//库函数搜索 3.0
import fonts.fontAwesome;
import win.ui;
import win.ui.atom;
import ide;
/*DSG{{*/
mainForm = win.form(text="aardio - 库函数关键词搜索 v3.0 光庆·程序·在线 chengxu.online";right=1056;bottom=784;bgcolor=16777215;exmode="none";mode="popup";parent=hwndStatusBar)
mainForm.add(
btnRefresh={cls="plus";text='\uF021 更新';left=686;top=735;right=805;bottom=776;bgcolor=32768;db=1;dl=1;font=LOGFONT(h=-16;name='FontAwesome');notify=1;z=2};
btnSearch={cls="plus";text='\uF002 搜索';left=550;top=735;right=673;bottom=776;bgcolor=-37376;db=1;dl=1;font=LOGFONT(h=-16;name='FontAwesome');notify=1;z=4};
checkbox={cls="checkbox";text="搜函数名、常量名";left=245;top=700;right=403;bottom=722;bgcolor=16777215;checked=1;db=1;dl=1;font=LOGFONT(h=-16);z=6};
checkbox2={cls="checkbox";text="搜函数描述、常量值";left=408;top=700;right=584;bottom=722;bgcolor=16777215;checked=1;db=1;dl=1;font=LOGFONT(h=-16);z=7};
checkbox3={cls="checkbox";text="搜函数对象名";left=590;top=700;right=715;bottom=722;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);z=11};
checkbox4={cls="checkbox";text="搜文件名";left=717;top=700;right=815;bottom=722;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);z=12};
checkbox5={cls="checkbox";text="查函数";left=10;top=700;right=90;bottom=722;bgcolor=16777215;checked=1;color=255;db=1;dl=1;font=LOGFONT(h=-16);z=13};
checkbox6={cls="checkbox";text="查常量";left=89;top=700;right=169;bottom=722;bgcolor=16777215;checked=1;color=8388736;db=1;dl=1;font=LOGFONT(h=-16);z=14};
edit={cls="richedit";left=9;top=8;right=1048;bottom=669;bgcolor=0;color=15793151;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(h=-16);multiline=1;readonly=1;vscroll=1;z=3};
editWord={cls="edit";left=9;top=742;right=484;bottom=772;autohscroll=false;autovscroll=false;clipch=1;db=1;dl=1;edge=1;font=LOGFONT(h=-16);tabstop=1;z=1};
plus2={cls="plus";left=814;top=736;right=1053;bottom=771;db=1;dl=1;foreRepeat="stretch";notify=1;z=8};
radiobutton={cls="radiobutton";text="与";left=490;top=736;right=537;bottom=757;bgcolor=16777215;checked=1;db=1;dl=1;font=LOGFONT(h=-16);z=9};
radiobutton2={cls="radiobutton";text="或";left=490;top=756;right=537;bottom=777;bgcolor=16777215;db=1;dl=1;font=LOGFONT(h=-16);z=10};
static={cls="static";left=10;top=673;right=452;bottom=698;db=1;dl=1;font=LOGFONT(h=-16);transparent=1;z=5}
)
/*}}*/
var skin = {
background={
active=0xFFA6B7FE;
default=0xFF006EFF;
hover=0x9E006EFF
}
}
mainForm.btnSearch.skin(skin)
mainForm.btnRefresh.skin(skin)
import process.mutex;
var mutex = process.mutex("godking-libfuncs-search")
if( mutex.conflict ){
win.msgbox("已经运行")
return;}
mainForm.show()
mainForm.edit.wrap=true
mainForm.editWord.setCueBannerText("多个关键词用分号、逗号、空格分隔。以@开头视为一个关键词。")
//定义函数分析线程
var getfuncs = function(fullpath){
if !#fullpath return ;
if thread.get("stop") return; // 停止
//创建共享表
import thread.table
var funcs = thread.table("funcs")
//分析数据
import ide.doc
var f = ide.doc(fullpath)
//添加函数
var sections = table.keys(f.sections)
for(i=1;#sections;1){
var keys = ..table.keys(f["sections"][sections[i]])
for(j=1;#keys;1){
if thread.get("stop") return;
funcs.push({fullpath=fullpath,type="section",section=sections[i],key=keys[j],value=f["sections"][sections[i]][keys[j]]})
}
}
//添加常量
var keys = ..table.keys(f["define"])
for(j=1;#keys;1){
if thread.get("stop") return;
funcs.push({fullpath=fullpath,type="define",section="",key=keys[j],value=f["define"][keys[j]]})
}
}
//定义函数保存线程
var savefuncs = function(){
import sqlite
import thread.table
var db = sqlite("/funcs.db")
var funcs = thread.table("funcs")
var savecount = 0;
db.beginTrans()
var cmd = db.prepare("INSERT INTO funcs([fullpath],[type],[section],[key],[value]) VALUES(@fullpath,@type,@section,@key,@value)")
while !thread.get("stop") {
var func = funcs.pop()
if func{
cmd.step(
fullpath=func["fullpath"],
type=func["type"],
section=func["section"],
key=func["key"],
value=func["value"]
)
savecount++;
thread.set("savecount",savecount)
thread.set("restcount",funcs.count())
}
}
cmd.finalize();
db.commitTrans()
db.close()
}
mainForm.btnRefresh.oncommand = function( id,event ){
//判断更新还是停止
if mainForm.btnRefresh.text='\uF021 更新'{
if ..win.msgbox("确定要更新吗?","提示",1/*_MB_OKCANCEL*/,mainForm.hwnd)!=1{
return ;
}
thread.set("stop", false)
mainForm.btnRefresh.text='\uF021 停止'
}else{
thread.set("stop", true)
mainForm.btnRefresh.text='\uF021 更新'
return ;
}
//防止数据库错误,先删除再重建
io.remove("/funcs.db")
if io.exist("/funcs.db") ..win.msgbox("删除原数据库失败")
//创建数据库
import sqlite
var db = sqlite("/funcs.db")
db.exec("CREATE TABLE [funcs]([fullpath],[type],[section],[key],[value]);")
if !db.existsTable("funcs") { ..win.msgbox("创建表失败!") }
db.close()
//搜索库文件
import fsys
var files = {"global"}
fsys.enum("~/lib/", "*.aardio",
function(dir,filename,fullpath,findData){
if(filename){
..table.push(files,fullpath)
}
}
,
);
//初始化函数共享表、线程变量
import thread.table
thread.table("funcs").clear()
thread.set("savecount",0)
thread.set("restcount",0)
//启动函数保存线程待命(监控函数共享表)
thread.create(savefuncs)
//创建线程管理器
import thread.manage
var ts = thread.manage()
//启动线程管理器任务,进行函数分析,加入函数共享表
var count = 0
var tick = time.tick()
for(i=1;#files;1){
ts.createLite(getfuncs,files[i])
count++;
mainForm.edit.text = "正在分析:" ++ ..math.round(count*100/#files,1) ++ "% >> " ++ ..math.floor((time.tick()-tick)/1000) ++ "s >>" ++ files[i]
mainForm.static.text = "已保存数量:" ++ thread.get("savecount") ++ " 剩余数量:" ++ thread.get("restcount")
while(thread.get("restcount")>3000){ //防止数据太多导致保存速度变慢
win.delay(100)
}
if thread.get("stop") {
ts.quitMessage()
return false;
}
}
mainForm.edit.text = "已分析完毕,正在等待保存中…………"
//检测函数共享表中剩余函数数量
ts.waitClose()
while(thread.get("restcount")>0){
mainForm.static.text = "保存数量:" ++ thread.get("savecount") ++ " 剩余数量:" ++ thread.get("restcount")
win.delay(100)
}
mainForm.static.text = "保存数量:" ++ thread.get("savecount") ++ " 剩余数量:" ++ thread.get("restcount")
//结束搜索
thread.set("stop", true)
mainForm.btnRefresh.text='\uF021 更新'
mainForm.edit.text = "更新完毕,共" ++ #files++"个文件," ++ thread.get("savecount") ++ "个函数常量,耗时:" ++ ..math.floor((time.tick()-tick)/1000) ++ "秒!"
}
mainForm.btnSearch.oncommand = function(id,event){
//关键信息提示
mainForm.edit.text=""
if !#mainForm.editWord.text {
mainForm.edit.text = "请填写函数关键词!"
return ;
}
if !(mainForm.checkbox.checked:mainForm.checkbox2.checked:mainForm.checkbox3.checked:mainForm.checkbox4.checked) {
mainForm.edit.text = "请先选择搜索项!"
return ;
}
if !(mainForm.checkbox5.checked:mainForm.checkbox6.checked) {
mainForm.edit.text = "请先选择搜索范围!"
return ;
}
//处理关键词
var t = mainForm.editWord.text
if t[[1]]="@" {
t = {..string.right(t,-2)}
}else{
t = ..string.replace(t,"@;",";")
t = ..string.replace(t,"@,",";")
t = ..string.replace(t,"@,",";")
t = ..string.replace(t,"@ ",";")
t = ..string.split(t,";")
}
//根据关键词,定义查询条件模板
var Tsql = " ("
for(i=1;#t;1){
Tsql += " [Tsql] like '%" + t[i] + "%'"
if i<#t{
if mainForm.radiobutton.checked {
Tsql += " and"
}else {
Tsql += " or"
}
}
}
Tsql += ")"
//根据模板,定义四个查询类型语句
var fsql = ..string.replace(Tsql,"@[Tsql]","[key]")
var csql = ..string.replace(Tsql,"@[Tsql]","[value]")
var osql = ..string.replace(Tsql,"@[Tsql]","[section]")
var psql = ..string.replace(Tsql,"@[Tsql]","[fullpath]")
//定义最终查询语句
var sql = "SELECT * FROM [funcs] where"
if !mainForm.checkbox5.checked { sql += " [type]='define' and" }
if !mainForm.checkbox6.checked { sql += " [type]='section' and" }
sql += "(1<>1"
if mainForm.checkbox.checked { sql += " or" + fsql }
if mainForm.checkbox2.checked { sql += " or" + csql }
if mainForm.checkbox3.checked { sql += " or" + osql }
if mainForm.checkbox4.checked { sql += " or" + psql }
sql += ")"
//开始查询
import sqlite
var db = sqlite("/funcs.db")
var data = db.getTable(sql)
db.close()
//显示数据
var t = ""
for(i=1;#data>100?100:#data;1){
if data[i]["type"]="define"{
t += i + " " + data[i]["key"] +" = " + data[i]["value"] + '\r\n\r\n';
} else {
t += i++": " +data[i]["key"] + '\r\n'
t += data[i]["fullpath"]+ '\r\n'
t += data[i]["value"] + '\r\n\r\n'
}
}
if #t{
mainForm.edit.text = t + "查询完毕!"
if #data>100 mainForm.edit.log('\n\n查询结果:' ++ #data ++ '条,数据太多,参考意义不大,只显示前100条。\n为更好的实现搜索效果,建议您使用多关键词,提高查询精确度。')
} else { mainForm.edit.text = "查无记录!" }
}
mainForm.onClose = function(hwnd,message,wParam,lParam){
thread.set("stop", true)
win.quitMessage()
}
import inet.http
mainForm.plus2.foreground = "http://chengxu.online/images/banner.gif"
mainForm.plus2.oncommand = function(id,event){
import process
process.explore("http://chengxu.online")
}
mainForm.editWord.onOk = function(){
mainForm.btnSearch.oncommand()
return true;
}
win.loopMessage();