root/trunk/Workspaces.pas

Revision 18, 11.2 kB (checked in by DavidM, 7 years ago)

Beta 8

Line 
1 unit Workspaces;
2
3 { Workspace classes }
4
5 interface
6 uses classes, Projects, SimpleXML;
7
8 { Configuration options for a Workspace }
9 type
10      TWorkspaceCfg = class
11        compiler       : string; { location of the dmd compiler }
12        linker         : string; { location of the linker }
13        sourceEditor   : string; { location of the source editor }
14        editorCommand  : string; { command string for invoking source editor }
15        paths          : TStringList;
16
17        constructor Create;
18        destructor  Free;
19
20        procedure CopyTo( other : TWorkspaceCfg );
21
22        function toXML : Node;
23        procedure fromXML( xml : Node );
24      end;
25
26
27 { Main Workspace class }    
28 type
29     TWorkspace = class
30       name      : string;         { onscreen title of the workspace }
31       filename  : string;         { filename to save workspace to }
32       output    : TStringList;    { results from compile/build }
33       projects  : TList;
34       failed    : TStringList;    { projects which failed to load }
35       config    : TWorkspaceCfg;
36
37       function Saved     : boolean;
38
39       constructor Create;
40       destructor  Free;
41       procedure Save;
42       procedure SaveAs( fname : string );
43
44       { Add a project to this workspace }
45       procedure Add( proj :TProject );
46
47       { Invoke the source editor for the passed file }
48       procedure EditFile( fname : string ; LN:Integer );
49
50       { Invoke the compiler for the passed project and file }     
51       function CompileFile( proj:TProject; fname : string ) : boolean;
52
53       { Conditionally invoke the compiler using the current FullBuild option }
54       function BuildFile( proj:TProject; fname : string ) : boolean;
55
56       { Build all files in the passed project }
57       function BuildAll( p : TProject ) : boolean;
58
59       { Build an EXE file for the passed project }     
60       function BuildProjectEXE( p : TProject ) : boolean;
61
62       { Build a LIB file for the passed project }
63       function BuildProjectLIB( p : TProject ) : boolean;
64
65       { Find a project based on passed name }
66       function  FindProject( filename : string ) : TProject;
67
68       protected
69       { Generates a command line string for editing a source file }
70       function GetEditString( fname:string; LN : Integer ) : string ;     
71     end;
72
73     { Loads a workspace file, returns nil if could not load }
74     function LoadWorkspace( fname : string ) :TWorkspace ;
75
76 const
77    FileVersion = '001';
78
79
80 implementation
81
82 uses UMain, SysUtils, MyUtils, Windows, FileCtrl, Clipbrd;
83
84
85 function TWorkspace.GetEditString( fname:string; LN: INteger ) : string ;
86 var
87   line, lcline : string;
88 begin
89   Result := '';
90   line := Trim(self.config.editorCommand) ;
91   if Empty( line ) then line:='$file /L:$Line';
92
93   lcline := LowerCase( line );
94   if Pos( '$file', lcline )<1 then line := '$file ' + line;
95
96   line:= StringReplace( line, '$file', fname, [rfReplaceAll,rfIgnoreCase] );
97   if LN>0 then
98     line:=StringReplace( line, '$line', Format( '%d', [LN] ), [rfReplaceAll,rfIgnoreCase] )
99   else
100     line:=StringReplace( line, '$line', Format( '%s', [''] ), [rfReplaceAll,rfIgnoreCase] );
101   Result := line;
102 end;
103
104
105
106 {Invoke Editor}
107 procedure TWorkspace.EditFile( fname : string ; LN : Integer );
108 var
109   args : TStringList;
110   argstring : string;
111   editor : string;
112 begin
113   editor := Path( config.sourceEditor );
114  
115   args := TStringList.Create;
116
117   if Pos( ' ', fname )>0 then fname:= '"' + fname + '"';
118
119   if LN>=0 then
120     args.add( GetEditString(fname,LN) )
121   else
122     args.add( fname );
123   argstring := Join( args, ' ');
124   args.Free; 
125   Clipboard.SetTextBuf( PChar( argstring ) );
126   Win32Exec( config.sourceEditor, argstring );
127 end;
128
129
130
131
132 { Compiles a source file, true if compilation was successful }
133 function TWorkspace.CompileFile( proj: TProject ; fname : string  ) : boolean;
134 var
135   cmd, dest : string;
136   qname : string;
137 begin
138   result := false;
139   output.Clear;
140   proj.sources.ClearErrors( fname ); 
141   if not DirectoryExists( proj.basepath ) then Exit;
142   SetCurrentDir( proj.basepath );
143   if not FileExists(fname) then Exit;
144
145   qname:= ShortName( fname );
146
147   cmd := Format( '-c %s %s', [ qname, proj.CompileOptions ] );
148   dest := proj.outPath;
149   if not DirectoryExists( dest ) then begin
150     output.Add( 'Output Directory does not exist!');
151     Exit;
152   end;
153
154   Sysutils.SetCurrentDir( proj.basepath );
155
156   { copy command line string to clipboard }
157   Clipboard.SetTextBuf( PChar( config.compiler + ' ' + cmd ) );
158   ConsoleApp( config.compiler, cmd, output );
159   TrimAll( output );
160
161   if output.count > 0 then proj.sources.AddErrors( fname , output );
162   Result:= ( output.Count = 0 );
163   Exit;
164 end;
165
166
167 function TWorkspace.BuildFile( proj:TProject; fname : string ) : boolean;
168 var
169   outname : string;
170   otime, stime : Integer; { obj time, source time }
171 begin
172   outname := proj.GetResultFile( fname );
173   proj.sources.ClearErrors( fname );
174   if (not proj.fullbuild) and FileExists(outname) then
175   begin
176     stime := FileAge( fname );
177     otime := FileAge( proj.GetResultFile( fname ) );
178     if otime >= stime then begin
179       result:= true;
180       Exit;
181     end;
182   end;
183   result:= CompileFile( proj, fname );
184 end;
185
186
187 function TWorkspace.BuildAll( p : TProject ) : boolean;
188 var
189   N : Integer;
190 begin
191   Result:= false;
192   with p.sources do
193     for N:= 0 to dfiles.Count-1 do
194       if not BuildFile( p, dfiles[N] ) then  Exit;
195
196   Result:=true;
197 end;
198
199
200 function TWorkspace.BuildProjectEXE( p : TProject ) : boolean;
201 var
202   outfiles : TStringList;
203   linkcmd : string;
204 begin
205   Result:=FileExists( self.config.compiler);
206   if not Result then Exit;
207
208   output.Clear;
209   Result := Self.BuildAll( p );
210   if not Result then Exit;
211
212   outfiles := TStringList.Create;
213   outfiles.Duplicates := dupIgnore;
214   p.GetObjectFiles( outfiles );
215   outfiles.AddStrings( p.sources.objfiles );
216   outfiles.AddStrings( p.sources.libfiles );
217
218   MyUtils.GetShortNames( outfiles );
219
220   linkcmd := Format( '%s %s',
221                      [ p.LinkOptions, Join( outfiles, ' ') ] );
222   ClipBoard.SetTextBuf( PChar( linkcmd ) );
223   SetCurrentDir( p.basepath );
224   ConsoleApp( config.compiler, linkcmd, output ) ;
225   result:= true;
226 end;
227
228
229
230 function TWorkspace.BuildProjectLIB( p : TProject ) : boolean;
231 var
232   outfiles : TStringList;
233   libcmd : string;
234   libfile : string;
235   N : Integer;
236 begin
237   Result:=FileExists( self.config.compiler);
238   if not Result then Exit;
239
240   output.Clear;
241   Result := Self.BuildAll( p );
242   if not Result then Exit;
243
244   outfiles := TStringList.Create;
245   p.GetObjectFiles( outfiles );
246   outfiles.AddStrings( p.sources.objfiles );
247   outfiles.AddStrings( p.sources.libfiles );
248
249   GetShortNames( outfiles );
250   libfile := p.LibName;
251
252   N := outfiles.IndexOf( libfile );
253   if N>=0 then  outfiles.Delete( N );
254
255   libfile := ShortName( libfile );
256
257   SetCurrentDir( p.basepath );
258
259   libcmd := Format( '-c %s %s', [ libfile, Join( outfiles, ' ' ) ] );
260   ClipBoard.SetTextBuf( PChar( libcmd ) );
261   ConsoleApp( 'lib.exe', libcmd, output ) ;
262   TrimAll( output );
263   outfiles.Free;
264   result:= true;
265 end;
266
267
268
269 constructor TWorkspace.Create;
270 begin
271   filename :='';
272   name := '';
273   output   := TStringList.Create;
274   projects := TList.Create;
275   failed   := TStringList.Create;
276   config   := TWorkspaceCfg.Create;
277 end;
278
279
280 destructor TWorkspace.Free;
281 var
282   N : LongInt;
283   proj : TProject;
284 begin
285   for N:= 0 to projects.Count-1 do begin
286     proj := projects[N];
287     proj.Free;
288   end;
289   output.Free; 
290   projects.Free;
291   failed.Free;
292   config.Free;
293 end;
294
295
296 function TWorkspace.Saved : boolean;
297 begin
298   Result:= ( not Empty(filename) ) and FileExists( filename );
299 end;
300
301 procedure TWorkspace.Add( proj: TProject );
302 begin
303   if not Assigned( proj ) then Exit;
304   proj.parent := Self ;
305   projects.Add( proj );
306 end;
307
308
309 function LoadWorkspace( fname : string ) : TWorkspace;
310 var
311    xml, tmp, cfg : Node;
312    N : LongInt;
313    proj : TProject;
314    str : string;
315 begin
316    Result := nil;
317
318    if not FileExists( fname ) then exit;
319
320    xml := LoadXML( fname );
321    if not Assigned(xml) then Exit;
322
323    result := TWorkspace.Create ;
324    result.filename := fname;
325
326    result.name := xml.FindText( 'Name' );
327
328    cfg := xml.FindNode( 'WorkspaceConfig' );
329    result.config.fromXML( cfg );
330
331    tmp := xml.FindNode( 'Projects' );
332    for N:=0 to tmp.Count-1 do begin
333      str := tmp[N].data;
334      proj := LoadProject( str );
335      if Assigned( proj ) then result.Add( proj )
336      else result.failed.Add( str );
337    end;
338
339    xml.Free;
340 end;
341
342 procedure TWorkspace.Save;
343 begin
344   if not Empty( self.filename ) then Self.SaveAs( self.filename );
345 end;
346
347 procedure TWorkspace.SaveAs( fname : string );
348 var
349   xml, prj, tmp : Node;
350   I : LongInt;
351   proj : TProject;
352 begin
353   filename := fname;
354
355   xml:=Node.Create( 'Workspace' );
356   tmp:=xml.Add( 'Name' );
357   tmp.data := self.name;
358
359   xml.AddChild( config.toXML );
360   prj := xml.Add( 'Projects' );
361
362   for I:= 0 to projects.Count-1 do begin
363     proj := projects[I];
364     tmp := prj.Add( 'Filename' );
365     tmp.data := proj.filename;
366   end;
367
368   SaveXML( xml, filename );
369   xml.Free;
370 end;
371
372
373 function TWorkspace.FindProject( filename : string ) : TProject;
374 var
375   proj : TProject;
376   pname : string;
377   N : integer;
378 begin
379   Result := nil;
380   pname := Trim( ExtractFileName( filename ));
381   pname := ChangeFileExt( pname, '' );
382   for N:=0 to projects.Count-1 do begin
383     proj := projects[ N ];
384     if proj.filename = filename then
385     begin
386       Result:= proj;
387       Exit;
388     end;
389   end;
390 end;
391
392
393 constructor TWorkspaceCfg.Create;
394 begin
395   compiler := '';
396   sourceEditor := '';
397   editorCommand := '';
398   paths := TStringList.Create;
399 end;
400
401
402 destructor TWorkspaceCfg.Free;
403 begin
404   paths.Free;
405 end;
406
407 function TWorkspaceCfg.toXML : Node;
408 var
409   cfg, tmp : Node;
410 begin
411   cfg:= Node.Create( 'WorkspaceConfig' );
412   tmp := cfg.Add( 'Compiler' );
413   tmp.data := self.compiler;
414
415   tmp := cfg.Add( 'Linker' );
416   tmp.data := self.linker;
417
418   tmp := cfg.Add( 'Editor' );
419   tmp.data := self.sourceEditor;
420
421   tmp := cfg.Add( 'EditCommand' );
422   tmp.data := self.editorCommand;
423   result:= cfg;
424 end;
425
426
427 procedure TWorkspaceCfg.fromXML( xml : Node );
428 begin
429   if not Assigned(xml) then Exit;
430   self.Compiler := xml.FindText( 'Compiler' );
431   self.linker := xml.FindText( 'Linker' );
432   self.sourceEditor := xml.FindText( 'Editor' );
433   self.editorCommand := xml.FindText( 'EditCommand' );
434 end;
435
436
437
438 procedure TWorkspaceCfg.CopyTo( other : TWorkspaceCfg );
439 begin
440   other.compiler := compiler;
441   other.linker := linker;
442   other.sourceEditor := sourceEditor;
443   other.editorCommand := editorCommand;
444   other.paths.Clear;
445   other.paths.AddStrings( paths );
446 end;
447
448 {
449 procedure TWorkspaceCfg.Save( writer:TDataWriter );
450 begin
451   writer.WriteString( compiler );
452   writer.WriteString( linker );
453   writer.WriteString( sourceEditor );
454   writer.WriteString( editorCommand );
455   writer.WriteStrings( paths );
456 end;
457
458
459 procedure TWorkspaceCfg.Load( reader : TDataReader );
460 begin
461   reader.ReadString( compiler );
462   reader.ReadString( linker );
463   reader.ReadString( sourceEditor );
464   reader.ReadString( editorCommand );
465   reader.ReadStrings( paths );
466 end;
467 }
468
469 end.
Note: See TracBrowser for help on using the browser.