Inserting a new line each "n" words according to clipboard

Hi, I’m Frank Espinoza. I have this clipboard, for example:

  1. The IMF will add the yuan to its basket of reserve currencies, an international stamp of approval of the strides China has made integrating into a global economic system dominated for decades by the U.S., Europe and Japan. The International Monetary Fund’s executive board, which represents the fund’s 188 member nations, decided the yuan meets the standard of being “freely usable” and will join the dollar, euro, pound and yen in its Special Drawing
    Rights basket, the organization said Monday in a statement.

What I want to do is to count 12 words in this paragraph, and then insert a \n, followed by a \t. So it looks like this:

  1. The IMF will add the yuan to its basket of reserve currencies,
    an international stamp of approval of the strides China has
    made integrating into a global economic system dominated for decades by
    the U.S., Europe and Japan. The International Monetary Fund’s executive
    board, which represents the fund’s 188 member nations, decided the
    yuan meets the standard of being “freely usable” and will join the dollar,
    euro, pound and yen in its Special Drawing
    Rights basket, the organization said Monday in a statement.

How could I do that?
Regards,
Frank Espinoza

Hi Frank. This sounds like a great case for RegEx. I don’t think it would be that hard, but I’m still so new at RegEx I don’t know the RegEx match pattern off the top of my head.
You might try some google searches on “regex insert after x words”, or similar.

You might also take a look at the KM wiki page on RegEx:
Regular Expressions

Good luck!

You could adjust something like the following in Script Editor (Yosemite onwards), and then put it in a Keyboard Maestro Execute JXA (JavaScript for Applications) action:

(function () {
    'use strict';

    var a = Application.currentApplication(),
        sa = (a.includeStandardAdditions = true, a),
        strText = sa.theClipboard(),

        lstWords = strText.split(/\b/),

        strAdjusted = lstWords.slice(0, 24).concat(
            '\n\t'
        ).concat(lstWords.slice(24)).join('');

    sa.setTheClipboardTo(strAdjusted);

    return strAdjusted;
})();
2 Likes

Thanks Rob. I thought you might have a solution like this up your JXA sleeve. :smile:
Much better solution than RegEx.

Great solution for plain text.

If you had rich text on the clipboard, and wanted to add the line breaks/tabs and retain the rich text, any ideas on how to proceed with that?

@hachondeoro, please checkout the below script and let me know if it will work for you.

Inspired by @ComplexPoint’s JXA post above, I wrote this JXA script, which should be ready to use in a KM JXA script action.

My many, continued, thanks to @ComplexPoint for his help and encouragement to me in learning JXA.

One minor point, Rob, I found that your script added a line break only to the first n words. Did I mess it up somehow? I wasn’t sure how to debug, ergo my script. :smile:

/*
⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶
	How To Add Line Breaks to Clipboard Text [JXA]
⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶

DATE:   	Tue, Dec 1, 2015
AUTHOR:	JMichaelTX (in KM forum, and others)

REF:
	1.  @ComplexPoint, KM Forum post, Dec 1, 2015
			https://forum.keyboardmaestro.com/t/inserting-a-new-line-each-n-words-according-to-clipboard/2488/3
		
	2.	@user1432124, Stackoverflow.com post/answer, Jun 10, 2012
			http://stackoverflow.com/a/10968692/915019
			
METHOD:
	•	Splits the string on the Clipboard into an array of words, using " " as the word boundary
	•	Recombines the words array back into a stirng, inserting the specified line break string (strLB) 
		after each nth word (numWordsPerLine)
	•	Except for two lines, get/set the Clipboard, this is pure core JavaScript.
		
BACKGROUND
	• Encouraged to continue my JXA learning by @Complex's post above, I ended up writing this
	• I found his code to give line break for only the first line, but he did say "You could adjust something like",
		so maybe that's what he meant.
	• I then found the Stackoverflow.com post, but it showed only (n-1) words on the first line.
	• So, as a learning exercise, I wrote this, fixing the minor flaws, and making the code more readable, IMO.
	
⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶⩶
*/
//--- ENCAPSULATE IN TOP LEVEL, AUTO-RUN FUNCTION ---

