-
Notifications
You must be signed in to change notification settings - Fork 0
/
findcmd.ado
221 lines (176 loc) · 5.98 KB
/
findcmd.ado
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
*! Version 1.0.0 Mehrab Ali 25Nov2020
* change of delimit and make lines - done
* Comment block "/*" - done
* inside comment block /* */ - done
* Drop /// from second line - done
* Program define drop and drop from install list - done
* : after capture qui etc - done
* if `dataprep' do "${dos}/01_data.do" - This is tricky.
/* The current commands can only consider command only if the exp followed by if command is one word */
* Include and do files/ado files - tricky
version 12.0
cap pr drop findcmd
prog def findcmd, rclass
syntax using/
qui {
tempfile currentdata
save `currentdata', emptyok
local path `"`c(sysdir_plus)'"'
insheet using "`path'/f/findcmd_commands.txt", clear
levelsof v1, loc(bcmdlist) clean
import delim using "`using'", stringcols(_all) clear
* Split and find out the commands
g command = ""
ds command, not
foreach var of varlist `r(varlist)' {
replace command = command + `var' + " "
}
replace command = subinstr(command, ":", "", .) // Get rid of : after commands
replace command = regexr(command, "\/\*(.)+\*\/", "") // Get rid of in line comments
replace command = substr(command, 1, strpos(command, "// ") - 2) if strpos(command, "//") & !strpos(command, "///") // Get rid of in line comments
split command, gen(var)
replace var1 = trim(var1)
replace var1 = trim(var2) if inlist(var1, "cap", "capture", "qui", "quitely", "n", "noi", "noisily")
* Comment block
gen start = 1 if regex(var1, "^\/\*")
gen end = 1 if regex(command, "\*\/")
g startcount = .
g endcount = .
loc i = 1
forval x=1/`=_N' {
if start[`x']==1 {
replace startcount = `i' in `x'
loc ++i
}
}
loc i = 1
forval x=1/`=_N' {
if end[`x']==1 {
replace endcount = `i' in `x'
loc ++i
}
}
gen grp_var = .
gen begin_row = .
gen begin_fieldname = .
gen end_row = .
gen end_fieldname = .
gen _sn = _n
levelsof _sn if start==1, loc (_sns) clean
foreach _sn in `_sns' {
loc b 1
loc e 0
loc curr_sn `_sn'
loc stop 0
while `stop' == 0 {
loc ++curr_sn
if end[`curr_sn']==1 {
loc ++e
if `b' == `e' {
loc end `curr_sn'
loc stop 1
}
}
else {
replace grp_var = 1 in `curr_sn'
if start[`curr_sn']==1 loc ++b
}
}
replace begin_row = _sn[`_sn'] in `_sn'
replace begin_fieldname = startcount[`_sn'] in `_sn'
replace end_row = _sn[`end'] in `_sn'
replace end_fieldname = endcount[`end'] in `_sn'
}
replace grp_var = 0 if missing(grp_var)
* Change of delimit
replace var1 = "#delimit" if inlist(var1, "#d", "#delim")
* Create identifier for the block
gen delim = ""
replace delim = ";" if var1 == "#delimit" & var2==";"
replace delim = "cr" if var1 == "#delimit" & var2=="cr"
replace delim = delim[_n-1] if mi(delim)
* Add the in line commands
split command, p(";") gen(spvar)
if `r(nvars)'>1 {
ds spvar*
forval i = 2(2)1000 {
cap confirm var spvar`i'
if _rc {
continue, break
}
split spvar`i', gen(spcmd`i'_)
}
ds spcmd*_1
foreach var in `r(varlist)' {
levelsof `var', clean loc(`var'list)
foreach cmd of local `var'list {
set obs `=_N+1'
replace var1 = "`cmd'" in `=_N'
}
}
}
* Drop the delimit change line
drop if inlist(var1, "#d", "#delimit", "#delim")
* Drop unnecessary lines
drop if inlist(var1, "{", "}", "//", "") | delim==";" | grp_var==1 | start==1 | end==1 ///
| regex(command[_n-1], "///")==1 | regex(var1, "^(\*)") ==1
* In line cmd combining with if
gen varif = ""
replace varif = trim(command) if var1=="if" & !regexm(command, "{")
cap split varif, gen(cmdif)
cap conf v cmdif3
if !_rc {
levelsof cmdif3, clean loc(ifs)
foreach ifcmd of local ifs {
set obs `=_N+1'
replace var1 = "`ifcmd'" in `=_N'
}
}
* Clean the cmd list
replace var1 = subinstr(var1, ",", "", .)
replace var1 = subinstr(var1, "+", "", .)
replace var1 = subinstr(var1, "=", "", .)
* User defined programs
replace var1 = "program" if inlist(var1, "pr", "prog")
replace var2 = "define" if var1=="program" & !inlist(var2, "dir", "di", "drop", "list", "l")
count if var1 == "program" & var2 == "define"
if r(N)>0 {
split command if var1 == "program" & var2 == "define", gen (userp)
cap replace userp3 = "end" if var1=="end"
replace userp3 = userp3[_n-1] if mi(userp3)
levelsof userp3 if userp3!="end", clean loc(defined)
return loc defined = "`defined'"
drop if (userp3 != "end" & !mi(userp3)) | var1 == "end"
}
* Bring in the cmd list
levelsof var1, clean loc(cmdlist)
loc notfound : list cmdlist - bcmdlist
loc usercmd : list notfound - defined
loc abuiltin : list cmdlist - usercmd
loc abuiltin : list abuiltin - defined
return scalar builtin_N = wordcount("`abuiltin'")
return scalar usercmd_N = wordcount("`usercmd'")
return scalar defined_N = wordcount("`defined'")
return loc builtin "`abuiltin'"
return loc usercmd "`usercmd'"
* Listing down do and ado included
replace command = regexr(command, `""(.)+do+(.)+""', "") // Get rid of in line strings insdie quotes
cap split command, p("do " "include ") gen(dof)
if `r(nvars)'>1 {
//replace dof2 = subinstr(dof2, `"""', "",.)
replace dof2 = regexr(dof2, "\.$", "")
levelsof dof2, clean loc(indos)
return scalar do_N = `r(N)'
return loc indos `indos'
}
else {
return scalar do_N = 0
}
}
u `currentdata', clear
noi di `"The do file "`using'" is successfully parsed."', _n
if "`abuiltin'" != "" noi di `" Built-in commands: `abuiltin'"'
if "`usercmd'" != "" noi di `" User written commands: `usercmd'"'
if "`defined'" != "" noi di `" Defined programs: `defined'"'
noi di `"{stata "return list":{it:click to see return list}}"'
end