sourceText value to be the layer index number according to current time indicator - after-effects

Is there any way I could use a text layer and set it's source text value to be the layer index number of the visible layer or where AE's current time indicator is (CTI) during ram preview?

This will indicate the current time and the index of the first active layer:
var comp = app.project.activeItem;
var layer = comp.layers.addText("");
layer.text.sourceText.expression =
"""idx = "-";
N = thisComp.numLayers;
for (i=1; i<=N; i++){
if (i===index) continue;
if (thisComp.layer(i).active){idx = i; break;};
};
line2 = "Active Layer : " + idx;
line1 = "CTI : " + timeToCurrentFormat(time);
line1 + "\r" + line2;"""
(This is to be used from a script. To use directly inside After Effects, copy paste what's between triple quotes in the text expression box).

Related

Auto Find and Replace Script in Google Sheets - Delete some certain cell content - global replace

Many cell entry's in my sheet contain extraneous words that I want to delete. I need a script to find keywords within a single column (in this case "B") and delete them in order. The goal is to make the cell entries shorter.
My keywords are "Epic Artifactory DIY", "Barn", "Planks", "Pack, "Coupon: WTXPXZP", "Coupon: FREESHIP50", "Coupon: SPRING10", and "Wall".
I found this script, but it will not work for me.
function fandr() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var s=ss.getActiveSheet();
var r=s.getDataRange();
var vlst=r.getValues();
var i,j,a,find,repl;
find="abc";
repl="xyz";
for (i in vlst) {
for (j in vlst[i]) {
a=vlst[i][j];
if (a==find) vlst[i][j]=repl;
}
}
r.setValues(vlst);
}
Thanks
Here is some code that gets the data in only one column, and replaces all the content with an empty string (deletes the words). Replace words in one column of a Google Sheet.
function replaceInColumn() {
var arrayWordsToFind,dataInColumn,dataAsString,newString,
newData,outerArray,i,lastrow,L,sh,ss,tempArray,toFind;
arrayWordsToFind = [
"Epic Artifactory DIY", "Barn", "Planks", "Pack",
"Coupon: WTXPXZP", "Coupon: FREESHIP50", "Coupon: SPRING10", "Wall"
]
ss = SpreadsheetApp.getActiveSpreadsheet();
sh = ss.getSheetByName("Your Sheet Name Here");
lastrow = sh.getLastRow();//Get row number of last row
//sh.getRange(start row, start column, number of Rows, number of Columns)
dataInColumn = sh.getRange(2, 2, lastrow).getValues();
dataAsString = dataInColumn.toString();//Convert 2D array to a string
//Logger.log('dataAsString: ' + dataAsString)
newString = dataAsString;
L = arrayWordsToFind.length;//The number of words to find
for (i=0;i<L;i++) {//Loop once for every word to find
toFind = new RegExp(arrayWordsToFind[i], "g");//define new Reg Ex with word to find - replace globally
newString = newString.replace(toFind,"");//Delete all found words
}
//Logger.log('newString: ' + newString)
newData = newString.split(",");//Convert string to 1D array
outerArray = [];
L = newData.length;
for (i=0;i<L;i++) {
//Logger.log('i: ' + i)
//Logger.log('newData[i]: ' + newData[i])
tempArray = [];//Reset
tempArray.push(newData[i]);
outerArray.push(tempArray);//Create a new 2D data array
}
sh.getRange(2, 2, outerArray.length).setValues(outerArray);
}
Key words: find replace column global
This Google Script function will help you find and replace text across all cells in a particular column (B in this case).
function findReplace() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var column = 2;
for (var d=0, l=data.length; d<l; d++) {
if (data[d][column-1] === "find") {
sheet.getRange(d+1, column).setValue("replace");
}
}
SpreadsheetApp.flush();
}

Make Google Apps script with regex in loop use less resources, so not to exceed maximum execution time

