Page 1 of 1

Replace words in expressions - script doesn't work

Posted: December 11th, 2008, 8:13 am
by Redsandro
Hi,

I want a script that changes all instances of thisComp to comp("currentCompName") inside all expressions of selected layers.

I drafted this, but somehow it doesn't work but doesn't give me an error either. Also, after running, there's nothing to 'undo.'

Can someone with a keener eye look at it and tell me where I am missing something?

Code: Select all

/**********
 *	NotThisComp
 **********
 *	Filename:		NotThisComp v1.0.jsx
 *	Written by:		Redsandro - http://www.rednet.nl/en/
 *	Date:			2008/12/10
 *	Last updated:	2008/12/10
 **********
 *
 *	Description:
 *
 *	Traverses selected layers for expressions that reference thisComp
 *	and change them to comp("compName") so the layer can sit in a parent
 *	composition.
 *
 **********/



clearOutput();

var myComp = app.project.activeItem;
if (myComp == null) {
	alert("You need to select a layer first.");
}
else {
	// Gather data
	//var compName = "no name";
	//compName = prompt("What name do you want to reference instead of thisComp()", compName));
	var myLayers = myComp.selectedLayers;
	var myCompName = myComp.name;
	var newName = "comp("+myCompName+")";

	// Check selected
	if (myLayers.length < 1)
		alert("You need to select some layers first!");
	else {
		app.beginUndoGroup("NotThisComp");

		// Walk layers
		for (var l=0; l<myLayers.length; l++) {
			var myLayer = myLayers[l];
			// Walk properties
			for (var p=0; p<myLayer.length; p++) {
				var prop = myLayer[p];
				if (prop.canSetExpression == true) {
					if (prop.expression.indexOf("thisComp"))
						prop.expression = prop.expression.split("thisComp").join(newName);
				}
				// if (.expressionEnabled != true) something went wrong
			}
			
		}

		app.endUndoGroup();
	}
}

Re: Replace words in expressions - script doesn't work

Posted: December 12th, 2008, 2:51 pm
by lloydalvarez
Just looking quickly at the code one thing i could suggest is that you use replace instead of split and join like this:

Code: Select all

prop.expression = prop.expression.replace(/thisComp/g,newName);

-Lloyd

Re: Replace words in expressions - script doesn't work

Posted: February 13th, 2009, 11:38 pm
by Redsandro
I wasted too much time manually editing ocurrances of thisComp, so I took another look at my script.
Turns out there is no way (afaik) to traverse all properties, but you can traverse selected properties.

So in case anyone sees how this can be handy, here it is:
(also as attachment).

Code: Select all

/**********
 *	NotThisComp
 **********
 *	Filename:		NotThisComp v1.1.jsx
 *	Written by:		Redsandro - http://www.rednet.nl/en/
 *	Date:			2008/12/10
 *	Last updated:	2009/02/14
 **********
 *
 *	Description:
 *
 *	Traverses selected properties in one or more layers for expressions that reference thisComp
 *	and changes them to comp("compName") so the layer can be precomposed and stuff without
 *	breaking layer references.
 *
 **********/



clearOutput();

var myComp = app.project.activeItem;
if (myComp == null) {
	alert("No composition selected.");
}
else {
	// Gather data
	//var compName = "no name";
	//compName = prompt("What name do you want to reference instead of thisComp()", compName));
	var myLayers = myComp.selectedLayers;
	var myCompName = myComp.name;
	var newName = "comp('"+myCompName+"')";

	// Check selected
	if (myLayers.length < 1)
		alert("No layers selected.");
	else {
		var changes = false;
		app.beginUndoGroup("NotThisComp");
		// Walk layers
		for (var l=0; l<myLayers.length; l++) {
			var myLayer = myLayers[l];
			// Walk properties
			//
			if (myLayer.selectedProperties && myLayer.selectedProperties.length > 0) {
 				var selProps = myLayer.selectedProperties;
				if (changes === false) changes = 0; // for knowing props were selected
 				for(var p=0; p<selProps.length; p++) {
					var prop = selProps[p];
					if (prop.canSetExpression == true) {
						if (prop.expression.indexOf("thisComp") != -1) {
							prop.expression = prop.expression.split("thisComp").join(newName);
							changes++;
						}
					}
				}
			}
		}
		app.endUndoGroup();

		if (changes === false) alert("No properties were selected.");
		else if (changes == 0) alert("No instance of 'thisComp' found.");
		else alert("Replaced: " + changes);
	}
}

