Making 'Replace Text' command - Need help

Hi folks,

I’ve got a niche use-case for the standard ‘replace_chars’ AppleScript subroutine published on macosxautomation.comhttp://www.macosxautomation.com/applescript/sbrt/sbrt-06.html but I need guidance putting it together. I’ve tried a few things, but am getting null results.

I’m an ‘occasional’ AppleScripter, so as much as I’ve learnt, I forget most of it between jaunts - even basic formatting and syntax - so I’m hoping to get some help. I think this could be useful for others, so will publish in the Code Exchange if it works out.

The Use-Case:
Frequently I encounter text with a swath of “\t” (backslash t), in it that all need to be changed to the tab character. I would like to be able to simply;

  1. Have the [typing] cursor flashing anywhere in the body of text.
  2. Run this script (saved as a Service), and it will ‘find and replace’ all instances of “\t” at once.

[format]on replace_chars(this_text, search_string, replacement_string)
set AppleScript’s text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript’s text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript’s text item delimiters to “”
return this_text
end replace_chars
replace_chars(this_text, search_string, replacement_string)[/format]

The Problem:
I’m not sure. I saved this as a Service, but it won’t even show up in the Services menu, so I can’t test it with a body of text in TextEdit (for example). I don’t know if there’s an issue with the script or if it won’t appear in the Services menu because there’s a problem with the script.

Model: 15" Retina MBP 2012, macOS 10.15.7
AppleScript: 2.11
Browser: Safari 605.1.15
Operating System: macOS 10.14

What you call “backslash t” and “tab character” are the same thing. So, you try to change “A” to “A”, and you will be able to do it. Only the text will remain unchanged as a result:


set this_text to "Hi,	forks" -- contains invisible tab character:
-- RESULT: "Hi, \tforks"
replace_chars(this_text, "	", tab) -- replace invisible tab with tab constant
-- RESULT : "Hi, \tforks"

on replace_chars(this_text, search_string, replacement_string)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end replace_chars

Now, assuming you want to create service to replace in the TextEdit’s selected text every tab character with space character:

  1. Choose - Quick Action
  2. Set - Workflow receives current text in “TextEdit.app”
  3. Set checkbox flag - Output replaces current text
  4. Drag Run AppleScript to the editor area on the right side of window
  5. For the script use this:

use AppleScript version "2.4" -- Yosemite (10.10) or later  
use scripting additions 

on run {input, parameters}
	set text item delimiters of AppleScript to tab
	set input to text items of (input as text) -- -- coercion is required
	set text item delimiters of AppleScript to space
	set input to input as string
	set text item delimiters of AppleScript to ""
	return input
end run

Save the service with some clear name. For example, “Replace Tabs with Spaces”. Done, use it.

Tip: it is better using service with any application. To achieve this, simply set in the step 2) this:
------------------- Workflow receives current text in “any application” ---------------------

No, they aren’t. In some contexts, “\t” is interpreted as a symbolic representation of a tab character that is substituted in its place during rendering or parsing, but the OP hasn’t stated what situations he comes across these “\t”, and it might be that these are literal “backslash-t” character pairs.

But since replacing a literal “\t” with a tab character would not be detrimental if it does the same for a \t placeholder, the specifics aren’t needed in order to solve the problem, and your idea of using a Quick Action that replaces the selections with the workflow’s output is an excellent one.

An “invisible” tab and AppleScript’s tab property are identical in value:

return "	" = tab
--> true

When you specify the tab property as an argument to your handler, the property is evaluated during runtime and its value passed to the handler. So you’re search_string and replacement_string are both the same.

The following should suffice, when used as part of a Quick Action that, as you stated, is best made available in any application:

on run {input as text}
		set my text item delimiters to {tab, "\\t"}
		return the input's text items as text
end run

Doesn’t the OP specify that the cursor merely be anywhere in the text, rather than having to pre-select the text? Will the service even show up without a selection?

The service will always be available when editing text, as a selection object always exists (although it may have zero length). However, the service will only process the contents of the selection, so having the cursor merely positioned within a body of text is not going to work. I also wouldn’t put too much effort into trying to make that work, as it’s not a very sensible idea. If the aim were to apply the change to the entire contents of a document, then one should really be passing it a file reference or document to process, rather than text.

Thanks for clarifying but FWIW, if in TextEdit say… if nothing is (visibly) selected, then no Services contextual menu is available, and if I go to the TextEdit > Services menu, it specifies that ‘No Services Apply’. When I select something, I get the full panoply of Service choices, and if I subsequently de-select everything, then none will apply again.

As to OP’s intent, perhaps they want it to apply to an entire document but may not know until the document is open — essentially to ‘replace all’ and not be constrained to the selected text. Even Apple’s find/replace mechanisms support this (in the GUI).

I would like to add one comment that seems to be directly related to the fact that the OP is still silent. I think we did not answer his main question: why the Services menu does not appear (when selected the tab character or when selected nothing)?

Here is my answer, which will probably satisfy the OP at least partially:

  1. The Services menu appears only when the user selects text, moreover,
  2. the selected text must contain at least one visible letter, otherwise the selection is considered empty and Services menu doesn’t appear.

Whether this is an oversight (bug) on the part of Apple or is it done on purpose, I don’t know. OP will simply have to choose, along with the invisible tab, any visible letters next to it.