3 public class AppSettings : Object
8 // what are we going to have as settings?
9 public string roo_html_dir { get; set; }
13 this.notify.connect(() => {
18 public static AppSettings factory()
21 var setting_file = BuilderApplication.configDirectory() + "/builder.settings";
23 if (!FileUtils.test(setting_file, FileTest.EXISTS)) {
24 return new AppSettings();
28 FileUtils.get_contents(setting_file, out data);
29 return Json.gobject_from_data (typeof (AppSettings), data) as AppSettings;
32 return new AppSettings();
36 var dirname = GLib.Environment.get_home_dir() + "/.Builder";
37 var setting_file = dirname + "/builder.settings";
38 string data = Json.gobject_to_data (this, null);
39 GLib.debug("saving application settings\n");
41 FileUtils.set_contents(setting_file, data);
43 print("Error saving app settings");
51 public static BuilderApplication application = null;
53 public class BuilderApplication : Gtk.Application
56 // options - used when builder is run as a compiler
57 // we have to spawn ourself as a compiler as just running libvala
58 // as a task to check syntax causes memory leakage..
60 const OptionEntry[] options = {
63 { "project", 0, 0, OptionArg.STRING, ref opt_compile_project, "select a project", null },
64 { "target", 0, 0, OptionArg.STRING, ref opt_compile_target, "Target to build", null },
65 { "skip-linking", 0, 0, OptionArg.NONE, ref opt_skip_linking, "Do not link the files and make a binary - used to do syntax checking", null },
66 { "skip-file", 0, 0, OptionArg.STRING, ref opt_compile_skip ,"For test compiles do not add this (usually used in conjunction with add-file ", null },
67 { "add-file", 0, 0, OptionArg.STRING, ref opt_compile_add, "Add this file to compile list", null },
68 { "output", 0, 0, OptionArg.STRING, ref opt_compile_output, "output binary file path", null },
69 { "debug", 0, 0, OptionArg.NONE, ref opt_debug, "Show debug messages for non-ui, or crash on warnings for gdb ", null },
70 { "pull-resources", 0, 0, OptionArg.NONE, ref opt_pull_resources, "Fetch the online resources", null },
73 { "list-projects", 0, 0, OptionArg.NONE, ref opt_list_projects, "List Projects", null },
74 { "list-files", 0, 0, OptionArg.NONE, ref opt_list_files, "List Files (in a project", null},
75 { "bjs", 0, 0, OptionArg.STRING, ref opt_bjs_compile, "convert bjs file (use all to convert all of them and compare output)", null },
76 { "bjs-glade", 0, 0, OptionArg.NONE, ref opt_bjs_compile_glade, "output glade", null },
77 { "bjs-test-all", 0, 0, OptionArg.NONE, ref opt_bjs_test, "Test all the BJS files to see if the new parser/writer would change anything", null },
78 { "bjs-target", 0, 0, OptionArg.STRING, ref opt_bjs_compile_target, "convert bjs file to tareet : vala / js", null },
79 { "test", 0, 0, OptionArg.STRING, ref opt_test, "run a test use 'help' to list the available tests", null },
80 { "language-server", 0, 0, OptionArg.STRING, ref opt_language_server, "run language server on this file", null },
81 { "drop-list", 0, 0, OptionArg.STRING, ref opt_drop_list, "show droplist / children for a Gtk type (eg. Gtk.Widget)", null },
86 public static string opt_compile_project;
87 public static string opt_compile_target;
88 public static string opt_compile_skip;
89 public static string opt_compile_add;
90 public static string opt_compile_output;
91 public static string opt_bjs_compile;
92 public static string opt_bjs_compile_target;
93 public static string opt_test;
94 public static string opt_drop_list;
95 public static string opt_language_server;
97 public static bool opt_skip_linking = false;
98 public static bool opt_debug = false;
99 public static bool opt_list_projects = false;
100 public static bool opt_list_files = false;
101 public static bool opt_pull_resources = false;
102 public static bool opt_bjs_compile_glade = false;
103 public static bool opt_bjs_test = false;
104 public static string _self;
113 public const Gtk.TargetEntry[] targetList = {
114 { "INTEGER", 0, Target.INT32 },
115 { "STRING", 0, Target.STRING },
116 { "application/json", 0, Target.STRING },
117 { "text/plain", 0, Target.STRING },
118 { "application/x-rootwindow-drop", 0, Target.ROOTWIN }
121 //public AppSettings settings = null;
125 //public static Palete.ValaCompileQueue valacompilequeue;
128 public BuilderApplication ( string[] args)
132 _self = FileUtils.read_link("/proc/self/exe");
134 // this should nto happen!!?
135 GLib.error("could not read /proc/self/exe");
137 GLib.debug("SELF = %s", _self);
138 var f = File.new_for_path(_self);
141 var fi = f.query_info("*",0);
142 dt = fi.get_creation_date_time().to_unix().to_string();
143 } catch (GLib.Error e) {
148 application_id: "org.roojs.%s.ver%s".printf( GLib.Path.get_basename(_self),dt),
149 flags: ApplicationFlags.FLAGS_NONE
151 BuilderApplication.windows = new Gee.ArrayList<Xcls_MainWindow>();
152 BuilderApplication.windowlist = new GLib.ListStore(typeof(WindowState));
153 //BuilderApplication.valacompilequeue = new Palete.ValaCompileQueue();
157 // this.settings = AppSettings.factory();
158 var opt_context = new OptionContext ("Application Builder");
161 opt_context.set_help_enabled (true);
162 opt_context.add_main_entries (options, null);
163 opt_context.parse (ref args);
166 } catch (OptionError e) {
167 stdout.printf ("error: %s\n", e.message);
168 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n %s",
169 args[0], opt_context.get_help(true,null));
170 GLib.Process.exit(Posix.EXIT_FAILURE);
175 this.pullResources();
177 Project.Project.loadAll();
179 var cur_project = this.compileProject();
180 this.dropList(cur_project); // --drop-list
181 this.languageServer(cur_project); // --language-server
182 this.listFiles(cur_project);
183 this.testBjs(cur_project);
184 this.languageServer(cur_project);
185 this.compileBjs(cur_project);
186 //this.compileVala();
190 public static Settings settings;
192 protected override void activate ()
194 var css = new Gtk.CssProvider();
195 css.load_from_resource("/css/roobuilder.css");
197 Gtk.StyleContext.add_provider_for_display(
198 Gdk.Display.get_default(),
200 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
202 BuilderApplication.settings = new Settings();
204 var w = new Xcls_MainWindow();
206 BuilderApplication.addWindow(w);
208 // it looks like showall after children causes segfault on ubuntu 14.4
209 w.windowstate.init();
210 // w.windowstate.showPopoverFiles(w.open_projects_btn.el, null, false);
215 public static BuilderApplication singleton( string[]? args)
217 if (application==null && args != null) {
218 application = new BuilderApplication( args);
226 public static string configDirectory()
228 var dirname = GLib.Environment.get_home_dir() + "/.Builder";
230 if (!FileUtils.test(dirname,FileTest.IS_DIR)) {
231 var dir = File.new_for_path(dirname);
233 dir.make_directory();
235 GLib.error("Failed to make directory %s", dirname);
238 if (!FileUtils.test(dirname + "/resources",FileTest.IS_DIR)) {
239 var dir = File.new_for_path(dirname + "/resources");
241 dir.make_directory();
243 GLib.error("Failed to make directory %s", dirname + "/resources");
252 // --------------- non static...
258 if (BuilderApplication.opt_debug || BuilderApplication.opt_compile_project == null) {
259 GLib.Log.set_default_handler(
260 // GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_CRITICAL,
263 print("%s: %s : %s\n", (new DateTime.now_local()).format("%H:%M:%S.%f"), lvl.to_string(), msg);
265 if (dom== "GtkSourceView") { // seems to be some critical wanrings comming from gtksourceview related to insert?
268 //if (msg.contains("gdk_popup_present")) { // seems to be problems with the popup present on gtksourceview competion.
271 if (BuilderApplication.opt_debug && lvl == GLib.LogLevelFlags.LEVEL_CRITICAL) {
282 if (!BuilderApplication.opt_list_projects) {
285 print("Projects\n %s\n", Project.Project.listAllToString());
286 GLib.Process.exit(Posix.EXIT_SUCCESS);
289 Project.Project? compileProject()
292 if (BuilderApplication.opt_compile_project == null) {
295 Project.Project cur_project = null;
296 cur_project = Project.Project.getProjectByPath( BuilderApplication.opt_compile_project);
300 if (cur_project == null) {
301 GLib.error("invalid project %s, use --list-projects to show project ids",BuilderApplication.opt_compile_project);
311 void dropList(Project.Project? cur_project) {
314 if (cur_project== null || BuilderApplication.opt_drop_list == null) {
318 if (BuilderApplication.opt_compile_project == null) {
319 GLib.error("need a project %s, to use --drop-list",BuilderApplication.opt_compile_project);
321 if (cur_project.xtype != "Gtk") {
322 var rp = (Palete.Roo) cur_project.palete;
323 print("\n\nDropList:\n%s", geeArrayToString(rp.getDropList(BuilderApplication.opt_drop_list)));
324 print("\n\nChildList:\n%s", geeArrayToString(rp.getChildList(BuilderApplication.opt_drop_list, false)));
325 print("\n\nChildList \n(with props): %s", geeArrayToString(rp.getChildList(BuilderApplication.opt_drop_list, true)));
328 print("\n\nPropsList: %s", this.girArrayToString(rp.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.PROP)));
329 print("\n\nSignalList: %s", this.girArrayToString(rp.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.LISTENER)));
332 print("\n\nCtor Values: %s", rp.fqnToNode(BuilderApplication.opt_drop_list).toJsonString());
333 GLib.Process.exit(Posix.EXIT_SUCCESS);
338 var p = (Palete.Gtk) cur_project.palete;
340 print("\n\nDropList:\n%s", geeArrayToString(p.getDropList(BuilderApplication.opt_drop_list)));
341 print("\n\nChildList:\n%s", geeArrayToString(p.getChildList(BuilderApplication.opt_drop_list, false)));
342 print("\n\nChildList \n(with props): %s", geeArrayToString(p.getChildList(BuilderApplication.opt_drop_list, true)));
345 print("\n\nPropsList: %s", this.girArrayToString(p.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.PROP)));
346 print("\n\nSignalList: %s", this.girArrayToString(p.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.LISTENER)));
349 print("\n\nCtor Values: %s", p.fqnToNode(BuilderApplication.opt_drop_list).toJsonString());
351 GLib.Process.exit(Posix.EXIT_SUCCESS);
354 string geeArrayToString(Gee.ArrayList<string> ar)
357 foreach(var n in ar) {
362 string girArrayToString(Gee.HashMap<string,Palete.GirObject> map)
365 foreach(var gi in map.values) {
366 ret += "%s %s (%s)\n".printf(gi.type, gi.name, gi.propertyof);
374 void listFiles(Project.Project? cur_project)
376 if (!BuilderApplication.opt_list_files) {
379 if (cur_project == null) {
380 GLib.error("missing project, use --project to select which project");
382 print("Files for %s\n %s\n", cur_project.name, cur_project.listAllFilesToString());
383 GLib.Process.exit(Posix.EXIT_SUCCESS);
388 Test to see if the internal BJS reader/writer still outputs the same files.
389 -- probably need this for the generator as well.
392 void testBjs(Project.Project? cur_project)
394 if (!BuilderApplication.opt_bjs_test) {
397 if (cur_project == null) {
398 GLib.error("missing project, use --project to select which project");
400 print("Checking files\n");
402 var ar = cur_project.sortedFiles();
403 foreach(var file in ar) {
407 GLib.FileUtils.get_contents(file.path, out oldstr);
408 var outstr = file.toJsonString();
409 if (outstr != oldstr) {
411 GLib.FileUtils.set_contents("/tmp/" + file.name , outstr);
412 print("meld %s /tmp/%s\n", file.path, file.name);
413 //GLib.Process.exit(Posix.EXIT_SUCCESS);
415 print("# Files match %s\n", file.name);
418 } catch (FileError e) {
419 GLib.debug("Got error %s", e.message);
421 GLib.debug("Got error %s", e.message);
424 print("All files pass");
425 GLib.Process.exit(Posix.EXIT_SUCCESS);
428 void compileBjs(Project.Project? cur_project)
430 if (BuilderApplication.opt_bjs_compile == null) {
433 if (cur_project == null) {
434 GLib.error("missing project, use --project to select which project");
437 if (BuilderApplication.opt_bjs_compile == "all") {
439 var ar = cur_project.sortedFiles();
441 foreach(var file in ar) {
443 if (file is JsRender.PlainFile) {
449 var oldfn = file.targetName();
451 print("\n\n\n\nFile : %s\n", oldfn);
454 var outstr = file.toSourceCode();
456 /* line number checking
458 // check line numbers:
459 var bits = outstr.split("\n");
460 var end = bits.length;
461 for(var i = 0;i < end; i++) {
462 print("%i : %s\n", i+1 , bits[i]);
463 if (!bad && bits[i].has_prefix("/*") && !bits[i].has_prefix(("/*%d*" +"/").printf(i+1))) {
464 end = i + 5 > bits.length ? bits.length: (i + 5);
465 print ("^^^^ mismatch\null");
472 GLib.error("got bad file");
477 GLib.FileUtils.get_contents(oldfn, out oldstr);
478 if (outstr != oldstr) {
480 GLib.FileUtils.set_contents("/tmp/" + file.name + ".out", outstr);
481 print("meld %s /tmp/%s\n", oldfn, file.name + ".out");
482 //GLib.Process.exit(Posix.EXIT_SUCCESS);
484 //print("# Files match %s\n", file.name);
486 } catch (FileError e) {
487 GLib.debug("Got error %s", e.message);
489 GLib.debug("got error %s", e.message);
492 GLib.Process.exit(Posix.EXIT_SUCCESS);
498 var file = cur_project.getByRelPath(BuilderApplication.opt_bjs_compile);
500 // then compile them all, and compare them...
504 GLib.error("missing file %s in project %s", BuilderApplication.opt_bjs_compile, cur_project.name);
509 GLib.debug("Load items failed");
512 if (BuilderApplication.opt_bjs_compile_glade) {
513 var str = file.toGlade();
515 GLib.Process.exit(Posix.EXIT_SUCCESS);
518 //BuilderApplication.compileBjs();
520 var str = file.toSourceCode();
523 if (!BuilderApplication.opt_debug) {
525 GLib.Process.exit(Posix.EXIT_SUCCESS);
528 // dump the node tree
529 file.tree.dumpProps();
535 var str_ar = str.split("\n");
536 for(var i =0;i<str_ar.length;i++) {
537 var node = file.tree.lineToNode(i+1);
538 var prop = node == null ? null : node.lineToProp(i+1);
539 print("%d: %s : %s\n",
541 node == null ? "......" : (prop == null ? "????????" : prop.name),
546 GLib.Process.exit(Posix.EXIT_SUCCESS);
548 void languageServer(Project.Project? cur_project)
550 if (BuilderApplication.opt_language_server == null) {
553 if (cur_project == null) {
554 GLib.error("missing project, use --project to select which project");
556 var file = cur_project.getByRelPath(BuilderApplication.opt_language_server);
558 // then compile them all, and compare them...
559 GLib.error("missing file %s in project %s", BuilderApplication.opt_language_server, cur_project.name);
562 var ls = file.getLanguageServer();
564 GLib.error("No langauge server returned for file:%s", file.relpath);
567 //GLib.debug("started server - sleep 30 secs so you can gdb attach");
569 var loop = new MainLoop();
570 GLib.Timeout.add_seconds(1, () => {
572 GLib.debug("Sending document_open");
575 ls.document_open(file);
576 ls.document_save.begin( file, (o,res) => {
577 ls.document_save.end(res);
580 //ls.syntax.begin(file, (obj,res) => {
581 // ls.syntax.end(res);
592 GLib.Process.exit(Posix.EXIT_SUCCESS);
598 if (BuilderApplication.opt_compile_target == null) {
601 Palete.ValaSourceCompiler.buildApplication();
603 GLib.Process.exit(Posix.EXIT_SUCCESS);
609 if (!opt_pull_resources) {
612 var loop = new MainLoop();
613 Resources.singleton().updateProgress.connect((p,t) => {
614 print("Got %d/%d", (int) p,(int)t);
619 Resources.singleton().fetchStart();
621 GLib.Process.exit(Posix.EXIT_SUCCESS);
627 if (opt_test == null) {
633 help - list available tests
634 flutter-project - was try and read flutter data (but desnt work.)
637 case "flutter-project":
638 Project.Project.loadAll();
639 //var p = Project.Project.factory("Flutter", "/tmp/test-flutter");
640 /*var pa = p.palete as Palete.Flutter;
642 var ar = pa.getChildList("material.Scaffold");
643 GLib.debug("childlist for material.Scaffold is %s",
644 string.joinv( "\n-- ", ar)
646 ar = pa.getDropList("material.MaterialApp");
647 GLib.debug("droplist for material.MaterialApp is %s",
648 string.joinv( "\n-- ", ar)
657 print("Invalid test\n");
662 GLib.Process.exit(Posix.EXIT_SUCCESS);
666 // move to 'window colletction?
667 public static Gee.ArrayList<Xcls_MainWindow> windows;
668 public static GLib.ListStore windowlist;
670 public static void addWindow(Xcls_MainWindow w)
673 windowlist.append(w.windowstate);
674 BuilderApplication.windows.add(w);
680 public static void removeWindow(Xcls_MainWindow w)
682 //GLib.debug("remove window before = %d", BuilderApplication.windows.size);
683 BuilderApplication.windows.remove(w);
684 for(var i = 0 ; i < windowlist.get_n_items(); i++) {
685 var ws = windowlist.get_item(i) as WindowState;
686 if (ws.file.path == w.windowstate.file.path && ws.project.path == w.windowstate.project.path) {
687 windowlist.remove(i);
697 //GLib.debug("remove window after = %d", BuilderApplication.windows.size);
702 public static Xcls_MainWindow? getWindow(JsRender.JsRender file)
704 foreach(var ww in BuilderApplication.windows) {
705 if (ww.windowstate != null && ww.windowstate.file != null && ww.windowstate.file.path == file.path) {
713 public static void newWindow(JsRender.JsRender file, int line)
715 var w = new Xcls_MainWindow();
718 BuilderApplication.addWindow(w);
719 w.windowstate.init();
720 w.windowstate.fileViewOpen(file, false, line);
726 static int queue_update_compile_countdown = -1;
727 static uint queue_update_compile_id = 0;
729 public static void updateCompileResults( )
731 queue_update_compile_countdown = 2; // 1 second after last call.
732 if (queue_update_compile_id == 0) {
733 queue_update_compile_id = GLib.Timeout.add(100, () => {
734 if (queue_update_compile_countdown < 0) {
737 queue_update_compile_countdown--;
738 if (queue_update_compile_countdown < 0) {
739 realUpdateCompileResults();
748 public static void realUpdateCompileResults( )
753 foreach(var ww in BuilderApplication.windows) {
754 if (ww == null || ww.windowstate == null || ww.windowstate.project ==null) {
759 ww.windowstate.updateErrorMarksAll();
761 //GLib.debug("calling udate Errors of window %s", ww.windowstate.file.targetName());
763 ww.windowstate.left_tree.updateErrors();
764 ww.windowstate.left_props.updateErrors();
770 public static void showSpinnerLspLog(Palete.LanguageClientAction action, string message) {
772 var msg = action.to_string() + " " + message;
775 case Palete.LanguageClientAction.INIT:
776 case Palete.LanguageClientAction.LAUNCH:
777 case Palete.LanguageClientAction.ACCEPT:
778 BuilderApplication.showSpinner( "software-update-available", msg );
781 case Palete.LanguageClientAction.DIAG:
782 BuilderApplication.showSpinner( "format-justify-fill", msg);
785 case Palete.LanguageClientAction.DIAG_END:
786 BuilderApplication.showSpinner( "", "");
789 case Palete.LanguageClientAction.OPEN:
790 BuilderApplication.showSpinner( "document-open", msg);
792 case Palete.LanguageClientAction.SAVE:
793 BuilderApplication.showSpinner( "document-save", msg);
795 case Palete.LanguageClientAction.CLOSE:
796 BuilderApplication.showSpinner( "window.close", msg);
798 case Palete.LanguageClientAction.CHANGE:
799 BuilderApplication.showSpinner( "format-text-direction-ltr", msg);
801 case Palete.LanguageClientAction.TERM:
802 BuilderApplication.showSpinner( "media-playback-stop", msg);
804 case Palete.LanguageClientAction.COMPLETE:
805 BuilderApplication.showSpinner( "mail-send-recieve", msg);
808 case Palete.LanguageClientAction.COMPLETE_REPLY:
809 BuilderApplication.showSpinner( "face-cool", msg);
812 case Palete.LanguageClientAction.RESTART:
813 case Palete.LanguageClientAction.ERROR:
814 case Palete.LanguageClientAction.ERROR_START:
815 case Palete.LanguageClientAction.ERROR_RPC:
816 case Palete.LanguageClientAction.ERROR_REPLY:
817 BuilderApplication.showSpinner( "software-update-urgent", msg );
820 case Palete.LanguageClientAction.EXIT:
821 BuilderApplication.showSpinner( "face-sick", msg);
828 public static void showSpinner(string icon, string tooltip = "")
832 // doc change send: - spinner -
835 // ?? restart = software-update-urgent - crash?
838 foreach (var win in BuilderApplication.windows) {
840 win.statusbar_compile_spinner.start(icon, tooltip);
842 win.statusbar_compile_spinner.stop();