Process "ANY" text!

Mac OSX specific forum
User avatar
Piero
Addict
Addict
Posts: 1112
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Process "ANY" text!

Post by Piero »

1st, save this Automator Quick Action as "writesel":

Image
Shell Script:

Code: Select all

cat > ~/Documents/myseltext.txt
 
PB Text Processor:
 

Code: Select all

; Make an Automator Quick Action named #servicen (writesel) for selected text, with Run Shell Script:
; cat > ~/Documents/myseltext.txt

EnableExplicit
#codepb="/code" ; trick to paste on Forum!
#servicen= "writesel" ; service name (it will avoid using clipboard if available)
#maxtype= 255 ; typing max (use clipboard if too much chars to type); clipboard will be restored… (0 for no typing)
#addesc= #True ; type ESC after "typing" (close PB autocomplete…)
#say = 1 ; 0 for no speaking
Global seltfile.s=GetUserDirectory(#PB_Directory_Documents)+"myseltext.txt" ; this file will be written and deleted!
Global ShOut.s, seltxt.s
#NSSquareStatusBarItemLength = -2
Define StatusBar,StatusItem

Procedure Shell(ShellCommand$)
   Protected Output$, shell, tmper$
   shell = RunProgram("/bin/sh","","",
      #PB_Program_Open|#PB_Program_Write|#PB_Program_Read)
   If shell
      WriteProgramStringN(shell,ShellCommand$)
      WriteProgramData(shell,#PB_Program_Eof,0)
      While ProgramRunning(shell)
         If AvailableProgramOutput(shell)
            Output$ + ReadProgramString(shell)+ Chr(13)
         EndIf
      Wend
   EndIf
   ShOut = Left(Output$,Len(Output$)-1)
EndProcedure

Procedure.s QP(str$) ; to quote paths
   ProcedureReturn "'" + ReplaceString(str$, "'", "'\''") + "'"
EndProcedure

Procedure.s GetText()
   Protected s.s,i.q
   Shell("rm -f "+QP(seltfile))
   Shell(~"osascript\n"+
      ~"tell application \"System Events\" to tell (1st application process whose frontmost is true)\n"+
      ~"try\n"+
      ~"perform action \"AXPick\" of menu item \""+#servicen+~"\" of menu 1 of menu item \"Services\""+
      ~" of menu 1 of menu bar item 2 of menu bar 1\n"+
      ~"on error\n"+
      ~"set cc to the clipboard\n"+
      ~"set the clipboard to \"\"\n"+
      ~"keystroke \"c\" using command down\n"+
      ~"delay .3\n"+
      ~"if (the clipboard) is \"\" then\n"+
      ~"set the clipboard to cc\n"+
      "if "+#say+" > 0 then "+~"say \"I tried to use clipboard, but there was No Selection\"\n"+
      ~"return\n"+
      ~"end\n"+
      ~"do shell script \"printf %s \" & quoted form of (the clipboard as text) & \" > "+QP(seltfile)+~"\"\n"+
      ~"set the clipboard to cc\n"+
      "if "+#say+" > 0 then "+~"say \"No Service\"\n"+
      ~"end\n"+
      ~"end\n")
   i=ElapsedMilliseconds()
   Delay(200)
   Shell("cat "+QP(seltfile))
   While FileSize(seltfile)=-1
      Delay(200)
      Shell("cat "+QP(seltfile))
      if (ElapsedMilliseconds()-i)>1800 : break : EndIf
   Wend
   s=shOut
   Shell("rm -f "+QP(seltfile))
   ProcedureReturn s
EndProcedure

Procedure.s PasteText(t.s)
   if t
      Protected  pasteScr.s = ~"osascript\n"+
         ~"tell application \"System Events\" to tell (1st application process whose frontmost is true)\n"+
         ~"set c to the clipboard\n"+
         ~"set the clipboard to \""+EscapeString(t)+~"\"\n"+
         ~"keystroke \"v\" using command down\n"+
         ~"delay .3\n"+
         ~"set the clipboard to c\n"+
         ~"end"
      Shell(pasteScr)
   EndIf
EndProcedure

Procedure checktypetext(t.s)
   Protected i
   For i = 1 to Len(t) : if Asc(Mid(t,i,1)) > 255 : ProcedureReturn 1 : endif : Next
   ProcedureReturn 0
EndProcedure

Procedure.s TypeText(t.s)
   if t
      if Len(t) <= #maxtype And Not checktypetext(t)
         Shell(~"osascript\ntell application \"System Events\" to keystroke \""+EscapeString(t)+~"\"")
         if #addesc : Shell(~"osascript\ntell application \"System Events\" to key code 53") : EndIf
         Shell(~"osascript\n if "+#say+~" > 0 then say \"I Used Typing\"")
      Else
         PasteText(t)
         Shell(~"osascript\n if "+#say+~" > 0 then say \"Pasted!\"")
      EndIf
   EndIf
EndProcedure

Procedure.s TitleCase(s.s)
   Protected c,cg,i,gl,m.s
   CreateRegularExpression(0,"(.*?)(\b[a-zA-Z][a-zA-Z]+)")
   If ExamineRegularExpression(0,s)
      While NextRegularExpressionMatch(0)
         c+RegularExpressionGroupLength(0,1)+1
         m=Mid(s,c,1)
         s=ReplaceString(s,m,UCase(m),0,c,1)
         gl=RegularExpressionGroupLength(0,2)
         cg=c+gl
         For i=c+1 To cg
            m=Mid(s,i,1)
            s=ReplaceString(s,m,LCase(m),0,i,1)
         Next
         c=cg-1
      Wend
   EndIf
   FreeRegularExpression(0)
   ProcedureReturn s
EndProcedure

Macro mm(m,d=0) : MenuItem(MacroExpandedCount, m) : If d : DisableMenuItem(0,MacroExpandedCount,d) : EndIf : EndMacro
Macro mc(m) : mm(m,1) : EndMacro
Macro cc(m=) : Case MacroExpandedCount : seltxt=GetText() : If seltxt : m : EndIf : EndMacro

OpenWindow(0, #PB_Any, #PB_Any, 300, 100, "Text Replacements",#PB_Window_Invisible)
LoadFont(0,"Apple Color Emoji",23,#PB_Font_HighQuality)
Define ItemLength.CGFloat = 22 ; space taken in menu bar
CreateImage(0, 32, 32, 32, 0) ; RGBA(0, 0, 0, 0)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_NativeText)
DrawingFont(FontID(0))
DrawText(5, 1, "🍕")
StopDrawing()
StatusBar = CocoaMessage(0, 0, "NSStatusBar systemStatusBar")
If StatusBar
   StatusItem = CocoaMessage(0, CocoaMessage(0, StatusBar,"statusItemWithLength:", #NSSquareStatusBarItemLength), "retain")
   If StatusItem
      CocoaMessage(0, StatusItem, "setLength:@", @ItemLength)
      CocoaMessage(0, StatusItem, "setImage:", ImageID(0))
      CreatePopupMenu(0)
      mc("Case") ; menu title
      mm(~"UPPERCASE\tCmd+Shift+U") ; ⌘⇧U in PB
      mm(~"lowercase\tCmd+Shift+L") ; ⌘⇧L in PB
      mc(~"tOGGLE cASE\tCmd+Shift+X") ; ⌘⇧X in PB
      mm("Title Case")
      MenuBar() ; --------------------
      mc("Enclose") ; menu title
      mm(~"\" \"")
      mm("( )")
      MenuBar() ; --------------------
      mc("BBcode") ; menu title
      mm("[code=purebasic]")
      mm("Apply Copied Link")
      
      MenuBar()
      MenuItem(999, "Quit")
      CocoaMessage(0, StatusItem, "setMenu:", MenuID(0))
      Repeat
         Select WaitWindowEvent()
            Case #PB_Event_CloseWindow
               Break
            Case #PB_Event_Menu
               Select EventMenu()
                  cc() ; case (title)
                  cc(TypeText(UCase(seltxt)))
                  cc(TypeText(LCase(seltxt)))
                  cc() ; inactive toggle case
                  cc(TypeText(TitleCase(seltxt)))
                  cc() ; enclose (title)
                  cc(TypeText(~"\""+seltxt+~"\""))
                  cc(TypeText("("+seltxt+")"))
                  cc() ; bbcode (title)
                  cc(TypeText("[code=purebasic]"+seltxt+"["+#codepb+"]"))
                  cc(TypeText("[url="+GetClipboardText()+"]"+seltxt+"[/url]"))
                     
                  Case 999 : Break
                  Case #PB_Menu_Quit : Break
               EndSelect
         EndSelect
      ForEver
   EndIf
EndIf
Last edited by Piero on Mon Dec 01, 2025 3:52 pm, edited 5 times in total.
User avatar
mk-soft
Always Here
Always Here
Posts: 6402
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Process "ANY" text!

Post by mk-soft »

I don't know why you always call a shell for scripts.
You can use AppleScript directly from PB.

Link: AppleScript with ErrorInfo
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Piero
Addict
Addict
Posts: 1112
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Process "ANY" text!

Post by Piero »

mk-soft wrote: Tue Nov 25, 2025 6:43 pm I don't know why you always call a shell for scripts.
Because it's extremely easier, for many reasons…
…and you use cocoa, while I use shell… (we do not use PB!) :P
User avatar
Piero
Addict
Addict
Posts: 1112
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Process "ANY" text!

Post by Piero »

mk-soft wrote: Tue Nov 25, 2025 6:43 pmdirectly from PB.
I'm using an intermediate disk file to get the selected text of almost any app, NOT to run (complex) applescripts!
Try to get it (the selected text of almost any app) with cocoa! (I found nothing on the net, so this seems to be a good new trick) :D
User avatar
Piero
Addict
Addict
Posts: 1112
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Process "ANY" text!

Post by Piero »

Updated

Code: Select all

Shell(~"osascript\ntell application \"System Events\" to keystroke \""+EscapeString(typet)+~"\"")
:wink:
User avatar
Piero
Addict
Addict
Posts: 1112
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Process "ANY" text!

Post by Piero »

Dramatically improved…

Dedicated to my Idol mk-soft (because we can always do it Better…)

…but NOT to Fred (registerServicesMenuSendTypes)
User avatar
Piero
Addict
Addict
Posts: 1112
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: Process "ANY" text!

Post by Piero »

Improved again!

Some shortcuts added just as reminders for PB IDE… but, for example, remember: if ⌘Q is implemented,
you can KEEP ⌘ PRESSED, tap TAB (repeatedly) and then tap Q to quit the selected app!

Useful free soft for this kind of stuff:
iCanHazShortcut free, opensource
FastScripts should be semi-free… (limited number of shortcuts)
WordServices free… and that web page has more good free stuff…

Dedicated to Fred (because I'm getting tired of always having to be critic!) ;)
Post Reply