Re: Replace words in expressions - script doesn't work

Posted: March 31st, 2009, 9:58 am
by ajk48n
I needed the same sort of script, so I took yours, and expanded on it.

I got the ability to search all properties implemented. The script basically recursively searches through all properties looking for ones which have expressions enabled. I also added the ability to specify your search and replace strings.

Code: Select all

{
app.beginUndoGroup("Search/Replace Expressions");



		win = new Window('dialog', "Search and Replace Expressions", "x:300,y:300,width:400,height:200");
		win.grp1 = win.add('group', "x:0,y:0,width:500,height:500", 'Title of Comp');
		
		win.grp1.add('statictext', "x:15,y:50,width:90,height:20", 'Search Text:');
		win.grp1.searchText = win.grp1.add('edittext', "x:100,y:50,width:250,height:20", '<search text>');
		
		win.grp1.add('statictext', "x:15,y:75,width:90,height:20", 'Replace Text:');
		win.grp1.replaceText = win.grp1.add('edittext', "x:100,y:75,width:250,height:20", '<replace text>');
		
		win.grp1.changeAllText = win.grp1.add('statictext', "x:15,y:110,width:225,height:20", 'Check to change all expressions:');
		win.grp1.changeAllExprCB = win.grp1.add('checkbox', "x:200,y:110,width:20,height:20");
		
		win.grp1.buildBtn = win.grp1.add('button', "x:15,y:150,width:200,height:30",	'Replace Text', {name:'ok'});
		win.grp1.buildBtn.onClick = searchProperties;
		win.grp1.cancelBtn = win.grp1.add('button', "x:240,y:150,width:100,height:30", 'Close', {name:'cancel'});

		win.show();
		
app.endUndoGroup();
}
		
		
function searchProperties()
{
	
	var changeAllCB = win.grp1.changeAllExprCB.value;
		
	clearOutput();

	var myComp = app.project.activeItem;

	// Gather data
	var myLayers = myComp.selectedLayers;
	var myCompName = myComp.name;
   
	// Walk layers
	if (myLayers.length > 0)
	{
		for (var l=0; l<myLayers.length; l++) {
			var myLayer = myLayers[l];
		
			if (changeAllCB)		
				findProperties(myLayer);
			else
			{
				selProps = myLayer.selectedProperties;
				if (selProps.length > 0)
				{
					for(var p=0; p<selProps.length; p++)
					{
						var prop = selProps[p];
						searchReplaceExpr(prop);
					}
				}
				else
					alert("No properties were selected");
			}
		}
	} else
		alert("You must select at least 1 layer");
}

function searchReplaceExpr(prop)
{
	var search_text = win.grp1.searchText.text;
	var replace_text = win.grp1.replaceText.text;
	
	if (prop.canSetExpression == true) {

		var search_text = eval("/" + search_text + "/g");	
		prop.expression = prop.expression.replace(search_text, replace_text);
	}
}

function findProperties(object)
{
	var numProps = 0;
	numProps = object.numProperties;

	// if there are undefined properties, we are at the bottom of the hierarchy of properties
	if (numProps == undefined)
	{
		if (object.expressionEnabled)
			searchReplaceExpr(object);
		return 1;
	} else if (numProps == 0)
		return 1;
	
	//recursively search all properties
	for (i=1; i<=numProps; i++)
	{
		findProperties(object.property(i));
	}
	return 0;
}

Re: Replace words in expressions - script doesn't work

Posted: March 31st, 2009, 10:33 am
by Redsandro
Nice! Thanks.

Re: Replace words in expressions - script doesn't work

Posted: April 16th, 2009, 4:19 pm
by davestewart
You could replace the eval in this code with a RegExp constructor:

var search_text = eval("/" + search_text + "/g");

var search_text = new RegExp(search_text, "g");

Re: Replace words in expressions - script doesn't work

Posted: January 31st, 2010, 11:35 pm
by Redsandro
lloydalvarez wrote:

Code: Select all

prop.expression = prop.expression.replace(/thisComp/g,newName);
davestewart wrote:var search_text = new RegExp(search_text, "g");
prop.expression.replace(regFind, strReplace); does not work with ( in the search-term.
On the other hand, prop.expression.split(strFind).join(strReplace); does not work when the search-term starts or ends with ".

The second method can be used with a workaround (searching with an extra character pre- or appending the quote) but the first cannot.
Do you know how to do this correctly?