graccesscli: extend script editor surface — --field, --lock-trigger-type, scripts delete
Three additions to the script editor commands. Each one closes a real gap surfaced by the round-trip-test against \$DelmiaReceiver.ProcessRecipe. 1. `object scripts set --field <name>` — explicit text-field selection. Previously `scripts set` always wrote to <Name>.ExecuteText (via ScriptAttributeName's default). To rewrite DeclarationsText / StartupText / ShutdownText / OnScanText / OffScanText / Expression, callers had to pass the full attribute name as `--script Foo.StartupText`, which is brittle. The new `--field` flag accepts any of the seven canonical ScriptTextSuffixes and composes <script>.<field> directly. Validates against the suffix list so an unrecognised --field surfaces a friendly error rather than a downstream FindAttributeForMutation failure. Default behavior (no --field) is unchanged: ExecuteText. 2. `object scripts settings set --lock-trigger-type` — parallel to the existing --lock-trigger-period. After writing TriggerType the new flag calls SetLocked(MxLockedInMe), matching the lock pattern on the period field. Without it, --trigger-type writes the value but leaves the attribute unlocked. 3. `object scripts delete` — script-named alias for the existing extension-delete subcommand. Wraps obj.DeleteExtensionPrimitive( "ScriptExtension", scriptName) inside AtomicObjectEdit (checkout / save / checkin). Removes the burden of remembering the generic `--extension-type ScriptExtension --primitive <Name>` form. Test count delta: 61 -> 63 (+2 command-shape assertions for the new ObjectScriptsSetCommand and ObjectScriptsDeleteCommand). Live round-trip-test against \$DelmiaReceiver.ProcessRecipe: - `--field DeclarationsText` write composed `ProcessRecipe.DeclarationsText`, CheckOut/Save/CheckIn all returned OK. - `--field ExecuteText` round-trip same. - A subsequent re-read shows the original body, suggesting that IAttribute.SetValue silently no-ops for ScriptExtension text fields on this GRAccess version (or the package-export reader pulls from a different snapshot than the just-saved revision). This is upstream of the editor surface — the new flags route correctly to the same SetValue path that scripts set already used. Diagnosing the SetValue ineffectiveness for script-text fields is a separate followup that should look at IScriptExtension-specific COM interfaces (per docs/script-parsing.md:8 "Object-level scripts are less direct"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -434,7 +434,16 @@ namespace ZB.MOM.WW.GRAccess.Cli.Commands
|
||||
[CommandOption("file", Description = "Script source file", IsRequired = true)]
|
||||
public string File { get; init; }
|
||||
|
||||
public override Dictionary<string, object> Args() { var args = base.Args(); args["file"] = File; return args; }
|
||||
[CommandOption("field", Description = "Script-text field to write: ExecuteText (default), DeclarationsText, StartupText, ShutdownText, OnScanText, OffScanText, Expression. Pass to target a non-body field; omit to default to ExecuteText.")]
|
||||
public string Field { get; init; } = "";
|
||||
|
||||
public override Dictionary<string, object> Args() { var args = base.Args(); args["file"] = File; args["field"] = Field; return args; }
|
||||
}
|
||||
|
||||
[Command("object scripts delete", Description = "Delete a ScriptExtension primitive from an object")]
|
||||
public sealed class ObjectScriptsDeleteCommand : ObjectScriptsGetCommand
|
||||
{
|
||||
public override string Subcommand => "scripts-delete";
|
||||
}
|
||||
|
||||
public abstract class ObjectScriptSettingsCommandBase : ObjectScriptsGetCommand
|
||||
@@ -451,6 +460,9 @@ namespace ZB.MOM.WW.GRAccess.Cli.Commands
|
||||
[CommandOption("lock-trigger-period", Description = "Lock TriggerPeriod in this object after setting it")]
|
||||
public bool LockTriggerPeriod { get; init; }
|
||||
|
||||
[CommandOption("lock-trigger-type", Description = "Lock TriggerType in this object after setting it")]
|
||||
public bool LockTriggerType { get; init; }
|
||||
|
||||
public override Dictionary<string, object> Args()
|
||||
{
|
||||
var args = base.Args();
|
||||
@@ -458,6 +470,7 @@ namespace ZB.MOM.WW.GRAccess.Cli.Commands
|
||||
args["trigger-type"] = TriggerType;
|
||||
args["expression"] = Expression;
|
||||
args["lock-trigger-period"] = LockTriggerPeriod;
|
||||
args["lock-trigger-type"] = LockTriggerType;
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,9 +142,18 @@ namespace ZB.MOM.WW.GRAccess.Cli.GRAccess
|
||||
case "scripts-create":
|
||||
RequireConfirm(args, Arg(args, "name"));
|
||||
return AtomicObjectEdit(FindSingleObject(galaxy, Kind(args), Arg(args, "name")), obj => ObjectScriptCreate(galaxy, obj, args));
|
||||
case "scripts-delete":
|
||||
return AtomicObjectEdit(FindSingleObject(galaxy, Kind(args), Arg(args, "name")), obj =>
|
||||
{
|
||||
var scriptName = Arg(args, "script");
|
||||
if (string.IsNullOrWhiteSpace(scriptName))
|
||||
throw new ArgumentException("Script name is required.");
|
||||
obj.DeleteExtensionPrimitive("ScriptExtension", scriptName);
|
||||
return CommandSummary(obj, $"Delete script {scriptName}");
|
||||
});
|
||||
case "scripts-set":
|
||||
RequireConfirm(args, Arg(args, "name"));
|
||||
return AtomicObjectEdit(FindSingleObject(galaxy, Kind(args), Arg(args, "name")), obj => ObjectScriptSet(galaxy, obj, Arg(args, "script"), Arg(args, "file")));
|
||||
return AtomicObjectEdit(FindSingleObject(galaxy, Kind(args), Arg(args, "name")), obj => ObjectScriptSet(galaxy, obj, Arg(args, "script"), Arg(args, "file"), Arg(args, "field", string.Empty)));
|
||||
case "scripts-settings-set":
|
||||
RequireConfirm(args, Arg(args, "name"));
|
||||
return AtomicObjectEdit(FindSingleObject(galaxy, Kind(args), Arg(args, "name")), obj => ObjectScriptSettingsSet(obj, args));
|
||||
@@ -1590,14 +1599,28 @@ namespace ZB.MOM.WW.GRAccess.Cli.GRAccess
|
||||
};
|
||||
}
|
||||
|
||||
private static string ObjectScriptSet(IGalaxy galaxy, IgObject obj, string scriptName, string file)
|
||||
private static string ObjectScriptSet(IGalaxy galaxy, IgObject obj, string scriptName, string file, string field = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(file))
|
||||
throw new ArgumentException("Script source --file is required.");
|
||||
if (!File.Exists(file))
|
||||
throw new FileNotFoundException("Script source file was not found.", file);
|
||||
|
||||
var attributeName = ScriptAttributeName(scriptName);
|
||||
string attributeName;
|
||||
if (!string.IsNullOrWhiteSpace(field))
|
||||
{
|
||||
// Validate against the canonical script-text suffix list so
|
||||
// callers get a friendly error before we try to write a
|
||||
// nonexistent attribute.
|
||||
if (!ScriptTextSuffixes.Any(s => string.Equals(s, field, StringComparison.OrdinalIgnoreCase)))
|
||||
throw new ArgumentException($"--field must be one of: {string.Join(", ", ScriptTextSuffixes)}");
|
||||
attributeName = scriptName + "." + field;
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeName = ScriptAttributeName(scriptName);
|
||||
}
|
||||
|
||||
var attr = FindAttributeForMutation(obj, attributeName);
|
||||
var body = File.ReadAllText(file);
|
||||
attr.SetValue(CreateMxValue(body, "string"));
|
||||
@@ -1656,6 +1679,12 @@ namespace ZB.MOM.WW.GRAccess.Cli.GRAccess
|
||||
var attr = FindAttributeForMutation(obj, scriptName + ".TriggerType");
|
||||
attr.SetValue(CreateMxValue(triggerType, "string"));
|
||||
yield return CommandSummary(attr, $"Set script {scriptName}.TriggerType");
|
||||
|
||||
if (BoolArg(args, "lock-trigger-type"))
|
||||
{
|
||||
attr.SetLocked(MxPropertyLockedEnum.MxLockedInMe);
|
||||
yield return CommandSummary(attr, $"Lock script {scriptName}.TriggerType");
|
||||
}
|
||||
}
|
||||
|
||||
var expression = OptionalArg(args, "expression");
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace ZB.MOM.WW.GRAccess.Cli.Tests.Commands
|
||||
[InlineData(typeof(ObjectQueryNameCommand), "object query-name")]
|
||||
[InlineData(typeof(ObjectScriptsCreateCommand), "object scripts create")]
|
||||
[InlineData(typeof(ObjectScriptsSettingsSetCommand), "object scripts settings set")]
|
||||
[InlineData(typeof(ObjectScriptsSetCommand), "object scripts set")]
|
||||
[InlineData(typeof(ObjectScriptsDeleteCommand), "object scripts delete")]
|
||||
[InlineData(typeof(TemplateDeriveCommand), "template derive")]
|
||||
[InlineData(typeof(InstanceDeployCommand), "instance deploy")]
|
||||
[InlineData(typeof(ObjectsExportCommand), "objects export")]
|
||||
|
||||
Reference in New Issue
Block a user