diff --git a/BeefLibs/corlib/src/IRefCounted.bf b/BeefLibs/corlib/src/IRefCounted.bf index 1514b731..1a0b7ca3 100644 --- a/BeefLibs/corlib/src/IRefCounted.bf +++ b/BeefLibs/corlib/src/IRefCounted.bf @@ -47,6 +47,16 @@ namespace System } } + public void ReleaseLastRef() + { + int refCount = Interlocked.Decrement(ref mRefCount); + Debug.Assert(refCount == 0); + if (refCount == 0) + { + delete this; + } + } + public int ReleaseRefNoDelete() { int refCount = Interlocked.Decrement(ref mRefCount); diff --git a/IDE/src/BuildContext.bf b/IDE/src/BuildContext.bf index c0ebcdb8..82d73375 100644 --- a/IDE/src/BuildContext.bf +++ b/IDE/src/BuildContext.bf @@ -35,6 +35,7 @@ namespace IDE delete val; delete _; }; + public ScriptManager.Context mScriptContext = new .() ~ _.ReleaseLastRef(); public ScriptManager mScriptManager ~ delete _; public bool Failed @@ -152,7 +153,7 @@ namespace IDE if (mScriptManager == null) { - mScriptManager = new .(); + mScriptManager = new .(mScriptContext); mScriptManager.mProjectName = new String(project.mProjectName); mScriptManager.mIsBuildScript = true; mScriptManager.mSoftFail = true; diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 9d486683..8c180241 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -7459,6 +7459,7 @@ namespace IDE startInfo.SetFileName(fileName); startInfo.SetWorkingDirectory(workingDir); startInfo.SetArguments(args); + if ((!runFlags.HasFlag(.NoRedirect)) && (!runFlags.HasFlag(.NoWait))) { startInfo.RedirectStandardOutput = true; @@ -7848,6 +7849,16 @@ namespace IDE else if (next is ExecutionQueueCmd) { var executionQueueCmd = (ExecutionQueueCmd)next; + + ReplaceVariables(executionQueueCmd.mFileName); + ReplaceVariables(executionQueueCmd.mArgs); + ReplaceVariables(executionQueueCmd.mWorkingDir); + if (executionQueueCmd.mEnvVars != null) + { + for (let kv in executionQueueCmd.mEnvVars) + ReplaceVariables(kv.value); + } + var executionInstance = DoRun(executionQueueCmd.mFileName, executionQueueCmd.mArgs, executionQueueCmd.mWorkingDir, executionQueueCmd.mUseArgsFile, executionQueueCmd.mEnvVars, executionQueueCmd.mStdInData, executionQueueCmd.mRunFlags); if (executionInstance != null) { @@ -8724,6 +8735,8 @@ namespace IDE } else cmdErr = "Invalid number of arguments"; + case "Var": + break ReplaceBlock; } if (newString == null) @@ -8962,6 +8975,98 @@ namespace IDE return !hadError; } + public void ReplaceVariables(String result) + { + int i = 0; + for ( ; i < result.Length - 2; i++) + { + if ((result[i] == '$') && (result[i + 1] == '(')) + { + int parenPos = -1; + int openCount = 1; + bool inString = false; + char8 prevC = 0; + for (int checkIdx = i + 2; checkIdx < result.Length; checkIdx++) + { + char8 c = result[checkIdx]; + if (inString) + { + if (prevC == '\\') + { + // Slashed char + prevC = 0; + continue; + } + + if (c == '"') + inString = false; + } + else + { + if (c == '"') + inString = true; + else if (c == '(') + openCount++; + else if (c == ')') + { + openCount--; + if (openCount == 0) + { + parenPos = checkIdx; + break; + } + } + } + + prevC = c; + } + + if (parenPos != -1) + ReplaceBlock: + do + { + String replaceStr = scope String(result, i + 2, parenPos - i - 2); + + if (!replaceStr.StartsWith("Var ")) + continue; + + String varName = scope String(replaceStr, 4); + String newString = null; + + if (mScriptManager.mContext.mVars.TryGetValue(varName, var value)) + { + if (value.VariantType == typeof(String)) + { + newString = scope:ReplaceBlock String(value.Get()); + } + } + + if (newString == null) + { + if (mBuildContext != null) + { + if (mBuildContext.mScriptContext.mVars.TryGetValue(varName, var value)) + { + if (value.VariantType == typeof(String)) + { + newString = scope:ReplaceBlock String(value.Get()); + } + } + } + } + + if (newString != null) + { + result.Remove(i, parenPos - i + 1); + result.Insert(i, newString); + i--; + } + } + } + } + + } + public bool ResolveConfigString(String platformName, Workspace.Options workspaceOptions, Project project, Project.Options options, StringView configString, String errorContext, String outResult) { String errorString = scope String(); diff --git a/IDE/src/ScriptManager.bf b/IDE/src/ScriptManager.bf index 2dfe9e25..43d06f09 100644 --- a/IDE/src/ScriptManager.bf +++ b/IDE/src/ScriptManager.bf @@ -17,6 +17,19 @@ namespace IDE { public static ScriptManager sActiveManager; + public class Context : RefCounted + { + public Dictionary mVars = new .() ~ + { + for (var kv in _) + { + delete kv.key; + kv.value.Dispose(); + } + delete _; + }; + } + class Target { public class Cmd @@ -54,15 +67,8 @@ namespace IDE ScriptHelper mScriptHelper = new ScriptHelper(this) ~ delete _; Target mRoot = new Target() ~ delete _; - Dictionary mVars = new .() ~ - { - for (var kv in _) - { - delete kv.key; - kv.value.Dispose(); - } - delete _; - }; + public Context mContext ~ _.ReleaseRef(); + List mCmdList = new .() ~ DeleteContainerAndItems!(_); public bool mFailed; public bool mCancelled; @@ -93,8 +99,16 @@ namespace IDE } } - public this() + public this(Context context = null) { + if (context != null) + { + context.AddRef(); + mContext = context; + } + else + mContext = new Context(); + AddTarget(mScriptHelper); //Exec("OutputLine(\"Hey bro!\", 2)"); @@ -520,7 +534,7 @@ namespace IDE { String* keyPtr; Variant* valuePtr; - if (mVars.TryAdd(scope String(varName), out keyPtr, out valuePtr)) + if (mContext.mVars.TryAdd(scope String(varName), out keyPtr, out valuePtr)) *keyPtr = new String(varName); else valuePtr.Dispose(); @@ -2451,5 +2465,34 @@ namespace IDE Windows.MessageBoxA((Windows.HWnd)0, "Waiting for user input", "Beef IDE", 0); #endif } + + [IDECommand] + public void SetVal(String valName, String value) + { + bool added = mScriptManager.mContext.mVars.TryAdd(valName, var keyPtr, var valuePtr); + if (added) + *keyPtr = new String(valName); + else + valuePtr.Dispose(); + *valuePtr = Variant.Create(new String(value), true); + } + + [IDECommand] + public void ReadFile(String filePath, String valName) + { + String value = scope .(); + if (File.ReadAllText(filePath, value) case .Err) + { + mScriptManager.Fail(scope String()..AppendF("Failed to read file '{}'", filePath)); + return; + } + + bool added = mScriptManager.mContext.mVars.TryAdd(valName, var keyPtr, var valuePtr); + if (added) + *keyPtr = new String(valName); + else + valuePtr.Dispose(); + *valuePtr = Variant.Create(new String(value), true); + } } }