I've posted a method to count characters here:
I’m always amazed with the creativity people have on this forum. When I see potential solutions like yours, Chris, it just makes me smile. I never would have thought of your solution.
I need to remember to post more questions, to see if there’s better ways of doing things. In this forum, multiple heads truly are better than one.
@nadeama, I think this should do the job for you.
Please test the below macro, and let me know if it works for you.
Turns out that there is no easy way to find the position of a substring within a string using non-script KM Actions. So, I wrote a general purpose script to do this.
Hey Chris, great thinking outside the box.
Very clever.
However, there may be some limitations and undesired consequences to this approach:
- I don't think it would work in a single-line text field.
- Adding a linefeed might trigger some other effects in some apps
- Since the paste is plain text, it might remove the formatting of styled text in the original document.
Hi everyone,
Thanks so much for your solutions. You guys are great!
Chris, your inventive solution worked like a charm in TextEdit, but as Michael pointed out it was problematic in iTunes (where I want to use it) because of the single-line fields of the Get Info dialog.
Michael, your script did the trick. You just saved me hours and hours of manual text input when editing tags in iTunes (I do a lot of that). Thank you!
Keyboard Maestro is really amazing. I can’t believe I haven’t used it before for anything but launching apps with a keystroke.
Very nice, Chris!
I have used this technique to create this macro:
Position cursor behind entered character.kmmacros (11.4 KB)
Demo:
Nice, @ALYB. I got a little dizzy looking at your list of triggers, though, and wrote a different version that uses typed string trigger. You trigger it by typing two semi-colons and then the character in question, with no spaces, like so: ;;v
, etc.
ALYB.kmmacros (6.0 KB)
Yes, @cfriend I don’t like this long list of hotkeys either, and it costs a lot of hotkeys that are no longer available to other macros. Ideally I would press: one hotkey, character. But afaik this isn’t possible.
I will try this suggestion: Initiator + Multiple Keystroke Trigger - #3 by noisneil
Edit: Works okay.
Thanks! It worked for me too!
Hey Chris, I don't know if this belongs in a separate question or can just be added to this one.
I'm looking to move the cursor to immediately before the next open parenthesis and insert a couple of returns then immediately after a close parenthesis character and add another return. This moves the text within the parentheses along with the parenthesis onto their own line and out of the body of the text they are within so
...sdflsdkfjsldfj asldkfj (dsjfasdfjsl sldfjsldfk) dkjfhsdkfjhs sadfsdf... becomes
...sdflsdkfjsldfj asldkfj
(dsjfasdfjsl sldfjsldfk)
dkjfhsdkfjhs sadfsdf...
Running the macro would then go to the next instance and pull out the text in parentheses along the enclosing parentheses.
FYI this is cleaning a large book worth text with loads these edits.
I think I can figure out how to get regex to find the characters I want but don't know how to use what regex finds to move the cursor to before or after the output.
Thanks for looking at this.
The following should work. You can use a variable as your input instead of the sample text that I copied from your example. However if your text is inside a word processor with special formatting, this won't work. I couldn't tell if you were intending for this to work in a word processor or not. If so, the solution will be more complex.
Here's the text:
sed "s/(/\n\n(/g;s/)/)\n/g"
Any reason why you can't do a Search for (
and Replace with \n\n(
, followed by a Search for )
and Replace with )\n
, either using KM or just using your editor's standard S'nR dialog?
I see specifying that I'm doing this in Apple Pages was missing and needed.
I see I can do this with Page's SnR, and it'd be mighty slow and clunky. A macro would be much better.
Using Keyboard Maestro's Search and Replace, can I use the variable of the current text insertion point as the search beginning point and then search for ( and replace with \n\n( ?
If not, how do I set it up?
Here is a better sample text:
So it’s good that you’re pessimistic, and if you’re not pessimistic, that’s good too. (to Ruth) If you find yourself being that way, don’t try to change it.
Changed to:
So it’s good that you’re pessimistic, and if you’re not pessimistic, that’s good too.
(to Ruth)
If you find yourself being that way, don’t try to change it.
Thank you for addressing this.
You can do that with Pages directly. Pages supports that.
You can't do it with KM because KM requires plaintext for its Search and Replace.
I recommended doing the work with plaintext, but you said you didn't want to do that. Alright, then your choice is to use Pages's clunky interface or discover if there is an AppleScript interface to Pages that speeds this up (I suspect there isn't, but I'm not sure.)
Despite these things, there's a 10% chance someone here that's smarter than me can think of a better solution for you.
To be honest, I don't see why you want to avoid Pages's clunky interface. Sure, it's a couple of menu presses and keystrokes entered, which is messy. But that's nothing significant. What's wrong with taking a fraction of a second to get the job done?
Not a Pages power user, so I may be missing some nuance here, but why would
...followed by
...be "mighty slow and clunky"?
Anything else is going to depend on you visiting the body text and then every text box in turn, since the find and replace in Pages has neither AppleScript nor Shortcut support -- and that's before getting into how to find and change the text. Even if you've multiple searches to do, that's going to be way trickier than using KM to automate the built-in dialog.
Edit to add:
So here's an AppleScript to find'n'replace pairs of terms across the whole(?) of the front Pages document. It's working on a short document, but see this thread for problems you might stumble across.
set pairsList to {¬
{"(", linefeed & linefeed & "("}, ¬
{")", ")" & linefeed} ¬
}
tell application "Pages"
tell document 1
set thePages to a reference to every page
repeat with eachPage in thePages
tell body text of eachPage
repeat with eachPair in pairsList
set (every character where it is (contents of first item of eachPair)) to (contents of second item of eachPair)
end repeat
end tell
end repeat
set textItems to every text item
repeat with eachTextItem in textItems
tell object text of eachTextItem
repeat with eachPair in pairsList
set (every character where it is (contents of first item of eachPair)) to (contents of second item of eachPair)
end repeat
end tell
end repeat
end tell
end tell
First, thank you, and Airy both! Neither of you has to or even needs to give this your time, attention, or the work of thinking about it, yet you have. I really appreciate it!! I don't take the generosity routinely exhibited around this forum for granted, at all!
"Mighty slow and clunky" "...missing some nuance here..." "What's wrong with taking a fraction of a second to get the job done?"
The volume of text is in the neighborhood of 480 pages, with hundreds of edits needed. Correct my thinking or provide the missing thinking, as you have generously been doing, and here’s what I got. (No sarcasm whatsoever intended. I’m just being as straight as I can be.)
When I look at how many individual steps/keystrokes/actions it takes to complete one of these S&Rs, I roughly estimate 25 or more discrete actions for each parenthesis. That's where slow and clunky is for me. What I'm really looking for is a way to minimize that volume of actions, given it must be repeated for hundreds of instances.
The AppleScript looks very promising. It needs some work that is above my paid grade. What happens is that it moves the first instance to a new line using two returns and puts in a return after the closing parenthesis. The issue then is that it stops there and doesn’t continue to the next instance.
Running the AppleScript again adds two more returns before the first instance and one more after, which looks like it is repeating its action successfully but again does not continue on to the next instance.
Ideally, rather than having the script run through the entire document, which to your reference points out that large volumes of text don’t play nice, it would be better if (if possible and not crazy difficult or complex) the S&R could commence at the insertion point and search forward as the built-in function works.
Here are some pics showing the issue:
No. It does not have to be repeated at all, because Pages has a button called "Replace All." Everything can be done with a single action.
You'll see from the earlier-linked thread that Pages has problems running AppleScripts over large amounts of text -- and it looks like you've enough on every page that even taking it one page at a time is hitting those limits.
As @Airy says, if you want to replace all "(" and ")" you should be able to do it within Pages with just two global Find and Replace operations -- it isn't even worth writing a macro. I put screen shots of the two (tested) dialogs in my previous post.
If you want to only replace some -- say, put Returns before and after (to Ruth)
but never around (laughter)
-- you are going to have to get creative. If it is a limited "exclusion list" I'd do something like:
- Find and Replace all the "(" and ")" around the exclusion list terms with "####" and "$$$$", respectively
- Do the above two Find and Replaces on all remaining "(" and ")"s
- Find and Replace "####" and "$$$$" with "(" and ")", respectively
If there's a lot of these it wouldn't be too difficult to put the list into a KM variable and drive the dialogs with a macro.
Anything more complicated and you are probably better off exporting to Word or LibreOffice, using their regular expression supporting Find and Replaces, re-importing the result back into Pages.