Menu

[r111]: / trunk / Src / USaveUnitMgr.pas  Maximize  Restore  History

Download this file

362 lines (328 with data), 12.9 kB

  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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
{
* USaveUnitMgr.pas
*
* Defines a class that manages generation, previewing and saving of a pascal
* unit.
*
* v1.0 of 29 Oct 2006 - Original version.
* v1.1 of 09 Feb 2007 - Added disclaimer to generated unit.
* - Modified to use new TSourceGen.IncludeRoutines method
* to add required routines to unit rather than adding
* one by one using IncludeRoutine.
* v1.2 of 02 Jul 2007 - Fixed typo in source code disclaimer comment.
* - Added code to build a document title and to include it
* in generated units.
* - A unit file name is now suggested for dialog box.
* - Changed default unit name / filename from
* "PreviewUnit" to "Snippets".
* v1.3 of 26 Sep 2007 - Changed code that checks for acceptable file name to
* pass any error message back via OnCheckFileName event
* handler rather than displaying error in a message box.
* v1.4 of 13 Sep 2008 - Changed to use a different header comment if snippet
* contains only user defined routines.
* - Changed document title to remove reference to
* database.
* - Changed to use for..in to loop through routine list.
* v1.5 of 05 Oct 2008 - Made constructor protected and made Execute method
* static.
* - Made protected and private sections strict.
* - Now use ClassName method in assert statement.
* v1.6 of 13 May 2009 - URL and program information now obtained from TWebInfo
* and TAppInfo respectively instead of UGlobals unit.
* v1.7 of 16 May 2009 - Modified to use renamed TSourceGen methods.
* - Renamed some fields and variables.
* v1.8 of 10 Jul 2009 - Changed to generate and use comments as IStringList
* rather than TStringList.
*
*
* ***** BEGIN LICENSE BLOCK *****
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is USaveUnitMgr.pas
*
* The Initial Developer of the Original Code is Peter Johnson
* (http://www.delphidabbler.com/).
*
* Portions created by the Initial Developer are Copyright (C) 2006-2009 Peter
* Johnson. All Rights Reserved.
*
* ***** END LICENSE BLOCK *****
}
unit USaveUnitMgr;
interface
uses
// Project
UBaseObjects, UIStringList, USourceFileOutputMgr, USourceGen, USnippets;
type
{
TSaveUnitMgr:
Manages generation, previewing and saving of a Pascal unit to disk.
Generated file can be a valid Pascal unit, a plain text file, an HTML file
or a RTF file. The last two files types can optionally be syntax
highlighted.
}
TSaveUnitMgr = class(TNoPublicConstructObject)
strict private
fSourceGen: TSourceGen;
{Generates source code unit}
fOutputMgr: TSourceFileOutputMgr;
{Gets file information from user and controls saving of snippers to disk}
fUnitName: string;
{Name of generated unit. Name is based on file when saving unit and has a
default fixed value when previewing}
fContainsMainDBSnippets: Boolean;
{Flag true if unit contains at least one snippet from main database, False
only if unit is completely user defined}
procedure SourceGenHandler(Sender: TObject;
const CommentStyle: TCommentStyle; out RawSourceCode, DocTitle: string);
{Handles output manager's OnGenerateOutput event by generating source code
of unit in required comment style.
@param Sender [in] Not used.
@param CommentStyle [in] Style of commenting to be used in source code.
@param SourceCode [out] Receives generated source code.
@param DocTitle [out] Receives document title.
}
procedure CheckFileNameHandler(Sender: TObject; const FileName: string;
var NameOK: Boolean; var ErrorMessage: string);
{Handler of output manager's OnCheckFileName event. Checks if file name is
suitable for use as basis of a unit name. If so unit name is recorded.
@param Sender [in] Not used.
@param FileName [in] File name to be checked.
@param NameOK [in/out] Defaults to true. Set to false if file name fails
check, i.e. is not valid as a unit name.
@param ErrorMessage [in/out] Default to ''. Set to error message if
NameOK is set false.
}
function UnitName: string;
{Gets name of unit to be used in generated code.
@return Name of unit.
}
function CreateHeaderComments: IStringList;
{Creates and stores header comments to be written to head of unit.
@return String list containing comments.
}
strict protected
constructor InternalCreate(const Snips: TRoutineList);
{Class constructor. Sets up object to save a unit containing all snippets
in a list.
@param Snips [in] List of snippets to include in unit.
}
procedure DoExecute;
{Gets information from user about name and format of required file and
saves unit to disk.
}
public
destructor Destroy; override;
{Class destructor. Tears down object.
}
class procedure Execute(const Snips: TRoutineList);
{Gets information from user about name and format of required file and
saves unit containing specified snippets to disk.
@param Snips [in] List of snippets to include in unit.
}
end;
implementation
uses
// Delphi
SysUtils,
// Project
UAppInfo, USourceFileInfo, UUtils, UWebInfo;
resourcestring
// Dialog box strings
// title
sSaveDlgTitle = 'Save Unit';
// default file / unit name
sDefUnitName = 'Snippets';
// file filter strings
sHTMLDesc = 'HTML file';
sRTFDesc = 'Rich text file';
sPascalDesc = 'Pascal unit';
sTextDesc = 'Plain text file';
// Error message
sErrorMsg = 'Filename is not valid for a Pascal unit';
// Unit header comments
sLicense = 'This unit is freeware and may be freely distributed and used on '
+ 'the condition that this comment is not removed from the unit.';
sMainDescription = 'The unit was generated automatically. It contains a '
+ 'selection of code taken from the Code Snippets Database at %0:s.';
sDisclaimer = 'The source code contained in this unit is made available on '
+ 'an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or '
+ 'implied. The code is used entirely at your own risk.';
sGenerated = 'Generated on : %0:s.';
sGenerator = 'Generated by : %0:s %1:s.';
sAdvert = 'The latest version of %0:s is available from the %1:s website '
+ 'at %2:s.';
sUserDescription = 'This unit was generated automatically.';
// Output document title
sDocTitle = 'Unit "%0:s" generated by %1:s';
{ TSaveUnitMgr }
procedure TSaveUnitMgr.CheckFileNameHandler(Sender: TObject;
const FileName: string; var NameOK: Boolean; var ErrorMessage: string);
{Handler of output manager's OnCheckFileName event. Checks if file name is
suitable for use as basis of a unit name. If so unit name is recorded.
@param Sender [in] Not used.
@param FileName [in] File name to be checked.
@param NameOK [in/out] Defaults to true. Set to false if file name fails
check, i.e. is not valid as a unit name.
@param ErrorMessage [in/out] Default to ''. Set to error message if NameOK
is set false.
}
begin
NameOK := TSourceGen.IsFileNameValidUnitName(FileName);
if NameOK then
fUnitName := TSourceGen.UnitNameFromFileName(FileName)
else
begin
fUnitName := '';
ErrorMessage := sErrorMsg
end;
end;
function TSaveUnitMgr.CreateHeaderComments: IStringList;
{Creates and stores header comments to be written to head of unit.
@return String list containing comments.
}
begin
Result := TIStringList.Create;
if fContainsMainDBSnippets then
begin
// Result used for units that contain at snippet(s) from main database
Result.Add(sLicense);
Result.Add('');
Result.Add(Format(sMainDescription, [TWebInfo.DatabaseURL]));
Result.Add('');
Result.Add(sDisclaimer);
Result.Add('');
Result.Add(Format(sGenerated, [DateStamp]));
Result.Add(
Format(
sGenerator, [TAppInfo.FullProgramName, TAppInfo.ProgramReleaseInfo]
)
);
Result.Add('');
Result.Add(
Format(
sAdvert,
[TAppInfo.ProgramName, TAppInfo.CompanyName, TWebInfo.ProgramHomeURL]
)
);
end
else
begin
// Result used for units that contain only user defined snippets
Result.Add(sUserDescription);
Result.Add('');
Result.Add(Format(sGenerated, [DateStamp]));
Result.Add(
Format(
sGenerator, [TAppInfo.FullProgramName, TAppInfo.ProgramReleaseInfo]
)
);
end;
end;
destructor TSaveUnitMgr.Destroy;
{Class destructor. Tears down object.
}
begin
FreeAndNil(fOutputMgr);
FreeAndNil(fSourceGen);
inherited;
end;
procedure TSaveUnitMgr.DoExecute;
{Gets information from user about name and format of required file and saves
unit to disk.
}
begin
// Hand off processing to output manager
fOutputMgr.Execute;
end;
class procedure TSaveUnitMgr.Execute(const Snips: TRoutineList);
{Gets information from user about name and format of required file and saves
unit containing specified snippets to disk.
@param Snips [in] List of snippets to include in unit.
}
begin
with InternalCreate(Snips) do
try
DoExecute;
finally
Free;
end;
end;
constructor TSaveUnitMgr.InternalCreate(const Snips: TRoutineList);
{Class constructor. Sets up object to save a unit containing all snippets in a
list.
@param Snips [in] List of snippets to include in unit.
}
var
Snippet: TRoutine; // references each snippet in list
begin
Assert(Assigned(Snips), ClassName + '.InternalCreate: Snips is nil');
inherited InternalCreate;
// Create source generator and initialize it with required snippets
fSourceGen := TSourceGen.Create;
fSourceGen.IncludeSnippets(Snips);
// Determine if snippet list contains at least one snippet from main database
fContainsMainDBSnippets := False;
for Snippet in Snips do
begin
if not Snippet.UserDefined then
begin
fContainsMainDBSnippets := True;
Break;
end;
end;
// Create and initialise output manager object
fOutputMgr := TSourceFileOutputMgr.Create;
fOutputMgr.DlgTitle := sSaveDlgTitle;
fOutputMgr.DlgHelpKeyword := 'SaveUnitDlg';
fOutputMgr.OnGenerateOutput := SourceGenHandler;
fOutputMgr.OnCheckFileName := CheckFileNameHandler;
with fOutputMgr.SourceFileInfo do
begin
Descriptions[sfText] := sTextDesc;
FileExtensions[sfText] := '.txt';
Descriptions[sfPascal] := sPascalDesc;
FileExtensions[sfPascal] := '.pas';
Descriptions[sfHTML] := sHTMLDesc;
FileExtensions[sfHTML] := '.html';
Descriptions[sfRTF] := sRTFDesc;
FileExtensions[sfRTF] := '.rtf';
FileName := sDefUnitName;
end;
end;
procedure TSaveUnitMgr.SourceGenHandler(Sender: TObject;
const CommentStyle: TCommentStyle; out RawSourceCode, DocTitle: string);
{Handles output manager's OnGenerateOutput event by generating source code of
unit in required comment style.
@param Sender [in] Not used.
@param CommentStyle [in] Style of commenting to be used in source code.
@param SourceCode [out] Receives generated source code.
@param DocTitle [out] Receives document title.
}
begin
RawSourceCode := fSourceGen.UnitAsString(
UnitName, CommentStyle, CreateHeaderComments
);
DocTitle := Format(sDocTitle, [UnitName, TAppInfo.ProgramName]);
end;
function TSaveUnitMgr.UnitName: string;
{Gets name of unit to be used in generated code.
@return Name of unit.
}
begin
// If we have valid unit name based on file, use it, otherwise use default
if fUnitName <> '' then
Result := fUnitName
else
Result := sDefUnitName;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.