Is there a way to make this script use less resources? I get exceeded maxiumum execution time, even when only selecting a small portion of the dataset.
I suppose the Regex consumes quite a bit of resources, particularly since it's done for every iteration of the source column, for each iteration of the target column. But I'm not sure how to solve it, to make it possible to run this through a large amount of data.
function updatecategory() {
/* let us say source array with name(columnA) & ID(columnB) is array 'source'
and target array with only IDs is array 'target', you get these with something like*/
var source = SpreadsheetApp.getActiveSpreadsheet().getSheets()[4].getDataRange().getValues();
// and
var target = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange("A3:A30").getValues();// if other columns, change index values in the arrays : 0=A, 1=B ...
// then let's create a 3 rd array that will be the new target with ID + names, and call it 'newtarget'
var newtarget=new Array()
// the iteration could be like this :
for(i=0;i<target.length;++i){ // don't miss any ID
var found=""
var targetstr = target[i][0].toString()
for(j=0;j<source.length;++j){ // iterate through source to find the name
for(k=2;k<3;++k){
var str = source[j][k].toString()
var regex = new RegExp(".(?!(?!.*.[a-zA-Z ]{2,}" + targetstr + ")(?!" + targetstr + "[a-zA-Z \*]+$)).*$", "gm")
//Find only words in a cell that exactly match the target word,
//that is not part of a word or a phrase.
var replace = ''
var newstr = str.replace(regex,replace)
if(newstr.indexOf(targetstr)>-1){
var newsource = source[j][0] + "(n)"
var newtargetrow=[target[i][0], newsource] // if match found, store it with name (idx0) and ID (idx 1)
//Logger.log(target[i][0].toString().match(source[j][0].toString()) + " " + source[j][0].toString())
//newtarget.push(newtargetrow);// store result in new array with 2 columns
found="found"
Logger.log(targetstr + " " + newsource)
} else if (found != "found") {
var newtargetrow=[target[i][0], ''] // if no match, show it in name column
//Logger.log(found)
}
}
}
//Logger.log(newtarget)
newtarget.push(newtargetrow);// store result in new array with 2 columns
//loop source
} // loop target
/* now you have a newtarget array that can directly overwrite the old target
using setValues() */
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];// assuming the target sheet is sheet nr2
sh.getRange(3,1,newtarget.length,newtarget[0].length).setValues(newtarget);
//
}
As per your feedback, you can use
var regex = new RegExp("(^|[,;]\\s)\\b" + targetstr + "\\b(?!\\s)", "gm")
It matches a targetstr that is a whole word (because of \b word boundary anchors round the term) and is preceded by a start-of-line anchor (^) or a comma or semi-colon followed with a whitespace ([,;]\\s) and that is not followed with whitespace ((?!\\s)).

Find value when not between quotes

Using JavaScript & regex I want to split a string on every %20 that is not within quotes, example:
Here%20is%20"a%20statement%20"%20for%20Testing%20"%20The%20Values%20"
//easy to read version: Here is "a statement " for Testing " The Values "
______________ ______________
would return
{"Here","is","a statement ","for","Testing"," The Values "}
but it seems my regex are no longer strong enough to build the expression. Thanks for any help!
A way using the replace method, but without using the replacement result. The idea is to use a closure to fill the result variable at each occurence:
var txt = 'Here%20is%20"a%20statement%20"%20for%20Testing%20"%20The%20Values%20"';
var result = Array();
txt.replace(/%20/g, ' ').replace(/"([^"]+)"|\S+/g, function (m,g1) {
result.push( (g1==undefined)? m : g1); });
console.log(result);
Just try with:
var input = 'Here%20is%20"a%20statement%20"%20for%20Testing%20"%20The%20Values%20"',
tmp = input.replace(/%20/g, ' ').split('"'),
output = []
;
for (var i = 0; i < tmp.length; i++) {
var part = tmp[i].trim();
if (!part) continue;
if (i % 2 == 0) {
output = output.concat(part.split(' '));
} else {
output.push(part);
}
}
Output:
["Here", "is", "a statement", "for", "Testing", "The Values"]

Easily aligning characters after whitespace in vim

