From cadd2abf84a684812e916f3fbe7d054bea414e0a Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Thu, 26 Feb 2015 17:43:12 +0300 Subject: [PATCH 1/9] show project dependencies --- src/ddebug/windows/mago.d | 7 +- src/dlangide/ui/frame.d | 20 +++-- src/dlangide/ui/wspanel.d | 2 +- src/dlangide/workspace/project.d | 95 +++++++++++++++++++++++- src/dlangide/workspace/workspace.d | 15 +++- views/res/mdpi/project-d-dependency.png | Bin 0 -> 330 bytes views/resources.list | 1 + 7 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 views/res/mdpi/project-d-dependency.png diff --git a/src/ddebug/windows/mago.d b/src/ddebug/windows/mago.d index e699369..4e5aa1b 100644 --- a/src/ddebug/windows/mago.d +++ b/src/ddebug/windows/mago.d @@ -79,6 +79,9 @@ void testMago() { Log.e("OLE 2 failed to initialize"); return; } + + IDebugCoreServer2 coreServer = null; + //hr = CoCreateInstance(&CLSID_MAGO, null, CLSCTX_ALL, &IID_IDebugEngine2, cast(void**)&piUnknown); hr = CoCreateInstance(&IID_MAGO_NATIVE_ENGINE, //CLSID_MAGO, null, @@ -118,10 +121,10 @@ void testMago() { envblock ~= 0; opts ~= 0; - + IDebugPort2 port; hr = debugEngineLaunch.LaunchSuspended ( null, - null, + port, exe.ptr,//LPCOLESTR args.ptr, dir.ptr, diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index 67ea836..43c702b 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -591,6 +591,16 @@ class IDEFrame : AppFrame { return false; } + private bool loadProject(Project project) { + if (!project.load()) { + _logPanel.logLine("Cannot read project " ~ project.filename); + window.showMessageBox(UIString("Cannot open project"d), UIString("Error occured while opening project "d ~ toUTF32(project.filename))); + return false; + } + _logPanel.logLine(toUTF32("Project file " ~ project.filename ~ " is opened ok")); + return true; + } + void openFileOrWorkspace(string filename) { if (filename.isWorkspaceFile) { Workspace ws = new Workspace(); @@ -605,13 +615,7 @@ class IDEFrame : AppFrame { } else if (filename.isProjectFile) { _logPanel.clear(); _logPanel.logLine("Trying to open project from " ~ filename); - Project project = new Project(); - if (!project.load(filename)) { - _logPanel.logLine("Cannot read project file " ~ filename); - window.showMessageBox(UIString("Cannot open project"d), UIString("Error occured while opening project"d)); - return; - } - _logPanel.logLine("Project file is opened ok"); + Project project = new Project(currentWorkspace, filename); string defWsFile = project.defWorkspaceFile; if (currentWorkspace) { Project existing = currentWorkspace.findProject(project.filename); @@ -628,6 +632,7 @@ class IDEFrame : AppFrame { } else if (result.id == IDEActions.AddToCurrentWorkspace) { // add to current currentWorkspace.addProject(project); + loadProject(project); currentWorkspace.save(); refreshWorkspace(); } @@ -656,6 +661,7 @@ class IDEFrame : AppFrame { ws.name = project.name; ws.description = project.description; ws.addProject(project); + loadProject(project); ws.save(defWsFile); setWorkspace(ws); _logPanel.logLine("Done"); diff --git a/src/dlangide/ui/wspanel.d b/src/dlangide/ui/wspanel.d index 934d157..6f9311b 100644 --- a/src/dlangide/ui/wspanel.d +++ b/src/dlangide/ui/wspanel.d @@ -147,7 +147,7 @@ class WorkspacePanel : DockWindow { TreeItem root = _tree.items.newChild(_workspace.filename, _workspace.name, "project-development"); root.intParam = ProjectItemType.Workspace; foreach(project; _workspace.projects) { - TreeItem p = root.newChild(project.filename, project.name, "project-d"); + TreeItem p = root.newChild(project.filename, project.name, project.isDependency ? "project-d-dependency" : "project-d"); p.intParam = ProjectItemType.Project; addProjectItems(p, project.items); } diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index 19977c1..7d741fa 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -9,6 +9,7 @@ import std.file; import std.json; import std.utf; import std.algorithm; +import std.process; /// return true if filename matches rules for workspace file names bool isProjectFile(string filename) { @@ -230,16 +231,24 @@ class Project : WorkspaceItem { protected ProjectFolder _items; protected ProjectSourceFile _mainSourceFile; protected SettingsFile _projectFile; + protected bool _isDependency; + protected string _dependencyVersion; protected string[] _sourcePaths; protected string[] _builderSourcePaths; - this(string fname = null) { + this(Workspace ws, string fname = null, string dependencyVersion = null) { super(fname); + _workspace = ws; _items = new ProjectFolder(fname); + _dependencyVersion = dependencyVersion; + _isDependency = _dependencyVersion.length > 0; } + @property bool isDependency() { return _isDependency; } + @property string dependencyVersion() { return _dependencyVersion; } + /// returns project's own source paths @property string[] sourcePaths() { return _sourcePaths; } /// returns project's own source paths @@ -346,6 +355,10 @@ class Project : WorkspaceItem { try { _name = toUTF32(_projectFile.getString("name")); + if (_isDependency) { + _name ~= "-"d; + _name ~= toUTF32(_dependencyVersion.startsWith("~") ? _dependencyVersion[1..$] : _dependencyVersion); + } _description = toUTF32(_projectFile.getString("description")); Log.d(" project name: ", _name); Log.d(" project description: ", _description); @@ -355,7 +368,8 @@ class Project : WorkspaceItem { Log.i("Project source paths: ", sourcePaths); Log.i("Builder source paths: ", builderSourcePaths); - + if (!_isDependency) + loadSelections(); } catch (JSONException e) { Log.e("Cannot parse json", e); return false; @@ -365,5 +379,82 @@ class Project : WorkspaceItem { } return true; } + + protected Project[] _dependencies; + @property Project[] dependencies() { return _dependencies; } + protected bool addDependency(Project dep) { + if (_workspace) + _workspace.addDependencyProject(dep); + _dependencies ~= dep; + return true; + } + bool loadSelections() { + _dependencies.length = 0; + DubPackageFinder finder = new DubPackageFinder(); + scope(exit) destroy(finder); + SettingsFile selectionsFile = new SettingsFile(buildNormalizedPath(_dir, "dub.selections.json")); + if (!selectionsFile.load()) + return false; + Setting versions = selectionsFile.objectByPath("versions"); + if (!versions) + return false; + string[string] versionMap = versions.strMap; + foreach(packageName, packageVersion; versionMap) { + string fn = finder.findPackage(packageName, packageVersion); + Log.d("dependency ", packageName, " ", packageVersion, " : ", fn ? fn : "NOT FOUND"); + if (fn) { + Project p = new Project(_workspace, fn, packageVersion); + if (p.load()) { + addDependency(p); + } else { + Log.e("cannot load dependency package ", packageName, " ", packageVersion, " from file ", fn); + destroy(p); + } + } + } + return true; + } +} + +class DubPackageFinder { + string systemDubPath; + string userDubPath; + string tempPath; + this() { + version(Windows){ + systemDubPath = buildNormalizedPath(environment.get("ProgramData"), "dub", "packages"); + userDubPath = buildNormalizedPath(environment.get("APPDATA"), "dub", "packages"); + tempPath = buildNormalizedPath(environment.get("TEMP"), "dub", "packages"); + } else version(Posix){ + systemDubPath = "/var/lib/dub/packages"; + userDubPath = buildNormalizedPath(environment.get("HOME"), ".dub", "packages"); + if(!userDubPath.isAbsolute) + userDubPath = buildNormalizedPath(getcwd(), userDubPath); + tempPath = "/tmp/packages"; + } + } + + protected string findPackage(string packageDir, string packageName, string packageVersion) { + string fullName = packageVersion.startsWith("~") ? packageName ~ "-" ~ packageVersion[1..$] : packageName ~ "-" ~ packageVersion; + string pathName = absolutePath(buildNormalizedPath(packageDir, fullName)); + if (pathName.exists && pathName.isDir) { + string fn = buildNormalizedPath(pathName, "dub.json"); + if (fn.exists && fn.isFile) + return fn; + fn = buildNormalizedPath(pathName, "package.json"); + if (fn.exists && fn.isFile) + return fn; + } + return null; + } + + string findPackage(string packageName, string packageVersion) { + string res = null; + res = findPackage(userDubPath, packageName, packageVersion); + if (res) + return res; + res = findPackage(systemDubPath, packageName, packageVersion); + return res; + } } diff --git a/src/dlangide/workspace/workspace.d b/src/dlangide/workspace/workspace.d index 02244f2..f219482 100644 --- a/src/dlangide/workspace/workspace.d +++ b/src/dlangide/workspace/workspace.d @@ -93,6 +93,17 @@ class Workspace : WorkspaceItem { fillStartupProject(); } + bool addDependencyProject(Project p) { + for (int i = 0; i < _projects.length; i++) { + if (_projects[i].filename.equal(p.filename)) { + _projects[i] = p; + return false; + } + } + addProject(p); + return true; + } + string absoluteToRelativePath(string path) { return toForwardSlashSeparator(relativePath(path, _dir)); } @@ -108,6 +119,8 @@ class Workspace : WorkspaceItem { json["description"] = JSONValue(toUTF8(_description)); JSONValue[string] projects; foreach (Project p; _projects) { + if (p.isDependency) + continue; // don't save dependency string pname = toUTF8(p.name); string ppath = absoluteToRelativePath(p.filename); projects[pname] = JSONValue(ppath); @@ -147,7 +160,7 @@ class Workspace : WorkspaceItem { Log.d("project: ", key, " path:", path); if (!isAbsolute(path)) path = buildNormalizedPath(_dir, path); //, "dub.json" - Project project = new Project(path); + Project project = new Project(this, path); _projects ~= project; project.load(); diff --git a/views/res/mdpi/project-d-dependency.png b/views/res/mdpi/project-d-dependency.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7bfcc896bf4cce8f8bb34fb1cb3d2bbc48a397 GIT binary patch literal 330 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4Pvb__>W@|Vg3MK}vQ zB8wRqxP?KOkzv*x37{Z*iKnkC`+X)UK1~JryrLICq3fP5jv*GO_Xaz19WoG@qw|&7 zZUIaDh3u~jY8$89Eor=0b>$w{*Jnp}|LA(<_}BHM`>d)7N0u$*V2g<`^Vu}{q)y`T z%aV2ncdfhqTY!Z@!6od^rI_pOlO9OkV>#$>?u)KVfLG)UftkJw`1_jIzfZes_Hhdn z!;RL3TO&O4D)9YNld0}KI-!_kVYWsz3KHWKZOU>+Mg@em6X5Co( z%oPsD&7=f1md;`86`p9!sHkVwIPdj+dtv7L44-~EJ`)r;v!$-##%?3F1?&=xd)FP{ YUXkFnvyYoi9q2^{Pgg&ebxsLQ09J>2%m4rY literal 0 HcmV?d00001 diff --git a/views/resources.list b/views/resources.list index 5d7ee6b..2d7728f 100644 --- a/views/resources.list +++ b/views/resources.list @@ -17,6 +17,7 @@ res/mdpi/edit-redo.png res/mdpi/edit-undo.png res/mdpi/edit-unindent.png res/mdpi/project-d.png +res/mdpi/project-d-dependency.png res/mdpi/project-development.png res/mdpi/project-open.png res/mdpi/run-build.png From fc419405ea6062d5e321d72f50ef3c901582ba09 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Thu, 26 Feb 2015 17:52:41 +0300 Subject: [PATCH 2/9] add dependency projects to import paths when running DCD --- dlangide.visualdproj | 2 +- src/dlangide/ui/dsourceedit.d | 2 +- src/dlangide/workspace/project.d | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/dlangide.visualdproj b/dlangide.visualdproj index 734db22..51867a8 100644 --- a/dlangide.visualdproj +++ b/dlangide.visualdproj @@ -72,7 +72,7 @@ 0 DebugInfo DCD 0 - Unicode USE_FREETYPE USE_LIBDPARSE USE_MAGO + Unicode USE_FREETYPE 0 3 0 diff --git a/src/dlangide/ui/dsourceedit.d b/src/dlangide/ui/dsourceedit.d index 9655fc1..2f5e824 100644 --- a/src/dlangide/ui/dsourceedit.d +++ b/src/dlangide/ui/dsourceedit.d @@ -83,7 +83,7 @@ class DSourceEdit : SourceEdit { /// returns project import paths - if file from project is opened in current editor string[] importPaths() { if (_projectSourceFile) - return _projectSourceFile.project.sourcePaths ~ _projectSourceFile.project.builderSourcePaths; + return _projectSourceFile.project.importPaths; return null; } diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index 7d741fa..3d1f9df 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -259,6 +259,29 @@ class Project : WorkspaceItem { return _builderSourcePaths; } + private static void addUnique(ref string[] dst, string[] items) { + foreach(item; items) { + bool found = false; + foreach(existing; dst) { + if (item.equal(existing)) { + found = true; + break; + } + } + if (!found) + dst ~= item; + } + } + @property string[] importPaths() { + string[] res; + addUnique(res, sourcePaths); + addUnique(res, builderSourcePaths); + foreach(dep; _dependencies) { + addUnique(res, dep.sourcePaths); + } + return res; + } + string relativeToAbsolutePath(string path) { if (isAbsolute(path)) return path; From b9b1b0e10b7df57a017fd30ca392d01cff90128c Mon Sep 17 00:00:00 2001 From: Anton Gushcha Date: Thu, 26 Feb 2015 17:54:34 +0300 Subject: [PATCH 3/9] Combobox to select project configuration --- src/dlangide/ui/commands.d | 2 ++ src/dlangide/ui/frame.d | 11 +++++++++++ src/dlangide/workspace/workspace.d | 7 ++++++- views/res/i18n/en.ini | 1 + views/res/i18n/ru.ini | 1 + 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/dlangide/ui/commands.d b/src/dlangide/ui/commands.d index d7fd6b6..f1b68ba 100644 --- a/src/dlangide/ui/commands.d +++ b/src/dlangide/ui/commands.d @@ -16,6 +16,7 @@ enum IDEActions : int { FileClose, FileExit, EditPreferences, + ProjectConfigurations, BuildConfigurations, BuildWorkspace, RebuildWorkspace, @@ -68,6 +69,7 @@ const Action ACTION_FILE_EXIT = new Action(IDEActions.FileExit, "MENU_FILE_EXIT" const Action ACTION_WORKSPACE_BUILD = new Action(IDEActions.BuildWorkspace, "MENU_BUILD_WORKSPACE_BUILD"c); const Action ACTION_WORKSPACE_REBUILD = new Action(IDEActions.RebuildWorkspace, "MENU_BUILD_WORKSPACE_REBUILD"c); const Action ACTION_WORKSPACE_CLEAN = new Action(IDEActions.CleanWorkspace, "MENU_BUILD_WORKSPACE_CLEAN"c); +const Action ACTION_PROJECT_CONFIGURATIONS = new Action(IDEActions.ProjectConfigurations, "MENU_PROJECT_CONFIGURATIONS"c); const Action ACTION_BUILD_CONFIGURATIONS = new Action(IDEActions.BuildConfigurations, "MENU_BUILD_CONFIGURATIONS"c); const Action ACTION_PROJECT_BUILD = new Action(IDEActions.BuildProject, "MENU_BUILD_PROJECT_BUILD"c, "run-build", KeyCode.F7, 0); const Action ACTION_PROJECT_REBUILD = new Action(IDEActions.RebuildProject, "MENU_BUILD_PROJECT_REBUILD"c, "run-build-clean", KeyCode.F7, KeyFlag.Control); diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index 67ea836..357ef3b 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -434,6 +434,17 @@ class IDEFrame : AppFrame { tb.addButtons(ACTION_FILE_OPEN, ACTION_FILE_SAVE, ACTION_SEPARATOR); tb.addButtons(ACTION_DEBUG_START); + + ToolBarComboBox cbProjectConfiguration = new ToolBarComboBox("projectConfig", [DEFAULT_PROJECT_CONFIGURATION]); + cbProjectConfiguration.onItemClickListener = delegate(Widget source, int index) { + if (currentWorkspace) { + currentWorkspace.projectConfiguration = cbProjectConfiguration.text; + } + return true; + }; + cbProjectConfiguration.action = ACTION_PROJECT_CONFIGURATIONS; + tb.addControl(cbProjectConfiguration); + ToolBarComboBox cbBuildConfiguration = new ToolBarComboBox("buildConfig", ["Debug"d, "Release"d, "Unittest"d]); cbBuildConfiguration.onItemClickListener = delegate(Widget source, int index) { if (currentWorkspace && index < 3) { diff --git a/src/dlangide/workspace/workspace.d b/src/dlangide/workspace/workspace.d index 02244f2..7181047 100644 --- a/src/dlangide/workspace/workspace.d +++ b/src/dlangide/workspace/workspace.d @@ -35,6 +35,7 @@ class WorkspaceException : Exception } immutable string WORKSPACE_EXTENSION = ".dlangidews"; +immutable dstring DEFAULT_PROJECT_CONFIGURATION = "default"d; /// return true if filename matches rules for workspace file names bool isWorkspaceFile(string filename) { @@ -46,7 +47,8 @@ class Workspace : WorkspaceItem { protected Project[] _projects; protected BuildConfiguration _buildConfiguration; - + protected dstring _projectConfiguration = DEFAULT_PROJECT_CONFIGURATION; + this(string fname = null) { super(fname); } @@ -58,6 +60,9 @@ class Workspace : WorkspaceItem { @property BuildConfiguration buildConfiguration() { return _buildConfiguration; } @property void buildConfiguration(BuildConfiguration config) { _buildConfiguration = config; } + @property dstring projectConfiguration() { return _projectConfiguration; } + @property void projectConfiguration(dstring config) { _projectConfiguration = config; } + protected Project _startupProject; @property Project startupProject() { return _startupProject; } diff --git a/views/res/i18n/en.ini b/views/res/i18n/en.ini index 1939fe4..68922e4 100644 --- a/views/res/i18n/en.ini +++ b/views/res/i18n/en.ini @@ -32,6 +32,7 @@ MENU_BUILD_PROJECT_BUILD=Build Project MENU_BUILD_PROJECT_REBUILD=Rebuild Project MENU_BUILD_PROJECT_CLEAN=Clean Project MENU_PROJECT=&PROJECT +MENU_PROJECT_CONFIGURATIONS=Project configurations MENU_PROJECT_SET_AS_STARTUP=Set as Startup Project MENU_PROJECT_SETTINGS=Project Settings MENU_PROJECT_REFRESH=Refresh Workspace Items diff --git a/views/res/i18n/ru.ini b/views/res/i18n/ru.ini index 82f24a2..4598b3b 100644 --- a/views/res/i18n/ru.ini +++ b/views/res/i18n/ru.ini @@ -11,6 +11,7 @@ MENU_EDIT_CUT=Вырезать MENU_EDIT_UNDO=&Отмена MENU_EDIT_REDO=&Повторить MENU_EDIT_PREFERENCES=&Настройки +MENU_PROJECT_CONFIGURATIONS=Конфигурации проекта MENU_VIEW=&Вид MENU_VIEW_LANGUAGE=&Язык интерфейса MENU_VIEW_LANGUAGE_EN=English From 6de6b99afebab8d9decbb6e0cff74cec2edf3c7b Mon Sep 17 00:00:00 2001 From: Anton Gushcha Date: Thu, 26 Feb 2015 17:59:24 +0300 Subject: [PATCH 4/9] project config support for builder --- src/dlangide/builders/builder.d | 8 +++++++- src/dlangide/ui/frame.d | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/dlangide/builders/builder.d b/src/dlangide/builders/builder.d index 6f07359..b4880c5 100644 --- a/src/dlangide/builders/builder.d +++ b/src/dlangide/builders/builder.d @@ -16,6 +16,7 @@ class Builder : BackgroundOperationWatcher { protected ExternalProcess _extprocess; protected OutputPanel _log; protected ProtectedTextStorage _box; + protected dstring _projectConfig; protected BuildConfiguration _buildConfig; protected BuildOperation _buildOp; protected bool _verbose; @@ -23,8 +24,9 @@ class Builder : BackgroundOperationWatcher { @property Project project() { return _project; } @property void project(Project p) { _project = p; } - this(AppFrame frame, Project project, OutputPanel log, BuildConfiguration buildConfig, BuildOperation buildOp, bool verbose) { + this(AppFrame frame, Project project, OutputPanel log, dstring projectConfig, BuildConfiguration buildConfig, BuildOperation buildOp, bool verbose) { super(frame); + _projectConfig = projectConfig; _buildConfig = buildConfig; _buildOp = buildOp; _verbose = verbose; @@ -83,6 +85,10 @@ class Builder : BackgroundOperationWatcher { } } + if(_projectConfig != DEFAULT_PROJECT_CONFIGURATION) { + params ~= "--config=".dup ~ cast(string)(_projectConfig); + } + if (_verbose) params ~= "-v".dup; diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index 357ef3b..7dcc9c0 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -697,7 +697,7 @@ class IDEFrame : AppFrame { _logPanel.logLine("No project is opened"); return; } - Builder op = new Builder(this, currentWorkspace.startupProject, _logPanel, currentWorkspace.buildConfiguration, buildOp, false); + Builder op = new Builder(this, currentWorkspace.startupProject, _logPanel, currentWorkspace.projectConfiguration, currentWorkspace.buildConfiguration, buildOp, false); setBackgroundOperation(op); } From fa94e9bbf92dbc236c58748baaa4271cad3a9966 Mon Sep 17 00:00:00 2001 From: Anton Gushcha Date: Thu, 26 Feb 2015 20:19:53 +0300 Subject: [PATCH 5/9] Loading project configs from projects --- src/dlangide/builders/builder.d | 8 ++-- src/dlangide/ui/frame.d | 45 +++++++++++++++++---- src/dlangide/workspace/project.d | 64 +++++++++++++++++++++++++++++- src/dlangide/workspace/workspace.d | 33 ++++++++++----- 4 files changed, 128 insertions(+), 22 deletions(-) diff --git a/src/dlangide/builders/builder.d b/src/dlangide/builders/builder.d index b4880c5..3cadd4a 100644 --- a/src/dlangide/builders/builder.d +++ b/src/dlangide/builders/builder.d @@ -16,7 +16,7 @@ class Builder : BackgroundOperationWatcher { protected ExternalProcess _extprocess; protected OutputPanel _log; protected ProtectedTextStorage _box; - protected dstring _projectConfig; + protected ProjectConfiguration _projectConfig; protected BuildConfiguration _buildConfig; protected BuildOperation _buildOp; protected bool _verbose; @@ -24,7 +24,7 @@ class Builder : BackgroundOperationWatcher { @property Project project() { return _project; } @property void project(Project p) { _project = p; } - this(AppFrame frame, Project project, OutputPanel log, dstring projectConfig, BuildConfiguration buildConfig, BuildOperation buildOp, bool verbose) { + this(AppFrame frame, Project project, OutputPanel log, ProjectConfiguration projectConfig, BuildConfiguration buildConfig, BuildOperation buildOp, bool verbose) { super(frame); _projectConfig = projectConfig; _buildConfig = buildConfig; @@ -85,8 +85,8 @@ class Builder : BackgroundOperationWatcher { } } - if(_projectConfig != DEFAULT_PROJECT_CONFIGURATION) { - params ~= "--config=".dup ~ cast(string)(_projectConfig); + if(_projectConfig.name != ProjectConfiguration.DEFAULT_NAME) { + params ~= "--config=".dup ~ _projectConfig.name; } if (_verbose) diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index 7dcc9c0..b4a2e0a 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -57,9 +57,33 @@ class BackgroundOperationWatcherTest : BackgroundOperationWatcher { } } +/// Subclass of toolbars that can update their items +class UpdateableToolBarComboBox : ToolBarComboBox { + this(string id, dstring[] items) { + super(id, items); + } + + @property items(dstring[] newItems) { + _adapter.items = newItems; + if(newItems.length > 0) { + selectedItemIndex = 0; + } + requestLayout(); + } + + @property dstring selectedItem() { + size_t index = _selectedItemIndex; + if(index < 0 || index >= _adapter.itemCount) return ""; + + return _adapter.items.get(index); + } +} + /// DIDE app frame class IDEFrame : AppFrame { + private UpdateableToolBarComboBox projectConfigurationCombo; + MenuItem mainMenuItems; WorkspacePanel _wsPanel; OutputPanel _logPanel; @@ -435,15 +459,15 @@ class IDEFrame : AppFrame { tb.addButtons(ACTION_DEBUG_START); - ToolBarComboBox cbProjectConfiguration = new ToolBarComboBox("projectConfig", [DEFAULT_PROJECT_CONFIGURATION]); - cbProjectConfiguration.onItemClickListener = delegate(Widget source, int index) { + projectConfigurationCombo = new UpdateableToolBarComboBox("projectConfig", [ProjectConfiguration.DEFAULT_NAME.to!dstring]); + projectConfigurationCombo.onItemClickListener = delegate(Widget source, int index) { if (currentWorkspace) { - currentWorkspace.projectConfiguration = cbProjectConfiguration.text; + currentWorkspace.setStartupProjectConfiguration(projectConfigurationCombo.selectedItem.to!string); } return true; }; - cbProjectConfiguration.action = ACTION_PROJECT_CONFIGURATIONS; - tb.addControl(cbProjectConfiguration); + projectConfigurationCombo.action = ACTION_PROJECT_CONFIGURATIONS; + tb.addControl(projectConfigurationCombo); ToolBarComboBox cbBuildConfiguration = new ToolBarComboBox("buildConfig", ["Debug"d, "Release"d, "Unittest"d]); cbBuildConfiguration.onItemClickListener = delegate(Widget source, int index) { @@ -604,7 +628,7 @@ class IDEFrame : AppFrame { void openFileOrWorkspace(string filename) { if (filename.isWorkspaceFile) { - Workspace ws = new Workspace(); + Workspace ws = new Workspace(this); if (ws.load(filename)) { askForUnsavedEdits(delegate() { setWorkspace(ws); @@ -663,7 +687,7 @@ class IDEFrame : AppFrame { string defWsFile = project.defWorkspaceFile; _logPanel.logLine("Creating new workspace " ~ defWsFile); // new ws - Workspace ws = new Workspace(); + Workspace ws = new Workspace(this); ws.name = project.name; ws.description = project.description; ws.addProject(project); @@ -700,7 +724,12 @@ class IDEFrame : AppFrame { Builder op = new Builder(this, currentWorkspace.startupProject, _logPanel, currentWorkspace.projectConfiguration, currentWorkspace.buildConfiguration, buildOp, false); setBackgroundOperation(op); } - + + /// updates list of available configurations + void setProjectConfigurations(dstring[] items) { + projectConfigurationCombo.items = items; + } + /// handle files dropped to application window void onFilesDropped(string[] filenames) { //Log.d("onFilesDropped(", filenames, ")"); diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index 19977c1..916c226 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -223,6 +223,59 @@ string[] dmdSourcePaths() { return res; } +/// Stores info about project configuration +struct ProjectConfiguration { + /// name used to build the project + string name; + /// type, for libraries one can run tests, for apps - execute them + Type type; + + /// How to display default configuration in ui + immutable static string DEFAULT_NAME = "default"; + /// Default project configuration + immutable static ProjectConfiguration DEFAULT = ProjectConfiguration(DEFAULT_NAME, Type.Default); + + /// Type of configuration + enum Type { + Default, + Executable, + Library + } + + private static Type parseType(string s) + { + switch(s) + { + case "executable": return Type.Executable; + case "library": return Type.Library; + case "dynamicLibrary": return Type.Library; + case "staticLibrary": return Type.Library; + default: return Type.Default; + } + } + + /// parsing from setting file + static ProjectConfiguration[string] load(Setting s) + { + ProjectConfiguration[string] res = [DEFAULT_NAME: DEFAULT]; + if(s.map is null || "configurations" !in s.map || s.map["configurations"].array is null) + return res; + + foreach(conf; s.map["configurations"].array) + { + if(conf.map is null || "name" !in conf.map) continue; + Type t = Type.Default; + if("targetType" in conf.map) { + t = parseType(conf.map["targetType"].str); + } + string confName = conf.map["name"].str; + res[confName] = ProjectConfiguration(confName, t); + } + + return res; + } +} + /// DLANGIDE D project class Project : WorkspaceItem { protected Workspace _workspace; @@ -233,13 +286,19 @@ class Project : WorkspaceItem { protected string[] _sourcePaths; protected string[] _builderSourcePaths; - + protected ProjectConfiguration[string] _configurations; this(string fname = null) { super(fname); _items = new ProjectFolder(fname); } + /// returns project configurations + @property const(ProjectConfiguration[string]) configurations() const + { + return _configurations; + } + /// returns project's own source paths @property string[] sourcePaths() { return _sourcePaths; } /// returns project's own source paths @@ -356,6 +415,9 @@ class Project : WorkspaceItem { Log.i("Project source paths: ", sourcePaths); Log.i("Builder source paths: ", builderSourcePaths); + _configurations = ProjectConfiguration.load(_projectFile); + Log.i("Project configurations: ", _configurations); + } catch (JSONException e) { Log.e("Cannot parse json", e); return false; diff --git a/src/dlangide/workspace/workspace.d b/src/dlangide/workspace/workspace.d index 7181047..2274728 100644 --- a/src/dlangide/workspace/workspace.d +++ b/src/dlangide/workspace/workspace.d @@ -1,10 +1,13 @@ module dlangide.workspace.workspace; import dlangide.workspace.project; +import dlangide.ui.frame; import dlangui.core.logger; +import std.conv; import std.path; import std.file; import std.json; +import std.range; import std.utf; import std.algorithm; @@ -35,7 +38,6 @@ class WorkspaceException : Exception } immutable string WORKSPACE_EXTENSION = ".dlangidews"; -immutable dstring DEFAULT_PROJECT_CONFIGURATION = "default"d; /// return true if filename matches rules for workspace file names bool isWorkspaceFile(string filename) { @@ -45,12 +47,14 @@ bool isWorkspaceFile(string filename) { /// DlangIDE workspace class Workspace : WorkspaceItem { protected Project[] _projects; - - protected BuildConfiguration _buildConfiguration; - protected dstring _projectConfiguration = DEFAULT_PROJECT_CONFIGURATION; - this(string fname = null) { + protected IDEFrame _frame; + protected BuildConfiguration _buildConfiguration; + protected ProjectConfiguration _projectConfiguration = ProjectConfiguration.DEFAULT; + + this(IDEFrame frame, string fname = null) { super(fname); + _frame = frame; } @property Project[] projects() { @@ -60,17 +64,28 @@ class Workspace : WorkspaceItem { @property BuildConfiguration buildConfiguration() { return _buildConfiguration; } @property void buildConfiguration(BuildConfiguration config) { _buildConfiguration = config; } - @property dstring projectConfiguration() { return _projectConfiguration; } - @property void projectConfiguration(dstring config) { _projectConfiguration = config; } + @property ProjectConfiguration projectConfiguration() { return _projectConfiguration; } + @property void projectConfiguration(ProjectConfiguration config) { _projectConfiguration = config; } protected Project _startupProject; @property Project startupProject() { return _startupProject; } - @property void startupProject(Project project) { _startupProject = project; } + @property void startupProject(Project project) { + _startupProject = project; + _frame.setProjectConfigurations(project.configurations.keys.map!(k => k.to!dstring).array); + } + /// setups currrent project configuration by name + void setStartupProjectConfiguration(string conf) + { + if(_startupProject && conf in _startupProject.configurations) { + _projectConfiguration = _startupProject.configurations[conf]; + } + } + protected void fillStartupProject() { if (!_startupProject && _projects.length) - _startupProject = _projects[0]; + startupProject = _projects[0]; } /// tries to find source file in one of projects, returns found project source file item, or null if not found From f2aa2d5426464de07c743267cb466f2670cb39fd Mon Sep 17 00:00:00 2001 From: Anton Gushcha Date: Thu, 26 Feb 2015 20:32:15 +0300 Subject: [PATCH 6/9] Adjusting builder to run tests on libraries configurations --- src/dlangide/builders/builder.d | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dlangide/builders/builder.d b/src/dlangide/builders/builder.d index 3cadd4a..0886a87 100644 --- a/src/dlangide/builders/builder.d +++ b/src/dlangide/builders/builder.d @@ -64,7 +64,11 @@ class Builder : BackgroundOperationWatcher { } else if (_buildOp == BuildOperation.Clean) { params ~= "clean".dup; } else if (_buildOp == BuildOperation.Run) { - params ~= "run".dup; + if (_projectConfig.type == ProjectConfiguration.Type.Library) { + params ~= "test".dup; + } else { + params ~= "run".dup; + } } else if (_buildOp == BuildOperation.Upgrade) { params ~= "upgrade".dup; params ~= "--force-remove".dup; From e9544d2f83d6f757632b2639c2a891c8d3edcda8 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Fri, 27 Feb 2015 12:19:20 +0300 Subject: [PATCH 7/9] refactor project configurations reading code --- src/dlangide/workspace/project.d | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index af283af..5728c43 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -259,20 +259,18 @@ struct ProjectConfiguration { static ProjectConfiguration[string] load(Setting s) { ProjectConfiguration[string] res = [DEFAULT_NAME: DEFAULT]; - if(s.map is null || "configurations" !in s.map || s.map["configurations"].array is null) + Setting configs = s.objectByPath("configurations"); + if(configs is null || configs.type != SettingType.ARRAY) return res; - foreach(conf; s.map["configurations"].array) - { - if(conf.map is null || "name" !in conf.map) continue; + foreach(conf; configs) { + if(!conf.isObject) continue; Type t = Type.Default; - if("targetType" in conf.map) { - t = parseType(conf.map["targetType"].str); - } - string confName = conf.map["name"].str; - res[confName] = ProjectConfiguration(confName, t); + if(auto typeName = conf.getString("targetType")) + t = parseType(typeName); + if (string confName = conf.getString("name")) + res[confName] = ProjectConfiguration(confName, t); } - return res; } } From 0b3785f2f318da28b0d59ff695ea28ec0b4b7d88 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Fri, 27 Feb 2015 12:37:19 +0300 Subject: [PATCH 8/9] add Gitter, TravisCI and donation buttons --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index dc2e729..0e189ac 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ GitHub page: [https://github.com/buggins/dlangide](https://github.com/buggins/dl DlangUI project GitHub page: [https://github.com/buggins/dlangui](https://github.com/buggins/dlangui) +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/buggins/dlangide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/buggins/dlangide.svg?branch=master)](https://travis-ci.org/buggins/dlangide) [![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H2ADZV8S6TDHQ "Donate once-off to this project using Paypal") + DCD integration =============== From 57d720e53b6e442e87415a9d0f928571518a2498 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Fri, 27 Feb 2015 13:19:54 +0300 Subject: [PATCH 9/9] update readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e189ac..93b6598 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,18 @@ Currently supported features: * Build and run project with DUB * Build log highlight and navigation to place of error or warning by clicking on log line * DUB dependencies update +* DUB package configuration selection (implemented by NCrashed) +* Dependency projects are shown in workspace tree Source editor features: * D language source code syntax highlight (basic) * Indent / unindent text with Tab and Shift+Tab or Ctrl+\[ and Ctrl+\] * Toggle line or block comments by Ctrl+/ and Ctrl+Shift+/ -* Select word by mouse double click * D source code autocompletion by Ctrl+Space or Ctrl+Shift+G (using DCD) * D source code Go To Definition by Ctrl+G or F12 (using DCD) +* D source code Smart Indents +* Select word by mouse double click ![screenshot](http://buggins.github.io/dlangui/screenshots/screenshot-dlangide.png "screenshot")