1 module dlangide.workspace.workspace; 2 3 import dlangide.workspace.project; 4 import dlangui.core.logger; 5 import std.path; 6 import std.file; 7 import std.json; 8 import std.utf; 9 import std.algorithm; 10 11 enum BuildOperation { 12 Build, 13 Clean, 14 Rebuild, 15 Run, 16 Upgrade 17 } 18 19 enum BuildConfiguration { 20 Debug, 21 Release, 22 Unittest 23 } 24 25 26 /** 27 Exception thrown on Workspace errors 28 */ 29 class WorkspaceException : Exception 30 { 31 this(string msg, string file = __FILE__, size_t line = __LINE__) 32 { 33 super(msg, file, line); 34 } 35 } 36 37 immutable string WORKSPACE_EXTENSION = ".dlangidews"; 38 39 /// return true if filename matches rules for workspace file names 40 bool isWorkspaceFile(string filename) { 41 return filename.endsWith(WORKSPACE_EXTENSION); 42 } 43 44 /// DlangIDE workspace 45 class Workspace : WorkspaceItem { 46 protected Project[] _projects; 47 48 protected BuildConfiguration _buildConfiguration; 49 50 this(string fname = null) { 51 super(fname); 52 } 53 54 @property Project[] projects() { 55 return _projects; 56 } 57 58 @property BuildConfiguration buildConfiguration() { return _buildConfiguration; } 59 @property void buildConfiguration(BuildConfiguration config) { _buildConfiguration = config; } 60 61 protected Project _startupProject; 62 63 @property Project startupProject() { return _startupProject; } 64 @property void startupProject(Project project) { _startupProject = project; } 65 66 protected void fillStartupProject() { 67 if (!_startupProject && _projects.length) 68 _startupProject = _projects[0]; 69 } 70 71 /// tries to find source file in one of projects, returns found project source file item, or null if not found 72 ProjectSourceFile findSourceFileItem(string filename) { 73 foreach (Project p; _projects) { 74 ProjectSourceFile res = p.findSourceFileItem(filename); 75 if (res) 76 return res; 77 } 78 return null; 79 } 80 81 /// find project in workspace by filename 82 Project findProject(string filename) { 83 foreach (Project p; _projects) { 84 if (p.filename.equal(filename)) 85 return p; 86 } 87 return null; 88 } 89 90 void addProject(Project p) { 91 _projects ~= p; 92 p.workspace = this; 93 fillStartupProject(); 94 } 95 96 string absoluteToRelativePath(string path) { 97 return toForwardSlashSeparator(relativePath(path, _dir)); 98 } 99 100 101 override bool save(string fname = null) { 102 if (fname.length > 0) 103 filename = fname; 104 try { 105 JSONValue content; 106 JSONValue[string] json; 107 json["name"] = JSONValue(toUTF8(_name)); 108 json["description"] = JSONValue(toUTF8(_description)); 109 JSONValue[string] projects; 110 foreach (Project p; _projects) { 111 string pname = toUTF8(p.name); 112 string ppath = absoluteToRelativePath(p.filename); 113 projects[pname] = JSONValue(ppath); 114 } 115 json["projects"] = projects; 116 content = json; 117 string js = content.toPrettyString; 118 write(_filename, js); 119 } catch (JSONException e) { 120 Log.e("Cannot parse json", e); 121 return false; 122 } catch (Exception e) { 123 Log.e("Cannot read workspace file", e); 124 return false; 125 } 126 return true; 127 } 128 129 override bool load(string fname = null) { 130 if (fname.length > 0) 131 filename = fname; 132 if (!exists(_filename) || !isFile(_filename)) { 133 return false; 134 } 135 Log.d("Reading workspace from file ", _filename); 136 137 try { 138 string jsonSource = readText!string(_filename); 139 JSONValue json = parseJSON(jsonSource); 140 _name = toUTF32(json["name"].str); 141 _description = toUTF32(json["description"].str); 142 Log.d("workspace name: ", _name); 143 Log.d("workspace description: ", _description); 144 JSONValue projects = json["projects"]; 145 foreach(string key, ref JSONValue value; projects) { 146 string path = value.str; 147 Log.d("project: ", key, " path:", path); 148 if (!isAbsolute(path)) 149 path = buildNormalizedPath(_dir, path); //, "dub.json" 150 Project project = new Project(path); 151 _projects ~= project; 152 project.load(); 153 154 } 155 string js = json.toPrettyString; 156 write(_filename, js); 157 } catch (JSONException e) { 158 Log.e("Cannot parse json", e); 159 return false; 160 } catch (Exception e) { 161 Log.e("Cannot read workspace file", e); 162 return false; 163 } 164 fillStartupProject(); 165 return true; 166 } 167 void close() { 168 } 169 } 170 171 /// global workspace 172 __gshared Workspace currentWorkspace;