How to have to commands in seperate ado-files sharing the same sub-commands in a separate file.
It is common that two ado-files in the same package share a lot of sub-commands (also called utility commands, functions etc.). It is bad practice to write the commands in one file first and copy and paste the sub-commands to the other ado-file. This is ad practice as updating these commands is very likely to lead to errors. This is a part of the DRY coding principle that is one of the few coding paradigms that all computer scientists agree on.
This Gist explains how you can set this up in a Stata environment.
You should give this file a unique name if you are planning on publishing commands using this method as there will be a name conflict if someone else also have a file called mySubCommandsXYZ.do or whatever you end up calling your file.
This file includes all sub-commands that should be included in the ado-files for the commands. The commands in this file may not have the same name as any sub-command written directly in the ado-files.
In the ado-files the following line of code is used capture findfile mySubCommandsXYZ.do
. findfile
is a command that looks in the adopath folders - these are the folders where user-written commands may be installed - for a file called mySubCommandsXYZ.do.
If the file is found, then the local path to that file is saved in the return local r(fn). That local is used in run "'r(fn)'"
. That line runs the file with all the functions and saves them into temporary memory so that the command can use them.
If the file is not found, an error is thrown.
If you are planning on publishing commands using this set-up, for example at SSC, all you need to do is to include the mySubCommandsXYZ.do (or whatever you called your file) with the ado-files and help-files.
/********************************************************************************
These functions are loaded into the command in
the prefix_bar.ado and the prefix_foo.ado file
********************************************************************************/
cap program drop suff_foo
program define suff_foo
syntax , string(string)
di "`string'_foo"
end
cap program drop suff_bar
program define suff_bar
syntax , string(string)
di "`string'_bar"
end
cap program drop prefix_bar
program define prefix_bar
syntax , string(string) suffix_foo suffix_bar
*This segment of code imports the utility functions for this command
capture findfile mySubCommandsXYZ.do //Search for file in adopath
if (_rc == 0) {
run "`r(fn)'" //Running the file loads all functions in the mySubCommandsXYZ.do file
}
else {
error 601 //the mySubCommandsXYZ.do file not found in the adopaths
}
local string "bar_`string'"
di "`string'"
if "`suffix_foo'" != "" suffix_foo , string("`string'")
if "`suffix_foo'" != "" suffix_foo , string("`string'")
end
cap program drop prefix_foo
program define prefix_foo
syntax , string(string) suffix_foo suffix_bar
*This segment of code imports the utility functions for these commands
capture findfile mySubCommandsXYZ.do //Search for file in adopath
if (_rc == 0) {
run "`r(fn)'" //Running the file loads all functions in the mySubCommandsXYZ.do file
}
else {
error 601 //the mySubCommandsXYZ.do file not found in the adopaths
}
local string "foo_`string'"
di "`string'"
if "`suffix_foo'" != "" suffix_foo , string("`string'")
if "`suffix_foo'" != "" suffix_foo , string("`string'")
end