I'm not quite sure if this is a bug per-se, but I ran into a problem attempting to create C & CPP template files, related to how the existing Objective-C template shell works (and interacting with it):
When you create a new file from template using File->New From Template->foo the environment variables for $TM_NEW_FILE and $TM_NEW_FILE_DIRECTORY seem to get interpreted such that they wind up pointing at a directory under that user's /tmp. The problem is that if any template shell script has already created an "untitled<n>.h" file there, that file causes the new template shell script's "exist" test to fail, and you wind up loading the (colliding) file generated by the prior template shell script. When dealing with three different template types (C, C++, and Objective-C) all who expect to also generate a .h file, the chance of such a collision becomes very high.
I looked at possibly using a timestamp to try and differentiate, but that causes a problem if the user actually triggers the template shell script from the Project window. In that case, the script receives properly-populated $TM_NEW_FILE and $TM_NEW_FILE_DIRECTORY variables, and thus you don't have the same problem of trying to avoid "tmp" naming collisions.
It seems like there are a couple of obvious solutions:
1. TextMate could populate a variable to indicate whether the template is being run from the Project window (in which case $TM_NEW_FILE and kin are properly populated, and should be unique), or from the "File->New From Template" menu item (in which case they are not, and you need to avoid collisions because all template scripts are dumping in the same tmp directory, using "untitled"-based names).
2. Alternately, in the "File->New From Template" case, TextMate itself could initially provide a _unique_ $TM_NEW_FILE_BASENAME and friends (perhaps append a `date "+%y%m%d%H%M%S"` to the basename?). That would prevent collisions in the tmp directory even when multiple templates provided files with overlapping file extensions.
There also appears to be an issue over time of these left-over template shell script file "breadcrumbs" created when "untitled<n>.foo" files are initially created, but the user presumably saves the file with a real name afterwards. There really doesn't appear to be any way for template scripts to clean up the tmp dir after themselves. Not a big deal if the filename collision problem gets solved, but eventually they'll start to create a fair amount of "Spotlight clutter", etc. which can become an issue.
Love the program, and am quite impressed by how much is already possible with V1's facilities. That said, I'm really looking forward to V2 and the more powerful snippets/templates/etc. I've been rather spoiled by Slickedit on PC, and keep hoping TextMate will offer similar abilities (I refuse to use that X-Window abortion Slickedit calls a "Mac version").
Thanks!
-John W.
On 16 Jan 2010, at 02:42, John Wiederhirn wrote:
[ Instantiating Templates are done in TMPDIR with non-unique name ] It seems like there are a couple of obvious solutions:
- TextMate could populate a variable to indicate whether the
template is being run from the Project window (in which case $TM_NEW_FILE and kin are properly populated, and should be unique), or from the "File->New From Template" menu item (in which case they are not, and you need to avoid collisions because all template scripts are dumping in the same tmp directory, using "untitled"-based names).
I think template commands already do too much (that TextMate should do), so having them resolve the conflict is clumsy.
- Alternately, in the "File->New From Template" case, TextMate
itself could initially provide a _unique_ $TM_NEW_FILE_BASENAME and friends [...]
Problem with this is that several templates use the file name in the template, so using an (ugly) unique name would leak into the instantiated template (rather than just have the default class, HTML title, etc.) be ‘untitled’.
To be honest templates are pretty lousy and it is something I have previously said would be completely revamped in 2.0, the current system is broken and it needs to be retired and reinvented/unified with snippets, so it is not really an area I am eager to “fix” for 1.x (even if 2.0 is not here yet).
Allan Odgaard-4 wrote:
I think template commands already do too much (that TextMate should do), so having them resolve the conflict is clumsy.
I definitely agree, but unfortunately it's fairly easy to wind up with an "untitled.h" in your temp directory that then subsequently blocks all further generation of C/C++/Obj-C templates of any kind. The issue isn't tied to multi-file templates either, even single-file templates that check for file existence can trigger this problem.
Allan Odgaard-4 wrote:
Problem with this is that several templates use the file name in the template, so using an (ugly) unique name would leak into the instantiated template (rather than just have the default class, HTML title, etc.) be ‘untitled’.
To be honest templates are pretty lousy and it is something I have previously said would be completely revamped in 2.0, the current system is broken and it needs to be retired and reinvented/unified with snippets, so it is not really an area I am eager to “fix” for 1.x (even if 2.0 is not here yet).
The problem, as you mention, is that what we have is broken. I'd certainly like to see a more orthogonal system in 2.0, but I still have to get work done in 1.x. It's not really different from any other bug in that regard, is it? Template support is a feature of 1.x (even if suboptimal), so shouldn't it at least work?
The crux of this issue isn't about how templates work, anyway. It's about whether new file generators should always use a "real" (thus unique) filename. The proposed "create file and insert template snippet" approach you've mentioned for 2.0 will face this same issue, so long as creating a file from the project prompts the user for a filename, and file->'new from template' does not.
The way Slickedit (as good a reference as any) handles this is to always prompt the user for a file name when creating a file, from whatever UI element triggers it. I'm kind of partial to that solution as well, because it prevents noisy temporary names from polluting templates/snipplates/whatever that might want to use the basename. Putting up a name request dialog also gives a place to let the user select a language mode during creation, which shortens the user process to create an arbitrary file (e.g. File->New) and set mode.
In any case, I hope I've made my point. I don't see this as an issue with 1.x templates in particular, it seems more like a general new file generation issue, and any solution can carry over into 2.0's code as well.
On 2 Feb 2010, at 21:30, John Wiederhirn wrote:
[...] unfortunately it's fairly easy to wind up with an "untitled.h" in your temp directory that then subsequently blocks all further generation of C/C++/Obj-C templates of any kind. The issue isn't tied to multi-file templates either, even single-file templates that check for file existence can trigger this problem.
It should only be for multi-file templates, as TextMate will do the check for single-file templates, and “bump” the untitled counter until there is a free spot. It can’t do that for multi-file templates because it only knows the name of one of the files generated (so that is the one it ensures does not already exist).
As for ‘fairly easy’ — with the default set of templates, only the Objective-C singleton generates multiple file. You can use this repeatedly w/o problems. What you have to do is use it, go into the temp. folder and delete the *.mm file w/o deleting the *.h file *then* a problem arise. But while easy, why would you do that? Why would you use the template without a project in the first place?
If you use the template with a project, you are asked for a name in advance, so the problem should not exist here, and IMO this template mainly makes sense to use for projects.
[...] but I still have to get work done in 1.x. It's not really different from any other bug in that regard, is it?
Sure it is: It doesn’t crash, it doesn’t lead to problems for 99.999% of users, the problems it can cause (no templates generated) are non- serious and easy to workaround (cleanup your temp. folder), at least when you know the issue, the intended use of the template should actually never lead to this problem, and finally, the “fix” is non- trivial, because this is more of a design flaw than a bug, it requires a rethought design which would likely break with the current template system, hence why this is scheduled for 2.0, where it is more ok to just drop support for the current templates.
[...] The proposed "create file and insert template snippet" approach you've mentioned for 2.0 will face this same issue [...] it seems more like a general new file generation issue, and any solution can carry over into 2.0's code as well.
Shell commands (and hence disk files) will not be involved in “New File [From Template]”, so there should be no such issue.
Allan Odgaard-4 wrote:
On 2 Feb 2010, at 21:30, John Wiederhirn wrote:
[...] unfortunately it's fairly easy to wind up with an "untitled.h" in your temp directory that then subsequently blocks all further generation of C/C++/Obj-C templates of any kind. The issue isn't tied to multi-file templates either, even single-file templates that check for file existence can trigger this problem.
It should only be for multi-file templates, as TextMate will do the check for single-file templates, and “bump” the untitled counter until there is a free spot. It can’t do that for multi-file templates because it only knows the name of one of the files generated (so that is the one it ensures does not already exist).
Okay, I'm confused, I thought one of the things you were trying to avoid was having "noisy" names pulled into the templates for subsequent usage, so was trying to avoid that totally. However, if you're okay with the user having to change stuff like UNTITLED_2_H, then why is changing TM1002022340_H worse? In either cases, it's a search and replace situation, no? <p> I'd have an easier time with just having the user delete the files in the temp folder if it were easily accessible from Finder (or even Terminal), but /var/folder/cT/cTlongtextgibberish/-Tmp-/ really isn't friendly to user-access, period. Heck I'd even be okay with just always deleting the questionable file in -Tmp-, but that's hard in a template script precisely because the untitled basename _does_ potentially change. You kind of wind up needing to know whether the basename was auto-generated or not to safely make that call. <p> BTW, that would be another workaround, just set an env var you hand to the template building script set to 1 or 0 depending on whether basename was auto-generated (file->new from template) or not. Then templates know they're in the -Tmp- dir, and thus whether they can overwrite any colliding files "safely". <p> Since you've made your position clear, though, I'll drop it. I look forward to 2.0 when hopefully multi-file templates (very useful for C, C++ and Obj-C "starter patterns") will be reliably useful. Thanks again.