(function () {

var app = Application.currentApplication()
app.includeStandardAdditions = true

var numWordsPerLine = 12		// Set for desired line break
var strLB = "\n\t"					// Chars for line break.  Default is NEW LINE and TAB

var strSource = app.theClipboard()		// Get the Clipboard
var arrSource = strSource.split(" ")	// Split string into array of words
var strWithBreaks = ''						// Initialize output string

//--- LOOP ON EACH WORD ---

for(var i=0; i < arrSource.length; i++) {
		
	strWithBreaks += " " + arrSource[i]		// -- Add Next word to output string
	
	//--- ADD BREAK AFTER NumberWords/Line Has been found ---
	
	if( ((i+1) % numWordsPerLine) == 0) {	// Use the Remainder (modulo) operator %
		strWithBreaks += strLB	// -- Add Line Break -- 
	}
	
} // END FOR on arrSource[]

//--- OUTPUT TO CLIPBOARD ---

app.setTheClipboardTo(strWithBreaks)

return strWithBreaks

})();	// END AUTO-RUN function()
1 Like

Hi JMichaelTX. Honestly, I didn’t believe someone would have an answer for this, but I was really interested because I was working on a bigger macro, and this step would have been terrific if it worked. It works wonders, and as JMichaelTX noted, the first script only worked for the first line, but this last one works perfectly. I have integrated into the macro, and everything looks better. Looks like I might someday have the necessity to start programming in Java. Thank you very much for your prompt response.

Regards,
Frank Espinoza

1 Like

And what about each x number of characters in a line, is it possible?

Yes. Actually that’s very easy. But, let me ask, is that really what you want?
It could/will produce line breaks in the middle of words.

Which reminds me of another question I was going to ask you.
What app are you pasting the results into?
Most apps have a soft word-wrap that will automatically wrap at either the window edge and/or a given number of characters.

This is mainly for my self. I tend to copy a lot of information from books and safari, but I like it to be well organised, so I can later print it and show it to other people. For example, according to the format of the last java-script:

 	  An important goal of the Python developers is making Python fun to use. This is reflected in the origin of the name,
 which comes from Monty Python,[44] and in an occasionally playful approach to tutorials and reference materials, such as using examples that refer
 to spam and eggs instead of the standard foo and bar.[45][46] A common neologism in the Python community is pythonic, which can
 have a wide range of meanings related to program style. To say that code is pythonic is to say that it uses
 Python idioms well, that it is natural or shows fluency in the language, that it conforms with Python's minimalist philosophy and emphasis
 on readability. In contrast, code that is difficult to understand or reads like a rough transcription from another programming language is called
 unpythonic. 

Even though it is separated by words, I feel it is still a little bit messy. So that is why I asked for the character separation. But as you said, it may break in the middle of words. I think this could be addressed by adding a “-” at the end of each word break at the end of the line, but I’m not so sure. What would you suggest?

What app are you using to store this information in?

I use Evernote a lot, and it would seem to be a great tool for this.
In Evernote, you would not have to worry about line length, since it will auto-wrap at the Note window boundary. Printing a EN Note is similar, but some people don’t like it.

The organization and search are great. And, it will sync your EN database on pretty much all devices: Mac, PC, Apple iOS, Android, etc.

IAC, if you have not tried Evernote, you might give it a shot. It’s free for the basic version.
If you decide to use it , I have a number of KM macros and AppleScript scripts to greatly facilitate getting info into Evernote in a nice, easy way.

Looks good, at first glance : - )

One small thing, it may be worth cacheing the array length in a variable before the loop, rather than writing:

for(var i=0; i < arrSource.length; i++)

( I think JS will otherwise end up re-measuring the array with every loop test - probably doesn’t make a significant difference here, but will begin to as scale increases )

I agree, and in fact have already made that change, as well as enhanced it to be a standalone function (no ref to Clipboard), and to add optional parameters. If it holds up, I’ll post tomorrow (well, later today.) :smile: