New to forum. A couple of questions if I may?

  1. Is it possible to copy the contents of a variable to the clipboard? Specifically a value. Or WRITE the value of a variable to a field. WRITE gives me an error that I am missing a parameter.

  2. looking for a way to convert text files stored in high ascii, into low ascii.

  3. I can do KEYSTROKE RETURN, but can’t do KEYSTROKE DELETE or KEYSTROKE BACKSPACE. Is there an alternative

IamRob. The following works with my keyboard:

tell application "System Events" to tell process "TextEdit"
	set frontmost to true
	key code 51 -- back delete
	-- key code 117 -- forward delete
end tell

BTW, I’m not aware of a corresponding equivalent for the above to keystroke return.

set someValue to "xyz"
set the clipboard to someValue

Not sure what you mean by a ‘field’.

Thanks for the replies.

  1. key code 51 works perfectly, thanks.

  2. set the clipboard to var – at least does not give me an error now, but the PASTE function goes dim. Meaning, if there was something in the clipboard and the menu item “PASTE” was previously selectable, now is no longer selectable.

Is “the clipboard” under a different process other than the application that is currently running?

In TextEdit, pressing Command-L gives a “goto line number” option. I thought I read in another post the rectangular entry box was called a field. I would like to either “paste” the value from the variable into that entry box, or “write” the value of the variable into the entry box.

solved number 1)

set var to 261
set the clipboard to var as text

I see very little posts on the clipboard, but it is starting to turn out to be a powerful tool. Can now do:

set v1 to the clipboard as text
set v2 to v1 + 3
return v2

or

set v1 to the clipboard as text
set v2 to v1 & “3”
return v2

Should now be able to step 2) on my own, but does anyone have an example of, or know what “WRITE” does?

Where are you getting “WRITE” from in this context? The write command is part of Standard Additions’ File Read/Write Suite (see below), and not part of TextEdit’s rather limited scripting dictionary. It won’t help you filling dialog boxes.

You could try playing with the following:

set the clipboard to "9"
tell application "TextEdit" to activate
delay 1
tell application "System Events"
    keystroke "l" using command down
    keystroke "v" using command down
    keystroke return
end tell

(Apps must be activated to access the system clipboard.)

This activates TextEdit, displays the go-to-line dialog box, pastes in the contents of the clipboard and then confirms the dialog by simulating a return. The first two keystroke commands must use lowercase letters. It doesn’t trap any potential errors (alpha characters in the clipboard, invalid line numbers…).

But it’s pretty clunky. Generally speaking, using AppleScript to manipulate interface elements (pasting, dialog boxes etc) is a bit of a last resort.

For example, the following modifies paragraph 9 of the frontmostTextEdit document without involving any interface elements:

set myPar to 9
set myText to "something different " & return
tell application "TextEdit"
    activate
    tell document 1
        set paragraph myPar to myText
    end tell
end tell

It’s quicker, more flexible and more powerful.

Couple of thoughts:

If you need to process text with AppleScript, you might want to investigate a more powerful scriptable text editor (BBEdit is probably the tool of choice, CotEditor is an alternative).

And as mentioned above, AppleScript has its own basic file read/write capabilities, with which it can read, edit and save text files without opening them in the user interface.

Here’s a very very quick example of the write command in Standard Additions:

set filePath to (path to desktop as string) & "demo.txt"
set nuText to (open for access file filePath with write permission)
write "This is a demo" to nuText
close access nuText

This creates a file on the user’s desktop called demo.txt, opens it, writes some text to it, and closes it off. Without anything happening in the user interface, except for the automagical appearance of the file on the user’s desktop.

Hope it helps,

hubert0

BBEdit.

tell application "BBEdit"
	tell document 1
		set content to (zap gremlins zap action replace_with_code with use ASCII equivalents and non ASCII characters)
	end tell
end tell

From BBEdit’s help documentation:

No need to re-invent the wheel :wink:

Almost there.
I need to go to a paragraph (or line), select it and modify it, before pasting it back . Can’t seem to find the right words or order of words.

How can I select a paragraph without replacing it with what is in myText.

Again, I’m quoting from the BBEdit User Manual (14.1.1), page 330:

So don’t go to a line, don’t select, don’t copy, don’t paste - use the application’s object model and scripting dictionary.

Here’s one way of modifying a paragraph in TextEdit:

tell application "TextEdit"
set startingPhrase to "Something at the beginning. "
set finalPhrase to " Something at the end." & return
	tell document 1
		set oldParagraph to paragraph 4
		set nuParagraph to startingPhrase & text 1 thru -2 of oldParagraph & finalPhrase
		set paragraph 4 to nuParagraph
	end tell
end tell

This concatenates a starting phrase, then “text 1 thru -2 of oldParagraph” - the paragraph without its last character, a return - and then a final phrase and a concluding return.

startingPhrase, finalPhrase, oldParagraph and nuParagraph are text variables.

But without knowing exactly how you want to modify the paragraph, it’s hard to give more concrete advice.

Thanks and Apologies. Found my error.

TextEdit doesn’t like being called a “process” when doing this. I know I also tried it this way without using “System Events” and using TextEdit as an application. But kept getting the error “Can’t get paragraph of TextEdit”. But I think I had “set frontmost to true” instead of “tell document 1”.

Some things seem to work and others don’t in different situations.

I wanted you to leave me something to do in the way of programming Applescript.

The example you left me is the fasted of the 3 I have written so far. But I still feel it should be faster yet.

This is my working script right now. I use it to remove the ascii part of hex dumps by reducing each paragraph to exactly 48 characters, and ignore any empty lines or lines less than 48 characters.


tell application "TextEdit"
	tell document 1

		set i to 2
		repeat
			repeat with x from 1 to 33
				set oldPara1 to paragraph i
				set fir_char to character 1 of oldPara1
				
				if fir_char is "<" or fir_char is return then
					set i to i - 1
					exit repeat
				end if
				
				set paragraph i to text 1 thru 48 of oldPara1 & return
				set i to i + 1
			end repeat
			
			set i to i + 2
		end repeat
		
	end tell
end tell

The biggest thing that baffles me is that the larger the document (more paragraphs) that are in the document, the slower the “paragraph” function gets.

For example, if I only have 16 paragraphs, this applescript if very fast. But if I have 10,000 paragraphs, but I still only want to work on the first 16 paragraphs, this is extremely slow.

What is the “paragraph” function doing that it cares how large the rest of the document is that it makes editing the first few lines extremely slow? I can manually copy and paste faster than the speed it is slowed down to.

Paragraphs aren’t stored as such by applications. The default AppleScript implementation of this builds a list of the paragraphs, and then returns the one you want. Building the list of 10,000 takes longer than a list of a dozen or so.

Applications can write faster code for specific cases like this, but most don’t. The default code has to be generic enough to deal with all sorts of collections, and trades efficiency for the ability to be used generally.

It’s generally quicker to get the text in one go, and manipulate it all in AppleScript itself.

I think I thought of the answer after I wrote this. I am setting a new, shortened paragraph back to the document each time through the loop which probably forces the paragraph list to be re-built each time.

Another option maybe!

Would it then be possible to work on the document as a whole, using the “return” mark as a marker and skip the paragraph function? I have to count the characters in each paragraph anyways, so how about a script that keeps track when it encounters one “return” mark to the next, and calculate the count difference between the two? Although I don’t know how to replace the text in that instance.

And one last option:

One of my other scripts used “SystemEvents” and the process “TextEdit”. The script is quite fast in this case, but I was limited to a portion of the document at a time. Is there a way to shorten the clipboard within the process? This is what I have and what is needed for it to work.


tell application "TextEdit"
	set nlines to count paragraphs of document 1
end tell

tell application "System Events" to tell process "TextEdit"
	set frontmost to true
	
	repeat with i from 1 to nlines
		set the clipboard to i as text
		keystroke "l" using command down
		keystroke "v" using command down
		keystroke return -- this highlights and selects a paragraph
		delay 0.15
		
		keystroke "c" using command down
		
-- I need to shorten the clipboard to 48 bytes here or keep the same length if any shorter?		
		
		keystroke "v" using command down
	end repeat
end tell

Hello, @lamRob,

Your script in the post #11 contains a lot of superfluous, and in the root is incorrect. Because you do not consider that Textedit paragraphs contain rich text.

Therefore, to circumcise the paragraphs will have to simply destroy their redundant characters:


tell application "TextEdit"
	activate
	tell document 1 to tell its text
		
		set aCount to count its paragraphs
		repeat with i from 1 to aCount -- or, indicate 16 (as you want)
			if (count characters of its paragraph i) > 49 then ¬
				delete characters 49 thru -2 of its paragraph i
		end repeat
		
	end tell
end tell

NOTE: do not delete character -1 because it is paragraph delimiter character in the Textedit (return)

Did a few tests, striving for speed. Some things of note:

tell document 1 “to tell its text” – the quoted part saves 5 seconds if document is a .rtf file
– and not needed if document is already a text document, which is what I am working with

deleting characters is twice as slow as getting the characters in a forward collection. This:

           if (count characters of its paragraph i) > 49 then ¬
               delete characters 49 thru -2 of its paragraph i

is twice as slow as this

          set Para to paragraph i
          set nCount to count of Para
          if nCount > 49 then set paragraph i to text 1 thru 48 of Para

And one final optimization working with the document as a whole. Using the “character” command instead of the “paragraph” command.

	tell application "TextEdit"
	activate
	tell document 1
		set done to return & return & "<Delete all after here>" & return & return
		set cdone to count characters of done
		set cnt to count characters
		set x to 1 -- characters
		set y to 1 -- start of each paragraph
		
		repeat
			set cntr to 1
			repeat
				set c to character x
				set x to x + 1
				set character y to c
				set y to y + 1
				set cntr to cntr + 1
				if c is return then set cntr to 0
				if cntr is 50 then exit repeat
			end repeat
			
			repeat
				set c to character x
				if c is return then exit repeat
				set x to x + 1
			end repeat
			if character (x + 2) is "[" then exit repeat
		end repeat
		
		repeat with i from 1 to cdone
			set c to character i of done
			set character y to c
			set y to y + 1
		end repeat
		beep
	end tell
end tell

This last code is about 5-7 times faster than previous methods. No slow down with 10,000 lines.

One major caveat though. This method seems to tie up the resources in TextEdit which does a lot of disk accessing when trying to save the document. Have to wait 3-5 minutes just to save the modified document. And even then have to reboot the computer to get full operation back to full operation. This part is a little frustrating, but still way faster than other methods.

Is there any particular reason for you to use TextEdit?

You do not need to if you simply want to modify text files with AppleScript.

You do not even have to have the files open on screen.

You can use AppleScript’s built-in text processing commands and the job will be far far faster than anything you can achieve with TextEdit.

As I understand it, you want to take a plain text (.txt) file of 10,000 paragraphs and modify it so that every paragraph longer than 48 characters is cut to its first 48 characters. I don’t understand what you want to do with the shorter paragraphs - leave them in the final version untouched, or remove then entirely? Either is possible.

To illustrate one way of modifying the text, I first built a text file of 10,000 lines of random characters and spaces, with paragraph lengths ranging from 35 to 55 characters.

I then ran the following script, which reads my text file, asks for a new file to place the modified text, creates an empty text variable, then loops through each paragraph of the original text, chops it to 48 characters if it’s any longer, then adds the paragraph (chopped or not) to the new text variable). When it’s finished looping, it writes the 10,000-paragraph new text variable into the specified file. The original text file is untouched.

It doesn’t require TextEdit, or System Events. It’s bare AppleScript.

set longText to read (choose file with prompt "Choose a file whose text is to be cut:")

set shortFile to (choose file name with prompt "Create a new file for the chopped-down text:")
set parCount to count paragraphs in longText
set shortText to ""
repeat with x from 1 to parCount
	set nextPar to paragraph x of longText
	set charCount to count characters in nextPar
	if charCount > 48 then --paragraph returns aren't counted
		set shortText to shortText & text 1 thru 48 of nextPar & return
-- remove the following two lines if the shorter paragraphs are to be dropped altogether
	else 
		set shortText to shortText & nextPar & return
	end if
end repeat
end

set shortFileWrite to (open for access shortFile with write permission)
try
	write shortText to shortFileWrite
on error
	close access shortFileWrite
end try
close access shortFileWrite
display dialog "Finished chopping!" buttons {"OK"} default button 1 giving up after 30

I don’t know if it does exactly what you want, and I’m sure there are faster ways of doing it. But it takes less than ten seconds on my machine and doesn’t require any sort of rebooting.

Nope. I should have clued in to using this method myself with using Applescript’s variables. But it mostly shows my inexperience with Applescript. I am mostly unsure of Applescripts limits with variables and execution.

I assumed Applescript was mostly used just to make operations automatic on open applications.

Thanks for the hint. It opens up a lot more doors for me and helps to understand some of the more complicated posts on this forum.

The following is an ASObjC suggestion. It creates a new file with the text “(trimmed)” appended to the file name. The RegEx code was written by Nigel.

use framework "Foundation"
use scripting additions

on main()
	set sourceFile to POSIX path of (choose file)
	set firstCharacter to 1 -- first character of retained substring
	set numberOfCharacters to 48 -- length of retained substring
	set trimThreshold to 48 -- minimum required length to trim a paragraph
	
	set theString to current application's NSString's stringWithContentsOfFile:sourceFile encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
	set theDelimiters to (current application's NSCharacterSet's newlineCharacterSet())
	set theArray to (theString's componentsSeparatedByCharactersInSet:theDelimiters)'s mutableCopy()
	
	set substringSearchPattern to "(?s)(?<=\\A.{" & firstCharacter - 1 & "}).{" & numberOfCharacters & "}"
	repeat with i from 1 to (theArray's |count|())
		set aParagraph to (theArray's objectAtIndex:(i - 1))
		if (count (aParagraph as text)) > trimThreshold then
			set substringRange to (aParagraph's rangeOfString:(substringSearchPattern) options:(current application's NSRegularExpressionSearch))
			set substringText to (aParagraph's substringWithRange:(substringRange))
			(theArray's replaceObjectAtIndex:(i - 1) withObject:substringText)
		end if
	end repeat
	set theString to theArray's componentsJoinedByString:linefeed
	
	set targetFile to getTargetFile(sourceFile, " (trimmed)")
	(current application's NSString's stringWithString:theString)'s writeToFile:targetFile atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
end main

on getTargetFile(theFile, theText)
	set theFile to current application's NSString's stringWithString:theFile
	set fileExtension to theFile's pathExtension()
	set fileNoExtension to theFile's stringByDeletingPathExtension()
	return (fileNoExtension's stringByAppendingString:theText)'s stringByAppendingPathExtension:fileExtension
end getTargetFile

main()

There could be issues with what constitutes 48 characters, given that NSString ranges are effectively based in 16-bit unichar units. It’s probably not a problem in this case, but if there is a chance of multi-unit characters, it gets a bit complex/impractical for ASObjC.

Ahem Peavine! :slight_smile:

That is way beyond my comprehension. I will take the 10 sec one over the 2 sec one any day.

But for what it’s worth, I am already done. My computer did it in roughly 15-20 secs, but even at that I was able to do 125 files in under 2 hours.

Thanks for everyone’s help.