Replace words in expressions - script doesn't work

Find out why the . goes before the /

Moderator: Paul Tuersley

Post Reply
Redsandro
Posts: 108
Joined: June 25th, 2008, 4:55 pm

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();
	}
}
avi + m2t -> Vdub + DGIndex -> AE CS3 -> x264 -> Hell On Earth :mrgreen:
User avatar
lloydalvarez
Enhancement master
Posts: 460
Joined: June 17th, 2004, 9:27 am
Location: New York City, NY
Contact:

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
Redsandro
Posts: 108
Joined: June 25th, 2008, 4:55 pm

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);
	}
}
Attachments
NotThisComp v1.1.zip
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.
(933 Bytes) Downloaded 910 times
avi + m2t -> Vdub + DGIndex -> AE CS3 -> x264 -> Hell On Earth :mrgreen:
ajk48n
Posts: 20
Joined: January 17th, 2007, 3:02 pm

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;
}
Redsandro
Posts: 108
Joined: June 25th, 2008, 4:55 pm

Nice! Thanks.
avi + m2t -> Vdub + DGIndex -> AE CS3 -> x264 -> Hell On Earth :mrgreen:
davestewart
Posts: 114
Joined: March 10th, 2005, 5:50 am
Location: London, UK
Contact:

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");
Redsandro
Posts: 108
Joined: June 25th, 2008, 4:55 pm

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?
avi + m2t -> Vdub + DGIndex -> AE CS3 -> x264 -> Hell On Earth :mrgreen:
Post Reply