I would like to create a mapped vim command that helps me align assignments for variables across multiple lines. Imagine I have the following text in a file:
foo = 1;
barbar = 2;
asdfasd = 3;
jjkjfh = 4;
baz = 5;
If I select multiple lines and use the regex below, noting that column 10 is in the whitespace for all lines, stray whitespace after column 10 will be deleted up to the equals sign.
:'<,'>s/^\(.\{10}\)\s*\(=.*\)$/\1\2/g
Here's the result:
foo = 1;
barbar = 2;
asdfasd = 3;
jjkjfh = 4;
baz = 5;
Is there a way to get the current cursor position (specifically the column position) while performing a visual block selection and use that column in the regular expression?
Alternatively, if it is possible to find the max column for any of the equals signs on the selected lines and insert whitespace so all equals signs are aligned by column, that is preferred to solving the previous problem. Imagine quickly converting:
foo = 1;
barbar = 2;
asdfasd = 3;
jjkjfh = 4;
baz = 5;
to:
foo = 1;
barbar = 2;
asdfasd = 3;
jjkjfh = 4;
baz = 5;
with a block selection and a key-combo.
Without plugins
In this case
foo = 1
fizzbuzz = 2
bar = 3
You can add many spaces with a macro:
0f=10iSPACEESCj
where 10 is an arbitrary number just to add enough space.
Apply the macro M times (for M lines) and get
foo = 1
fizzbuzz = 2
bar = 3
Then remove excessive spaces with a macro that removes all characters till some column N:
0f=d12|j
where 12 is the column number you want to align along and | is a vertical bar (SHIFT + \). Together 12| is a "go to column 12" command.
Repeat for each line and get
foo = 1
fizzbuzz = 2
bar = 3
You can combine the two macros into one:
0f=10iSPACEESCd11|j
Not completely satisfied with Tabular and Align, I've recently built another similar, but simpler plugin called vim-easy-align.
Check out the demo screencast: https://vimeo.com/63506219
For the first case, simply visual-select the lines and enter the command :EasyAlign= to do the trick.
If you have defined a mapping such as,
vnoremap <silent> <Enter> :EasyAlign<cr>
you can do the same with just two keystrokes: Enter and =
The case you mentioned in the comment,
final int foo = 3;
public boolean bar = false;
can be easily aligned using ":EasyAlign*\ " command, or with the aforementioned mapping, Enter, *, and space key, yielding
final int foo = 3;
public boolean bar = false;
There are two plugins for that: Either the older Align - Help folks to align text, eqns, declarations, tables, etc, or Tabular.

Flash AS3 count capital letters?

How could I count the number of capital letters in a string using flash as3?
for example
var thestring = "This is The String";
should return int 3
Thank you
// Starting string.
var thestring:String = "This is The String";
// Match all capital letters and check the length of the returned match array.
var caps:int = thestring.match(/[A-Z]/g).length;
trace(caps); // 3
One way to solve this is to convert the string to lower case and count the characters affected. That means you don't have to specify which characters to include in the category of "uppercase letters", which isn't trivial. This method supports accented characters such as É.
// Starting string.
var theString:String = "'Ö' is actually the Swedish word for 'island'";
var lowerCase : String = theString.toLowerCase();
var upperCount : int = 0;
for (var i:int = 0; i < theString.length; i++) {
if (theString.charAt(i) != lowerCase.charAt(i)) {
upperCount++;
}
}
trace(upperCount); // prints 2
Each letter in a string has a value that corresponds with that letter:
var myString:String = "azAZ";
trace(myString.charCodeAt(0));
trace(myString.charCodeAt(1));
trace(myString.charCodeAt(2));
trace(myString.charCodeAt(3));
// Output is 97, 122, 65, 90
The name.charCodeAt(x) returns the code of the letter at the position in the string, starting at 0.
From this output we know that a - z are values ranging from 97 to 122, and we also know, that A - Z are values ranging from 65 - 90.
With that, we can now make a For Loop to find capital letters:
var myString:String = "This is The String";
var tally:int = 0;
for (var i:int = 0; i < myString.length; i++)
{
if (myString.charCodeAt(i) >= 65 && myString.charCodeAt(i) <= 95)
{
tally += 1;
}
}
trace(tally);
// Output is 3.
The variable "tally" is used to keep track of the number of capital letters found. In the For Loop, we are seeing if the value of the current letter it is analyzing is between the values 65 and 90. If it is, it adds 1 to tally and then traces the total amount when the For Loop finishes.
Why be succint? I say, processing power is made to be used. So:
const VALUE_0:uint = 0;
const VALUE_1:uint = 1;
var ltrs:String = "This is JUST some random TexT. How many Caps?";
var cnt:int = 0;
for(var i:int = 0; i < ltrs.length; i++){
cnt += processLetter(ltrs.substr(i,1));
}
trace("Total capital letters: " + cnt);
function processLetter(char:String):int{
var asc:int = char.charCodeAt(0);
if(asc >= Keyboard.A && asc <= Keyboard.Z){
return VALUE_1;
}
return VALUE_0;
}
// Heh heh!