Does anyone know a way of listing all the variables used in a program by tab or class, I thought I had seen something on the forum previously but I cannot find. I try and use variable names that are memorable, but when you come back to complete a project after a few weeks, I tend to lose track of what variable names I have used.
@timber This might be close enough to what you’re after. Key in the project name and press go. You can include comments using the slider.
Project updated below
Updated version. Tap a project name and it will list the names. Tap again for another project.
-- code viewer
viewer.mode=STANDARD
function setup()
pasteboard.copy("")
project=""
textMode(CORNER)
font("Courier")
parameter.boolean("Include_Comments",false,setup1)
list()
end
function setup1()
tab,tab1={},{}
dy,per=0,0
comment=false
longComment=false
process()
end
function draw()
background(40,40,50)
fill(255)
if pasteboard.text~="" then
project=pasteboard.text
pasteboard.copy("")
setup1()
end
if lp==nil then
return
end
if #lp==0 then
text("Project not found... "..project,50,HEIGHT/2)
return
end
if dy==0 then
text(project,30,HEIGHT-30)
text("Nbr Count Name Entries "..#tab1,30,HEIGHT-70)
text("Scroll up/down",WIDTH/2+80,HEIGHT-30)
end
for a,b in pairs(tab1) do
text(string.format("%5d %5d %-s",a,tab[b],b),2,HEIGHT-80-a*20+dy)
end
end
function touched(t)
if t.state==CHANGED then
dy=dy+t.deltaY
if dy<0 then
dy=0
end
end
end
function list()
output.clear()
temp=listProjects()
for a,b in pairs(temp) do
print(b)
end
pasteboard.copy("")
end
function process()
str=""
project=string.gsub(project,"\
","")
lp=listProjectTabs(project)
if #lp==0 then
return
end
for a,b in pairs(lp) do
local rp=readProjectTab(project..":"..b)
str=str..rp
end
str1=""
proc()
end
function get4bytes(z)
v=string.sub(str,z,z)
v1=string.sub(str,z+1,z+1)
v2=string.sub(str,z+2,z+2)
v3=string.sub(str,z+3,z+3)
end
function checkComments()
if v=="\
" then
comment=false
end
if v=="-" and v1=="-" and v2=="[" and v3=="[" then
longComment=true
elseif longComment and v=="-" and v1=="-" and v2=="]" and v3=="]" then
longComment=false
elseif v=="-" and v1=="-" then
comment=true
end
if Include_Comments then
comment,longComment=false,false
end
end
function proc()
for z=1,string.len(str) do
get4bytes(z)
checkComments()
if comment or longComment then
-- ignore until end of comment
else
proc1()
end
end
proc2()
end
function proc1()
if v>="a" and v<="z" or v>="A" and v<="Z" then
per=0
str1=str1..v
elseif v>="0" and v<="9" then
per=0
str1=str1..v
elseif str1~="" and v=="_" then
per=0
str1=str1..v
elseif str1~="" and v=="'" then
per=0
str1=str1..v
elseif str1~="" and v=="." then
per=per+1
if per==2 then
per=0
str1=string.sub(str1,1,string.len(str1)-1)
if tab[str1]==nil then
tab[str1]=1
else
tab[str1]=tab[str1]+1
end
str1=""
else
str1=str1..v
end
elseif str1~="" then
per=0
local len=string.len(str1)
if string.sub(str1,len,len)=="." then
str1=string.sub(str1,1,len-1)
end
if string.sub(str1,len,len)=="'" then
str1=string.sub(str1,1,len-1)
end
if tab[str1]==nil then
tab[str1]=1
else
tab[str1]=tab[str1]+1
end
str1=""
else
str1=""
end
end
function proc2()
for a,b in pairs(tab) do
table.insert(tab1,a)
end
table.sort(tab1)
end
Here’s an updated version. It shows a list of all projects. You can tap on a project name and that will fill in the parameter project name. Then press Process for a list of names in that project. To view another, tap List of projects and select another name.
Updated code below
@dave1707 thank you, this will be a good starting point. I’ve not studied the code closely, but it looks like you create a list of tabs that make up the selected project and iterate through them. If that is the case, I could theoretically add another parameter to select only the tab I wanted to interrogate. I.e Select project → Select tab → Process. The reason for this would be to differentiate between variables with the same name but in different classes.
I think this might be better done with string patterns, but “if it works do it”.
@RonJeffries Just curious, how would string patterns work.
Here’s a version that gives the counts by tab name.
-- code viewer, breakdown by tabs
viewer.mode=STANDARD
function setup()
pasteboard.copy("")
project=""
textMode(CORNER)
font("Courier")
parameter.boolean("Include_Comments",false,setup1)
list()
end
function setup1()
tab,tab1,tab2={},{},{}
dy,per=0,0
comment=false
longComment=false
process()
end
function draw()
background(40,40,50)
fill(255)
if pasteboard.text~="" then
project=pasteboard.text
pasteboard.copy("")
setup1()
end
if lp==nil then
return
end
if #lp==0 then
text("Project not found... "..project,50,HEIGHT/2)
return
end
if dy==0 then
text(project,30,HEIGHT-30)
text("Nbr Count Name < tab >",30,HEIGHT-70)
text("Entries "..#tab1,WIDTH-200,HEIGHT-70)
text("Scroll up/down",WIDTH-200,HEIGHT-30)
end
for a,b in pairs(tab2) do
st,en=string.find(b,"#*",1,true)
str=string.sub(b,en+1)
text(string.format("%5d %-s",a,str),2,HEIGHT-80-a*20+dy)
end
end
function touched(t)
if t.state==CHANGED then
dy=dy+t.deltaY
if dy<0 then
dy=0
end
end
end
function list()
output.clear()
temp=listProjects()
for a,b in pairs(temp) do
print(b)
end
pasteboard.copy("")
end
function process()
str=""
project=string.gsub(project,"\
","")
lp=listProjectTabs(project)
if #lp==0 then
return
end
for a,b in pairs(lp) do
str=""
tabName=b
local rp=readProjectTab(project..":"..b)
str=str..rp
str1=""
proc()
end
table.sort(tab2)
end
function get4bytes(z)
v=string.sub(str,z,z)
v1=string.sub(str,z+1,z+1)
v2=string.sub(str,z+2,z+2)
v3=string.sub(str,z+3,z+3)
end
function checkComments()
if v=="\
" then
comment=false
end
if v=="-" and v1=="-" and v2=="[" and v3=="[" then
longComment=true
elseif longComment and v=="-" and v1=="-" and v2=="]" and v3=="]" then
longComment=false
elseif v=="-" and v1=="-" then
comment=true
end
if Include_Comments then
comment,longComment=false,false
end
end
function proc()
for z=1,string.len(str) do
get4bytes(z)
checkComments()
if comment or longComment then
-- ignore until end of comment
else
proc1()
end
end
proc2()
end
function proc1()
if v>="a" and v<="z" or v>="A" and v<="Z" then
per=0
str1=str1..v
elseif v>="0" and v<="9" then
per=0
str1=str1..v
elseif str1~="" and v=="_" then
per=0
str1=str1..v
elseif str1~="" and v=="'" then
per=0
str1=str1..v
elseif str1~="" and v=="." then
per=per+1
if per==2 then
per=0
str1=string.sub(str1,1,string.len(str1)-1)
if tab[str1]==nil then
tab[str1]=1
else
tab[str1]=tab[str1]+1
end
str1=""
else
str1=str1..v
end
elseif str1~="" then
per=0
local len=string.len(str1)
if string.sub(str1,len,len)=="." then
str1=string.sub(str1,1,len-1)
end
if string.sub(str1,len,len)=="'" then
str1=string.sub(str1,1,len-1)
end
str1=str1.." < "..tabName.." >"
if tab[str1]==nil then
tab[str1]=1
else
tab[str1]=tab[str1]+1
end
str1=""
else
str1=""
end
end
function proc2()
for a,b in pairs(tab) do
table.insert(tab1,a)
end
createTab2()
tab={}
end
function createTab2()
for a,b in pairs(tab) do
ss=string.format("%s#*%4d %-s",a,b,a)
table.insert(tab2,ss)
end
end
if i understand what your program does, it basically looks for a pattern of _, alpha and numbers in between punctuation and white space. so we’d express that as a pattern, something like
[%s\\+\\-\\*\\/]*([_%a][_%w]*)[%s\\+\\-\\*\\/]
-- not name name not name
hideous, yes, but once we get the pattern right, tabContents:gmatch(pattern) would return all the matches.
See my recent Codea Stats articles for examples of finding class and method definitions.
Trouble with patters is they are hard to write and read. but when the are applicable, they are mighty.
I might try to do this problem in an upcoming stats article. it’ll be a bear!
@RonJeffries i do patterns sometimes, but it seems to take forever to get it right. Probably the more you use it, the easier it becomes.
if it ever gets easy, I’ve not done it enough.
here’s a thing:
-- find
function setup()
s = readProjectTab("Main")
t = {}
for w in string.gmatch(s, "[_%a][_%w]*") do
table.insert(t,w)
end
table.sort(t)
w = ""
for _,word in ipairs(t) do
if word~= w then print(word) end
w = word
end
end
@RonJeffries That’s a start. If I add a=1234, it doesn’t find the 1234. Also, it splits up the commands that have a . in them (ie table.sort). There would probably have to be multiple gmatch commands to find each type of word, number, whatever.
why should it find 1234, that’s not a variable?
is table.sort one word? i’d think not …
i think i’d winnow out dups, then remove all the keywords.
and of course remove comments, which is hard but doable i think.
@RonJeffries Here’s a modification. It finds the number and counts everything. My original code doesn’t look for just variables, but everything that makes up the code. I’m not sure if patterns could do everything the way I’m doing it.
function setup()
s = readProjectTab("Main")
t = {}
for w in string.gmatch(s, "[%a%d]*") do
if t[w]==nil then
t[w]=1
else
t[w]=t[w]+1
end
end
a=1234
table.sort(t)
print("============")
for a,b in pairs(t) do
print(t[a].." = "..a)
end
end
misses _i, but easily fixed.
i prefer t[w] = (t[w] or 0) + 1
i’m not sure if patterns could do what yours does, not least because i don’t know what it does. it’d have to study it to know.
horses for courses, certainly.
i didn’t know that pasteboard trick. very cool.
@RonJeffries My code doesn’t catch the _i, but it does catch the i . Don’t know if that’s really important or not, but probably should for clarity. I’d like to redo the way I check things and separate them so I can have a comment showing what I’m trying to catch with each if .
The pasteboard code makes it easy to select projects from a list.
As for the t[w]= code, for me that’s not easily understandable. It saves code, but if I looked at it some time from now, I wouldn’t know what it was really doing.
ah. i’m used to it. old C programmer or something.
@dave1707 Thanks, the added tab reference is very useful.