├── .gitignore ├── Edit-Anywhere.kmmacros ├── README.md └── images ├── Edit Anywhere 2.kmmacros ├── Edit Anywhere.kmmacros └── define-your-editor.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /Edit-Anywhere.kmmacros: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Activate 7 | Normal 8 | CreationDate 9 | 459387347.72605699 10 | IsActive 11 | 12 | Macros 13 | 14 | 15 | Actions 16 | 17 | 18 | IsActive 19 | 20 | IsDisclosed 21 | 22 | MacroActionType 23 | Comment 24 | Text 25 | If you want to change where the temporary file is stored, edit the EDIT_ANYWHERE_FILE variable. 26 | 27 | Note that the filename (and path, if any) will be relative to your $HOME. So, for example, if you want to use a file named ~/Dropbox/txt/my-very-special-name-here.txt then you should set the variable to "Dropbox/txt/my-very-special-name-here.txt" 28 | 29 | Do NOT include the /Users/YourNameHere/ part of the path, that will be added automatically later. 30 | 31 | Do not change the variable name (EDIT_ANYWHERE_FILE) just change the part in the "To:" field. 32 | 33 | 34 | Title 35 | Note: You can customize 'EDIT_ANYWHERE_FILE' 36 | 37 | 38 | IsActive 39 | 40 | IsDisclosed 41 | 42 | MacroActionType 43 | SetVariableToText 44 | Text 45 | edit_anywhere.txt 46 | Variable 47 | EDIT_ANYWHERE_FILE 48 | 49 | 50 | ActionName 51 | Store to the name of the active application to the variable ‘EditAnywhereApp’ 52 | IsActive 53 | 54 | IsDisclosed 55 | 56 | MacroActionType 57 | SetVariableToText 58 | Text 59 | %Application%1% 60 | Variable 61 | EditAnywhereApp 62 | 63 | 64 | ActionName 65 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 66 | IsActive 67 | 68 | IsDisclosed 69 | 70 | KeyCode 71 | 0 72 | MacroActionType 73 | SimulateKeystroke 74 | Modifiers 75 | 256 76 | ReleaseAll 77 | 78 | 79 | 80 | ActionName 81 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 82 | IsActive 83 | 84 | IsDisclosed 85 | 86 | KeyCode 87 | 0 88 | MacroActionType 89 | SimulateKeystroke 90 | Modifiers 91 | 256 92 | ReleaseAll 93 | 94 | 95 | 96 | IsActive 97 | 98 | IsDisclosed 99 | 100 | MacroActionType 101 | Pause 102 | Time 103 | 1 104 | TimeOutAbortsMacro 105 | 106 | 107 | 108 | IsActive 109 | 110 | IsDisclosed 111 | 112 | KeyCode 113 | 7 114 | MacroActionType 115 | SimulateKeystroke 116 | Modifiers 117 | 256 118 | ReleaseAll 119 | 120 | 121 | 122 | Action 123 | ByTyping 124 | IsActive 125 | 126 | IsDisclosed 127 | 128 | MacroActionType 129 | InsertText 130 | Paste 131 | 132 | Text 133 | (Waiting for EditAnywhere) 134 | 135 | 136 | ActionName 137 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 138 | IsActive 139 | 140 | IsDisclosed 141 | 142 | KeyCode 143 | 0 144 | MacroActionType 145 | SimulateKeystroke 146 | Modifiers 147 | 256 148 | ReleaseAll 149 | 150 | 151 | 152 | IsActive 153 | 154 | IsDisclosed 155 | 156 | MacroActionType 157 | Pause 158 | Time 159 | .5 160 | TimeOutAbortsMacro 161 | 162 | 163 | 164 | ActionName 165 | This is where the magic happens 166 | DisplayKind 167 | None 168 | IncludeStdErr 169 | 170 | IsActive 171 | 172 | IsDisclosed 173 | 174 | MacroActionType 175 | ExecuteShellScript 176 | Path 177 | /usr/local/scripts/km-edit-anywhere-any-editor.sh 178 | Text 179 | #!/bin/zsh -f 180 | 181 | 182 | ## This is the app that you want to use as your external editor 183 | ## Note that it should not include the '.app' suffix 184 | ## 185 | ## Examples: 186 | ## APP='BBEdit' 187 | ## APP='TextWrangler' 188 | ## APP='MultiMarkdown Composer' 189 | ## 190 | APP='BBEdit' 191 | 192 | ## OS X no longer has a good way to ensure that GUI apps like 193 | ## Keyboard Maestro have access to your $PATH so I often just create 194 | ## a text file in my $HOME which I can use in all my scripts. This 195 | ## checks to see if that file exists, and if it does not exist, it 196 | ## will use the PATH as defined in the second half of the if/else 197 | 198 | if [[ -e "$HOME/.path" ]] 199 | then 200 | source "$HOME/.path" 201 | else 202 | PATH=/usr/local/scripts:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin 203 | fi 204 | 205 | 206 | 207 | 208 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|#### 209 | # 210 | # You should not ~need~ to edit anything below this line 211 | # 212 | 213 | 214 | ###################################################################### 215 | ## This is the name of the temporary file which will be used to keep 216 | ## your edits before it is sent back to the app where it came from. 217 | ## 218 | ## This is now based on a variable set in the Keyboard Maestro macro 219 | ## 220 | 221 | ## If, for some reason, the filename is NOT set, use a reasonable default 222 | [[ "$KMVAR_EDIT_ANYWHERE_FILE" == "" ]] && KMVAR_EDIT_ANYWHERE_FILE='edit_anywhere.txt' 223 | 224 | ## Try to protect against someone putting '..' in the file path and 225 | ## attempting to get out of the $HOME I don't know if this is 226 | ## actually necessary, but once it occurred to me, I figured I might 227 | ## as well add it. 228 | FILE=`echo "${HOME}/${KMVAR_EDIT_ANYWHERE_FILE}" | tr -s '.' '.'` 229 | 230 | 231 | NAME="[Edit Anywhere via Keyboard Maestro]" 232 | 233 | ## Change this if necessary 234 | ## Used for pbcopy and pbpaste 235 | LANG=en_US.UTF-8 236 | 237 | zmodload zsh/datetime ## needed for strftime 238 | 239 | function timestamp { strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS" } 240 | 241 | # This gives us a unique reference point for when the script was launched 242 | TIME=`strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS"` 243 | 244 | 245 | if (( $+commands[growlnotify] )) 246 | then 247 | ## We found the growlnotify tool installed 248 | GROWLNOTIFY_FOUND='yes' 249 | 250 | ## We only check to see if Growl.app is running IFF we have 251 | ## found growlnotify because otherwise there's no point caring. 252 | 253 | if [ "`pgrep -x Growl`" = "" ] 254 | then 255 | ## Growl is NOT running 256 | GROWL_RUNNING='no' 257 | else 258 | ## Growl IS running 259 | GROWL_RUNNING='yes' 260 | fi 261 | 262 | else 263 | ## We did NOT find the growlnotify tool installed 264 | GROWLNOTIFY_FOUND='no' 265 | 266 | ## We just set this to 'no' because it doesn't matter, if the 267 | ## growlnotify tool isn't found too. 268 | GROWL_RUNNING='no' 269 | fi 270 | 271 | 272 | if [ "$GROWL_RUNNING" = "yes" -a "$GROWLNOTIFY_FOUND" = "yes" ] 273 | then 274 | ## If growlnotify is installed AND Growl.app is running, use Growl for notifications 275 | 276 | function msg 277 | { 278 | growlnotify \ 279 | --appIcon "$APP" \ 280 | --identifier "$NAME" \ 281 | --message "$@" \ 282 | --title "$NAME" 283 | 284 | } ## end of msg/growl 285 | 286 | 287 | elif (( $+commands[terminal-notifier] )) 288 | then 289 | ## OTHERWISE, use terminal-notifier for notifications, if it is installed. 290 | 291 | function msg 292 | { 293 | if [[ -e "/Applications/$APP.app/Contents/Info.plist" ]] 294 | then 295 | ## If there is an app plist where we'd expect it to be, try to get the Bundle identifier from it 296 | 297 | TN_BUNDLE_ID=`defaults read /Applications/${APP}.app/Contents/Info CFBundleIdentifier` 298 | fi 299 | 300 | ## If we were not able to get a bundle ID, use Keyboard Maestro's 301 | [[ "$TN_BUNDLE_ID" == "" ]] && TN_BUNDLE_ID='com.stairways.keyboardmaestro.editor' 302 | 303 | terminal-notifier \ 304 | -title "$NAME" \ 305 | -subtitle "`timestamp`" \ 306 | -group "$NAME" \ 307 | -sender "$TN_BUNDLE_ID" \ 308 | -activate "$TN_BUNDLE_ID" \ 309 | -message "$@" 310 | } ## end of msg/terminal-notifier 311 | 312 | else 313 | 314 | function msg { echo "$NAME: $@" | tee -a "${TMPDIR-/tmp/}${NAME}.$TIME.log" } 315 | 316 | fi 317 | 318 | 319 | ########################################################################################### 320 | ########################################################################################### 321 | ## 322 | ## Here is where the action begins 323 | ## 324 | 325 | ## What do we do if they asked for a path which does not exist? 326 | ## Well, we will try to create the folder and then paste the file in there 327 | PARENT_DIR="$FILE:h" 328 | 329 | [[ ! -d "$PARENT_DIR" ]] && mkdir -p "$PARENT_DIR" && msg "Created $PARENT_DIR for $FILE" 330 | 331 | if [[ -e "$FILE" ]] 332 | then 333 | pbpaste >> "$FILE" 334 | else 335 | pbpaste > "$FILE" 336 | fi 337 | 338 | EXIT="$?" 339 | 340 | if [ "$EXIT" != "0" ] 341 | then 342 | 343 | msg "FATAL ERROR: Failed to create file at $FILE. Exit = $EXIT. Sorry." 344 | 345 | ## if we can't create the file, send the contents of the 346 | ## pasteboard to a temp file in TextEdit at least so the user 347 | ## will not lose whatever they had there at least 348 | /usr/bin/pbpaste | /usr/bin/open -e -f 349 | 350 | exit 1 351 | fi 352 | 353 | 354 | if [[ "$KMVAR_EditAnywhereApp" == "" ]] 355 | then 356 | ## "$KMVAR_EditAnywhereApp" is not set. ABORT. 357 | 358 | msg "Variable KMVAR_EditAnywhereApp is empty. Giving up." 359 | 360 | ## Open the file in the default text editor 361 | ## so the user knows their text has not been lost 362 | /usr/bin/open -t "$FILE" 363 | 364 | exit 1 365 | 366 | else 367 | ## Tell the user what app we took text from 368 | ## This is mostly a debugging comment and could be removed if it annoys you 369 | msg "Will send text back to: $KMVAR_EditAnywhereApp" 370 | 371 | fi 372 | 373 | 374 | if (( $+commands[bbedit] )) 375 | then 376 | ## We found the command line bbedit tool 377 | CL_BBEDIT='yes' 378 | else 379 | ## We did NOT find the command line bbedit tool 380 | CL_BBEDIT='no' 381 | fi 382 | 383 | 384 | 385 | if [[ "$CL_BBEDIT" = "yes" && "$APP:l" == "bbedit" ]] 386 | then 387 | ## IFF the user wants to use BBEdit and they have the bbedit 388 | ## command line tool installed, then we will use the bbedit tool 389 | 390 | ## if BBEdit is not running, launch it 391 | pgrep -xq BBEdit || (open -a BBEdit && sleep 3) 392 | 393 | ## We will try to open the app with the bbedit command, 394 | ## but if it fails we will open TextEdit 395 | bbedit \ 396 | --language 'Markdown' \ 397 | --create-unix \ 398 | --new-window \ 399 | --resume \ 400 | --wait \ 401 | -- "$FILE" \ 402 | || open -n -e -W "$FILE" 403 | 404 | else 405 | ## if we get here, either the app is NOT BBEdit 406 | ## or they do not have the `bbedit` tool installed 407 | 408 | ## We will try to open the file in the requested app 409 | ## but if the open command fails for some reason, 410 | ## we will open TextEdit 411 | 412 | open -a "$APP" -n -W "$FILE" || open -a -n -e -W "$FILE" 413 | 414 | fi # if app is BBEdit 415 | 416 | 417 | EXIT="$?" 418 | 419 | if [ "$EXIT" != "0" ] 420 | then 421 | 422 | ## If we get here, something went wrong 423 | 424 | msg "Unable to open $FILE in $APP." 425 | 426 | ## Show the file in the Finder, so the user can try to do something with it 427 | /usr/bin/open -R "$FILE" 428 | 429 | exit 1 430 | fi 431 | 432 | ## If we get here, `open` or `bbedit` exited successfully 433 | 434 | 435 | ## Make sure that the app we want to paste into is actually running 436 | ## it *should* be, but it's possible that it either crashed or the 437 | ## user quit it in the interim, so let's check 438 | 439 | pgrep -xq "$KMVAR_EditAnywhereApp" 440 | 441 | EXIT="$?" 442 | 443 | if [ "$EXIT" = "1" ] 444 | then 445 | 446 | ## If we get here, the app is NOT running, so let's tell the user 447 | ## that we are launching it. 448 | 449 | msg "Launching $KMVAR_EditAnywhereApp so we can paste to it" 450 | 451 | 452 | ## Here is where we actually launch the app 453 | open -a "$KMVAR_EditAnywhereApp" 454 | 455 | ## now we need to give it a few seconds to get itself running 456 | ## This is guesswork, because we don't know how long it will 457 | ## take for the app to launch and be ready to accept input 458 | sleep 5 459 | fi 460 | 461 | ## Tell the user we are ready to paste information back to the source app 462 | msg "Pasting text to $KMVAR_EditAnywhereApp" 463 | 464 | ## Activate the app 465 | ## NOTE: originally this was not happening fast enough 466 | ## for it to be ready to accept a 'paste' 467 | ## when this script finished 468 | ## so I added some extra 'padding' 469 | ## and an extra 'open' call 470 | ## This should not harm anything. 471 | 472 | open -a "$KMVAR_EditAnywhereApp" 473 | 474 | ## wait a second 475 | sleep 1 476 | 477 | ## No no, REALLY activate the app 478 | open -a "$KMVAR_EditAnywhereApp" 479 | 480 | 481 | ## copy the file back to the pasteboard 482 | pbcopy < "$FILE" 483 | 484 | ## OK, now we are done with the FILE so we have to either leave it there, 485 | ## delete it, or move it to the trash. 486 | ## I don't want to leave it there when it has already been used, 487 | ## and I don't want to delete it in case something went wrong 488 | ## So I'm going to move it to the trash instead 489 | ## AND I'm going to rename the file with the current time stamp so if I 490 | ## happen to have several of these and need to recover one, 491 | ## I can do that, as long as I haven't emptied my trash 492 | 493 | ## This will be 'edit_anywhere' without the path or extension 494 | ## unless you changed $FILE 495 | SHORT="$FILE:t:r" 496 | 497 | ## This will be 'txt' unless you changed $FILE 498 | EXT="$FILE:e" 499 | 500 | /bin/mv -n "$FILE" "$HOME/.Trash/$SHORT.`timestamp`.$EXT" 501 | 502 | exit 0 503 | #EOF 504 | 505 | TimeOutAbortsMacro 506 | 507 | TimeOutPeriod 508 | 86400 509 | TrimResults 510 | 511 | TrimResultsNew 512 | 513 | UseText 514 | 515 | 516 | 517 | ActionName 518 | Paste contents of file back to "Source" app 519 | Conditions 520 | 521 | ConditionList 522 | 523 | 524 | ConditionType 525 | Menu 526 | MenuConditionSelectionType 527 | Is 528 | MenuConditionType 529 | IsEnabled 530 | MenuModifiers 531 | 256 532 | MenuShortcut 533 | C 534 | MenuTitle 535 | Paste 536 | 537 | 538 | ConditionListMatch 539 | All 540 | 541 | ElseActions 542 | 543 | 544 | IsActive 545 | 546 | IsDisclosed 547 | 548 | KeyCode 549 | 9 550 | MacroActionType 551 | SimulateKeystroke 552 | Modifiers 553 | 256 554 | ReleaseAll 555 | 556 | 557 | 558 | IsActive 559 | 560 | IsDisclosed 561 | 562 | MacroActionType 563 | IfThenElse 564 | ThenActions 565 | 566 | 567 | IsActive 568 | 569 | IsDisclosed 570 | 571 | MacroActionType 572 | SelectMenuItem 573 | Menu 574 | 575 | Edit 576 | Paste 577 | 578 | TargetingType 579 | Front 580 | 581 | 582 | TimeOutAbortsMacro 583 | 584 | 585 | 586 | CreationDate 587 | 459387347.72605699 588 | IsActive 589 | 590 | ModificationDate 591 | 460507471.884552 592 | Name 593 | Edit Anywhere 594 | Triggers 595 | 596 | 597 | FireType 598 | Pressed 599 | KeyCode 600 | 11 601 | MacroTriggerType 602 | HotKey 603 | Modifiers 604 | 6912 605 | 606 | 607 | UID 608 | 63DA32F6-8BA8-49AD-B4BC-C9AC7761D87E 609 | 610 | 611 | Name 612 | Global Macro Group 613 | ToggleMacroUID 614 | 4948A9C1-5CD3-4AA1-A25D-9D29C5471ED8 615 | UID 616 | DA8512F7-F323-46B1-8319-752E0495CFD0 617 | 618 | 619 | 620 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | edit-anywhere 2 | ============= 3 | 4 | **Summary:** A quick-and-dirty attempt at implementing [QuickCursor][1] using [BBEdit][2] and [Keyboard Maestro][3]. 5 | 6 | **For those who aren't familiar with QuickCursor:** 7 | QuickCursor did one thing really well: anywhere you could edit text, it would send that text to [your favorite text editor][2] and then when you closed that file, it would send the text back to the original application. 8 | 9 | So, for example, if you were using Google Chrome to write an email in GMail but wanted to write it in BBEdit, you would just press your keyboard shortcut for QuickCursor, it would select all of the text (or just part of it if you had some already selected), cut it, open it in BBEdit, wait for you to finish, and then switch back to Google Chrome and paste the text that you had written in BBEdit. 10 | 11 | Got it? Good. (If not, watch [the YouTube video for QuickCursor][4].) 12 | 13 | ### If QuickCursor is so great, why are you using this? ### 14 | 15 | In a word: [sandboxing][5]. QuickCursor was killed by sandboxing. 16 | 17 | This annoyed me for several reasons. QuickCursor was the first app that I bought from the Mac App Store. But most of all I really missed being able to edit text in BBEdit from anywhere. 18 | 19 | ### How does this work? ### 20 | 21 | Like so: 22 | 23 | 1. User presses a keyboard shortcut which has been defined in Keyboard Maestro which triggers a macro which I call 'edit anywhere' (or "EA" for short). 24 | 25 | 2. EA checks to see if the menu item 'cut' is enabled. 26 | * if yes, then EA assumes that you have some text selected, and that is the text you want to edit. 27 | * if no, EA will do 'Select All' (using either the menu item or ⌘ + A depending on which is available) 28 | 29 | 3. EA will then 'cut' the text from step 2 and save it to a file `~/edit_anywhere.txt`. That file is in your home directory, which means that: 30 | * you can save it as often as you like 31 | * if you reboot your computer (or, heaven forbid, it crashes) the file will still be there 32 | * it is secure, at least in as much as no one else should be able to read it unless they already have access to your account. 33 | 34 | 4. EA will then open the file in your editor of choice 35 | * If you use BBEdit and have the `bbedit` command-line tool installed, the script will use that. The file will open in BBEdit and the script will pause until you close the file in BBEdit. You do not have to quit the BBEdit app, just close the window or ‘tab’ where you had been editing the document. (Note: if you purchased BBEdit from the Mac App Store you will have to [download and install the command line tools from BareBones.com][6].) 36 | 37 | * If you use another editor, it will be opened using `open -a YourAppHere -n -W` which means that a new instance of the app will be opened (even if it is already running) and the script will wait until that _instance_ of the app has quit (not just the window closed, but the app quit). 38 | 39 | 40 | 5. EA will then paste the contents of `~/edit_anywhere.txt` into the original app. 41 | 42 | 8. EA will then rename the `~/edit_anywhere.txt` file to something like `edit_anywhere.2015-08-05--16.30.15.txt` (representing the current date and 24h-time) and move it to the trash (~/.Trash/). This is intended as a safety net in case you need to recover text from the file for some reason. (For example, if pasting the contents of the file into the original app did not work for some reason.) 43 | 44 | 45 | ### There are a few provisos, a couple of *quid pro quos*. 46 | 47 | * This will only work in ‘regular’ applications. Specifically, if will ***not*** work in applications which only exist in the menu bar. This limitation was present in QuickCursor too. When in doubt, I recommend testing the “round trip” in your app of choice to make sure that it works as expected. 48 | 49 | ### Future Feature Ideas 50 | 51 | * Now the the script knows which app that the content came from, it would be fairly easy to define different text editors depending on which app sent the text. For example, when you invoke this macro from Scrivener, it could open MultiMarkdown Composer or Byword instead of your regular app. 52 | 53 | ### FAQ: “How do I use a different app besides BBEdit?” 54 | 55 | The macro assumes you want to use BBEdit unless you change the `APP=` variable in the script section of the macro, as shown here: 56 | 57 | ![](images/define-your-editor.jpg) 58 | 59 | ### FAQ: “How do I install this?” 60 | 61 | 1. [Download the macro](https://github.com/tjluoma/edit-anywhere/raw/master/Edit-Anywhere.kmmacros) (right click on that link and use save as, or equivalent.) 62 | 63 | 2. Make sure the file extension is `.kmmacros` (Be sure that your browser did ***not*** rename it to something like `.kmmacros.txt`) 64 | 65 | 3. Double-click the file to add it to Keyboard Maestro. If it does not open in Keyboard Maestro, see Step #2. (Use the Inspector in Finder to check the full filename.) 66 | 67 | 68 | [1]: http://www.hogbaysoftware.com/products/quickcursor 69 | [2]: http://barebones.com 70 | [3]: http://www.keyboardmaestro.com/main/ 71 | [4]: http://www.youtube.com/watch?v=-bHwcyHrRGs 72 | [5]: http://www.hogbaysoftware.com/products/quickcursor/faq 73 | [6]: http://www.barebones.com/support/bbedit/cmd-line-tools.html -------------------------------------------------------------------------------- /images/Edit Anywhere 2.kmmacros: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Activate 7 | Normal 8 | CreationDate 9 | 459387347.72605699 10 | IsActive 11 | 12 | Macros 13 | 14 | 15 | Actions 16 | 17 | 18 | ActionName 19 | Store to the name of the active application to the variable ‘EditAnywhereApp’ 20 | IsActive 21 | 22 | IsDisclosed 23 | 24 | MacroActionType 25 | SetVariableToText 26 | Text 27 | %Application%1% 28 | Variable 29 | EditAnywhereApp 30 | 31 | 32 | ActionName 33 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 34 | IsActive 35 | 36 | IsDisclosed 37 | 38 | KeyCode 39 | 0 40 | MacroActionType 41 | SimulateKeystroke 42 | Modifiers 43 | 256 44 | ReleaseAll 45 | 46 | 47 | 48 | ActionName 49 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 50 | IsActive 51 | 52 | IsDisclosed 53 | 54 | KeyCode 55 | 0 56 | MacroActionType 57 | SimulateKeystroke 58 | Modifiers 59 | 256 60 | ReleaseAll 61 | 62 | 63 | 64 | IsActive 65 | 66 | IsDisclosed 67 | 68 | MacroActionType 69 | Pause 70 | Time 71 | 1 72 | TimeOutAbortsMacro 73 | 74 | 75 | 76 | IsActive 77 | 78 | IsDisclosed 79 | 80 | KeyCode 81 | 7 82 | MacroActionType 83 | SimulateKeystroke 84 | Modifiers 85 | 256 86 | ReleaseAll 87 | 88 | 89 | 90 | ActionName 91 | Save clipboard info to ~/edit_anywhere.txt 92 | Append 93 | 94 | Destination 95 | ~/edit_anywhere.txt 96 | Encoding 97 | UTF8 98 | Format 99 | PlainText 100 | IsActive 101 | 102 | IsDisclosed 103 | 104 | MacroActionType 105 | WriteFile 106 | Name 107 | 1109C933-5030-4E31-AA95-D42DCB9F5020 108 | RedundandDisplayName 109 | Default Clipboard 110 | Source 111 | Clipboard 112 | Text 113 | 114 | Variable 115 | Variable 116 | 117 | 118 | Action 119 | ByTyping 120 | IsActive 121 | 122 | IsDisclosed 123 | 124 | MacroActionType 125 | InsertText 126 | Paste 127 | 128 | Text 129 | (Waiting for EditAnywhere) 130 | 131 | 132 | ActionName 133 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 134 | IsActive 135 | 136 | IsDisclosed 137 | 138 | KeyCode 139 | 0 140 | MacroActionType 141 | SimulateKeystroke 142 | Modifiers 143 | 256 144 | ReleaseAll 145 | 146 | 147 | 148 | IsActive 149 | 150 | IsDisclosed 151 | 152 | MacroActionType 153 | Pause 154 | Time 155 | .5 156 | TimeOutAbortsMacro 157 | 158 | 159 | 160 | ActionName 161 | This is where the magic happens 162 | DisplayKind 163 | Window 164 | IncludeStdErr 165 | 166 | IsActive 167 | 168 | IsDisclosed 169 | 170 | MacroActionType 171 | ExecuteShellScript 172 | Path 173 | /usr/local/scripts/km-edit-anywhere-bbedit.sh 174 | Text 175 | #!/bin/zsh -f 176 | 177 | 178 | ## This is the app that you want to use as your external editor 179 | ## Note that it should not include the '.app' suffix 180 | ## 181 | ## Examples: 182 | ## APP='BBEdit' 183 | ## APP='TextWrangler' 184 | ## APP='MultiMarkdown Composer' 185 | ## 186 | APP='BBEdit' 187 | 188 | 189 | ###################################################################### 190 | ## This is the name of the temporary file which will be used to keep 191 | ## your edits before it is sent back to the app where it came from. 192 | ## 193 | ## If you change this, 194 | ## make sure you change all of the other references to this file 195 | ## in the Keyboard Maestro macro 196 | FILE="$HOME/edit_anywhere.txt" 197 | 198 | ## OS X no longer has a good way to ensure that GUI apps like 199 | ## Keyboard Maestro have access to your $PATH so I often just create 200 | ## a text file in my $HOME which I can use in all my scripts. This 201 | ## checks to see if that file exists, and if it does not exist, it 202 | ## will use the PATH as defined in the second half of the if/else 203 | 204 | if [[ -e "$HOME/.path" ]] 205 | then 206 | source "$HOME/.path" 207 | else 208 | PATH=/usr/local/scripts:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin 209 | fi 210 | 211 | 212 | 213 | 214 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|#### 215 | # 216 | # You should not ~need~ to edit anything below this line 217 | # 218 | 219 | 220 | 221 | NAME="[Edit Anywhere via Keyboard Maestro]" 222 | 223 | ## Change this if necessary 224 | ## Used for pbcopy 225 | LANG=en_US.UTF-8 226 | 227 | zmodload zsh/datetime ## needed for strftime 228 | 229 | function timestamp { strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS" } 230 | 231 | # This gives us a unique reference point for when the script was launched 232 | TIME=`strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS"` 233 | 234 | if [ -e '/usr/local/bin/growlnotify' -a "`pgrep -x Growl`" != "" ] 235 | then 236 | ## If growlnotify is installed AND Growl.app is running, use Growl for notifications 237 | 238 | function msg 239 | { 240 | growlnotify \ 241 | --appIcon "$APP" \ 242 | --identifier "$NAME" \ 243 | --message "$@" \ 244 | --title "$NAME" 245 | 246 | } ## end of msg/growl 247 | 248 | 249 | elif (( $+commands[terminal-notifier] )) 250 | then 251 | ## OTHERWISE, use terminal-notifier for notifications, if it is installed. 252 | 253 | function msg 254 | { 255 | if [[ -e "/Applications/$APP.app/Contents/Info.plist" ]] 256 | then 257 | ## If there is an app plist where we'd expect it to be, try to get the Bundle identifier from it 258 | 259 | TN_BUNDLE_ID=`defaults read /Applications/$APP.app/Contents/Info CFBundleIdentifier` 260 | fi 261 | 262 | ## If we were not able to get a bundle ID, use Keyboard Maestro's 263 | [[ "$TN_BUNDLE_ID" == "" ]] && TN_BUNDLE_ID='com.stairways.keyboardmaestro.editor' 264 | 265 | terminal-notifier \ 266 | -title "$NAME" \ 267 | -subtitle "`timestamp`" \ 268 | -group "$NAME" \ 269 | -sender "$TN_BUNDLE_ID" \ 270 | -activate "$TN_BUNDLE_ID" \ 271 | -message "$@" 272 | } ## end of msg/terminal-notifier 273 | 274 | else 275 | 276 | function msg { echo "$NAME: $@" | tee -a "${TMPDIR-/tmp/}${NAME}.$TIME.log" } 277 | 278 | fi 279 | 280 | 281 | ########################################################################################### 282 | ########################################################################################### 283 | ## 284 | ## Here is where the action begins 285 | ## 286 | 287 | if [[ "$KMVAR_EditAnywhereApp" == "" ]] 288 | then 289 | ## "$KMVAR_EditAnywhereApp" is not set. ABORT. 290 | 291 | msg "Variable KMVAR_EditAnywhereApp is empty. Giving up." 292 | 293 | ## Open the file in the default text editor 294 | ## so the user knows their text has not been lost 295 | /usr/bin/open -t "$FILE" 296 | 297 | exit 1 298 | 299 | else 300 | ## Tell the user what app we took text from 301 | ## This is mostly a debugging comment and could be removed if it annoys you 302 | msg "Will send text back to: $KMVAR_EditAnywhereApp" 303 | 304 | fi 305 | 306 | 307 | if [ "$APP:l" = "bbedit" -a -x /usr/local/bin/bbedit ] 308 | then 309 | ## IFF the user wants to use BBEdit and they have the bbedit 310 | ## command line tool installed, then we will use the bbedit tool 311 | 312 | ## if BBEdit is not running, launch it 313 | pgrep -xq BBEdit || (open -a BBEdit && sleep 3) 314 | 315 | ## We will try to open the app with the bbedit command, 316 | ## but if it fails we will open TextEdit 317 | /usr/local/bin/bbedit \ 318 | --language 'Markdown' \ 319 | --create-unix \ 320 | --new-window \ 321 | --resume \ 322 | --wait \ 323 | -- "$FILE" \ 324 | || open -a -n -e -W "$FILE" 325 | 326 | else 327 | ## if we get here, either the app is NOT BBEdit 328 | ## or they do not have the `bbedit` tool installed 329 | 330 | ## We will try to open the file in the requested app 331 | ## but if the open command fails for some reason, 332 | ## we will open TextEdit 333 | 334 | open -a -n -W "$APP" "$FILE" || open -a -n -e -W "$FILE" 335 | 336 | fi # if app is BBEdit 337 | 338 | 339 | EXIT="$?" 340 | 341 | if [ "$EXIT" != "0" ] 342 | then 343 | 344 | ## If we get here, something went wrong 345 | 346 | msg "Unable to open $FILE in $APP." 347 | 348 | ## Show the file in the Finder, so the user can try to do something with it 349 | /usr/bin/open -R "$FILE" 350 | 351 | exit 1 352 | fi 353 | 354 | ## If we get here, `open` or `bbedit` exited successfully 355 | 356 | 357 | ## Make sure that the app we want to paste into is actually running 358 | ## it *should* be, but it's possible that it either crashed or the 359 | ## user quit it in the interim, so let's check 360 | 361 | pgrep -xq "$KMVAR_EditAnywhereApp" 362 | 363 | EXIT="$?" 364 | 365 | if [ "$EXIT" = "1" ] 366 | then 367 | 368 | ## If we get here, the app is NOT running, so let's tell the user 369 | ## that we are launching it. 370 | 371 | msg "Launching $KMVAR_EditAnywhereApp so we can paste to it" 372 | 373 | 374 | ## Here is where we actually launch the app 375 | open -a "$KMVAR_EditAnywhereApp" 376 | 377 | ## now we need to give it a few seconds to get itself running 378 | ## This is guesswork, because we don't know how long it will 379 | ## take for the app to launch and be ready to accept input 380 | sleep 5 381 | fi 382 | 383 | ## Tell the user we are ready to paste information back to the source app 384 | msg "Pasting text to $KMVAR_EditAnywhereApp" 385 | 386 | ## Activate the app 387 | ## NOTE: originally this was not happening fast enough 388 | ## for it to be ready to accept a 'paste' 389 | ## when this script finished 390 | ## so I added some extra 'padding' 391 | ## and an extra 'open' call 392 | ## This should not harm anything. 393 | 394 | open -a "$KMVAR_EditAnywhereApp" 395 | 396 | ## wait a second 397 | sleep 1 398 | 399 | ## No no, REALLY activate the app 400 | open -a "$KMVAR_EditAnywhereApp" 401 | 402 | 403 | ## copy the file back to the pasteboard 404 | pbcopy < "$FILE" 405 | 406 | ## OK, now we are done with the FILE so we have to either leave it there, 407 | ## delete it, or move it to the trash. 408 | ## I don't want to leave it there when it has already been used, 409 | ## and I don't want to delete it in case something went wrong 410 | ## So I'm going to move it to the trash instead 411 | ## AND I'm going to rename the file with the current time stamp so if I 412 | ## happen to have several of these and need to recover one, 413 | ## I can do that, as long as I haven't emptied my trash 414 | 415 | ## This will be 'edit_anywhere' without the path or extension 416 | ## unless you changed $FILE 417 | SHORT="$FILE:t:r" 418 | 419 | ## This will be 'txt' unless you changed $FILE 420 | EXT="$FILE:e" 421 | 422 | /bin/mv -n "$FILE" "$HOME/.Trash/$SHORT.`timestamp`.$EXT" 423 | 424 | exit 0 425 | #EOF 426 | 427 | TimeOutAbortsMacro 428 | 429 | TimeOutPeriod 430 | 86400 431 | TrimResults 432 | 433 | TrimResultsNew 434 | 435 | UseText 436 | 437 | 438 | 439 | ActionName 440 | Paste contents of file back to "Source" app 441 | Conditions 442 | 443 | ConditionList 444 | 445 | 446 | ConditionType 447 | Menu 448 | MenuConditionSelectionType 449 | Is 450 | MenuConditionType 451 | IsEnabled 452 | MenuModifiers 453 | 256 454 | MenuShortcut 455 | C 456 | MenuTitle 457 | Paste 458 | 459 | 460 | ConditionListMatch 461 | All 462 | 463 | ElseActions 464 | 465 | 466 | IsActive 467 | 468 | IsDisclosed 469 | 470 | KeyCode 471 | 9 472 | MacroActionType 473 | SimulateKeystroke 474 | Modifiers 475 | 256 476 | ReleaseAll 477 | 478 | 479 | 480 | IsActive 481 | 482 | IsDisclosed 483 | 484 | MacroActionType 485 | IfThenElse 486 | ThenActions 487 | 488 | 489 | IsActive 490 | 491 | IsDisclosed 492 | 493 | MacroActionType 494 | SelectMenuItem 495 | Menu 496 | 497 | Edit 498 | Paste 499 | 500 | TargetingType 501 | Front 502 | 503 | 504 | TimeOutAbortsMacro 505 | 506 | 507 | 508 | CreationDate 509 | 459387347.72605699 510 | IsActive 511 | 512 | ModificationDate 513 | 460499322.459104 514 | Name 515 | Edit Anywhere 516 | Triggers 517 | 518 | 519 | FireType 520 | Pressed 521 | KeyCode 522 | 11 523 | MacroTriggerType 524 | HotKey 525 | Modifiers 526 | 6912 527 | 528 | 529 | UID 530 | 63DA32F6-8BA8-49AD-B4BC-C9AC7761D87E 531 | 532 | 533 | Name 534 | Global Macro Group 535 | ToggleMacroUID 536 | 4948A9C1-5CD3-4AA1-A25D-9D29C5471ED8 537 | UID 538 | DA8512F7-F323-46B1-8319-752E0495CFD0 539 | 540 | 541 | 542 | -------------------------------------------------------------------------------- /images/Edit Anywhere.kmmacros: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Activate 7 | Normal 8 | CreationDate 9 | 459387347.72605699 10 | IsActive 11 | 12 | Macros 13 | 14 | 15 | Actions 16 | 17 | 18 | ActionName 19 | Store to the name of the active application to the variable ‘EditAnywhereApp’ 20 | IsActive 21 | 22 | IsDisclosed 23 | 24 | MacroActionType 25 | SetVariableToText 26 | Text 27 | %Application%1% 28 | Variable 29 | EditAnywhereApp 30 | 31 | 32 | ActionName 33 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 34 | IsActive 35 | 36 | IsDisclosed 37 | 38 | KeyCode 39 | 0 40 | MacroActionType 41 | SimulateKeystroke 42 | Modifiers 43 | 256 44 | ReleaseAll 45 | 46 | 47 | 48 | ActionName 49 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 50 | IsActive 51 | 52 | IsDisclosed 53 | 54 | KeyCode 55 | 0 56 | MacroActionType 57 | SimulateKeystroke 58 | Modifiers 59 | 256 60 | ReleaseAll 61 | 62 | 63 | 64 | IsActive 65 | 66 | IsDisclosed 67 | 68 | MacroActionType 69 | Pause 70 | Time 71 | 1 72 | TimeOutAbortsMacro 73 | 74 | 75 | 76 | IsActive 77 | 78 | IsDisclosed 79 | 80 | KeyCode 81 | 7 82 | MacroActionType 83 | SimulateKeystroke 84 | Modifiers 85 | 256 86 | ReleaseAll 87 | 88 | 89 | 90 | ActionName 91 | Save clipboard info to ~/edit_anywhere.txt 92 | Append 93 | 94 | Destination 95 | ~/edit_anywhere.txt 96 | Encoding 97 | UTF8 98 | Format 99 | PlainText 100 | IsActive 101 | 102 | IsDisclosed 103 | 104 | MacroActionType 105 | WriteFile 106 | Name 107 | 1109C933-5030-4E31-AA95-D42DCB9F5020 108 | RedundandDisplayName 109 | Default Clipboard 110 | Source 111 | Clipboard 112 | Text 113 | 114 | Variable 115 | Variable 116 | 117 | 118 | Action 119 | ByTyping 120 | IsActive 121 | 122 | IsDisclosed 123 | 124 | MacroActionType 125 | InsertText 126 | Paste 127 | 128 | Text 129 | (Waiting for EditAnywhere) 130 | 131 | 132 | ActionName 133 | Type the ⌘A Keystroke (This should trigger 'Select All Text') 134 | IsActive 135 | 136 | IsDisclosed 137 | 138 | KeyCode 139 | 0 140 | MacroActionType 141 | SimulateKeystroke 142 | Modifiers 143 | 256 144 | ReleaseAll 145 | 146 | 147 | 148 | IsActive 149 | 150 | IsDisclosed 151 | 152 | MacroActionType 153 | Pause 154 | Time 155 | .5 156 | TimeOutAbortsMacro 157 | 158 | 159 | 160 | ActionName 161 | This is where the magic happens 162 | DisplayKind 163 | Window 164 | IncludeStdErr 165 | 166 | IsActive 167 | 168 | IsDisclosed 169 | 170 | MacroActionType 171 | ExecuteShellScript 172 | Path 173 | /usr/local/scripts/km-edit-anywhere-bbedit.sh 174 | Text 175 | #!/bin/zsh -f 176 | 177 | 178 | ## This is the app that you want to use as your external editor 179 | ## Note that it should not include the '.app' suffix 180 | ## 181 | ## Examples: 182 | ## APP='BBEdit' 183 | ## APP='TextWrangler' 184 | ## APP='MultiMarkdown Composer' 185 | ## 186 | APP='BBEdit' 187 | 188 | 189 | ###################################################################### 190 | ## This is the name of the temporary file which will be used to keep 191 | ## your edits before it is sent back to the app where it came from. 192 | ## 193 | ## If you change this, 194 | ## make sure you change all of the other references to this file 195 | ## in the Keyboard Maestro macro 196 | FILE="$HOME/edit_anywhere.txt" 197 | 198 | ## OS X no longer has a good way to ensure that GUI apps like 199 | ## Keyboard Maestro have access to your $PATH so I often just create 200 | ## a text file in my $HOME which I can use in all my scripts. This 201 | ## checks to see if that file exists, and if it does not exist, it 202 | ## will use the PATH as defined in the second half of the if/else 203 | 204 | if [[ -e "$HOME/.path" ]] 205 | then 206 | source "$HOME/.path" 207 | else 208 | PATH=/usr/local/scripts:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin 209 | fi 210 | 211 | 212 | 213 | 214 | ####|####|####|####|####|####|####|####|####|####|####|####|####|####|#### 215 | # 216 | # You should not ~need~ to edit anything below this line 217 | # 218 | 219 | 220 | 221 | NAME="[Edit Anywhere via Keyboard Maestro]" 222 | 223 | ## Change this if necessary 224 | ## Used for pbcopy 225 | LANG=en_US.UTF-8 226 | 227 | zmodload zsh/datetime ## needed for strftime 228 | 229 | function timestamp { strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS" } 230 | 231 | # This gives us a unique reference point for when the script was launched 232 | TIME=`strftime "%Y-%m-%d--%H.%M.%S" "$EPOCHSECONDS"` 233 | 234 | if [ -e '/usr/local/bin/growlnotify' -a "`pgrep -x Growl`" != "" ] 235 | then 236 | ## If growlnotify is installed AND Growl.app is running, use Growl for notifications 237 | 238 | function msg 239 | { 240 | growlnotify \ 241 | --appIcon "$APP" \ 242 | --identifier "$NAME" \ 243 | --message "$@" \ 244 | --title "$NAME" 245 | 246 | } ## end of msg/growl 247 | 248 | 249 | elif (( $+commands[terminal-notifier] )) 250 | then 251 | ## OTHERWISE, use terminal-notifier for notifications, if it is installed. 252 | 253 | function msg 254 | { 255 | if [[ -e "/Applications/$APP.app/Contents/Info.plist" ]] 256 | then 257 | ## If there is an app plist where we'd expect it to be, try to get the Bundle identifier from it 258 | 259 | TN_BUNDLE_ID=`defaults read /Applications/$APP.app/Contents/Info CFBundleIdentifier` 260 | fi 261 | 262 | ## If we were not able to get a bundle ID, use Keyboard Maestro's 263 | [[ "$TN_BUNDLE_ID" == "" ]] && TN_BUNDLE_ID='com.stairways.keyboardmaestro.editor' 264 | 265 | terminal-notifier \ 266 | -title "$NAME" \ 267 | -subtitle "`timestamp`" \ 268 | -group "$NAME" \ 269 | -sender "$TN_BUNDLE_ID" \ 270 | -activate "$TN_BUNDLE_ID" \ 271 | -message "$@" 272 | } ## end of msg/terminal-notifier 273 | 274 | else 275 | 276 | function msg { echo "$NAME: $@" | tee -a "${TMPDIR-/tmp/}${NAME}.$TIME.log" } 277 | 278 | fi 279 | 280 | 281 | ########################################################################################### 282 | ########################################################################################### 283 | ## 284 | ## Here is where the action begins 285 | ## 286 | 287 | if [[ "$KMVAR_EditAnywhereApp" == "" ]] 288 | then 289 | ## "$KMVAR_EditAnywhereApp" is not set. ABORT. 290 | 291 | msg "Variable KMVAR_EditAnywhereApp is empty. Giving up." 292 | 293 | ## Open the file in the default text editor 294 | ## so the user knows their text has not been lost 295 | /usr/bin/open -t "$FILE" 296 | 297 | exit 1 298 | 299 | else 300 | ## Tell the user what app we took text from 301 | ## This is mostly a debugging comment and could be removed if it annoys you 302 | msg "Will send text back to: $KMVAR_EditAnywhereApp" 303 | 304 | fi 305 | 306 | 307 | if [ "$APP:l" = "bbedit" -a -x /usr/local/bin/bbedit ] 308 | then 309 | ## IFF the user wants to use BBEdit and they have the bbedit 310 | ## command line tool installed, then we will use the bbedit tool 311 | 312 | ## if BBEdit is not running, launch it 313 | pgrep -xq BBEdit || (open -a BBEdit && sleep 3) 314 | 315 | ## We will try to open the app with the bbedit command, 316 | ## but if it fails we will open TextEdit 317 | /usr/local/bin/bbedit \ 318 | --language 'Markdown' \ 319 | --create-unix \ 320 | --new-window \ 321 | --resume \ 322 | --wait \ 323 | -- "$FILE" \ 324 | || open -a -n -e -W "$FILE" 325 | 326 | else 327 | ## if we get here, either the app is NOT BBEdit 328 | ## or they do not have the `bbedit` tool installed 329 | 330 | ## We will try to open the file in the requested app 331 | ## but if the open command fails for some reason, 332 | ## we will open TextEdit 333 | 334 | open -a -n -W "$APP" "$FILE" || open -a -n -e -W "$FILE" 335 | 336 | fi # if app is BBEdit 337 | 338 | 339 | EXIT="$?" 340 | 341 | if [ "$EXIT" != "0" ] 342 | then 343 | 344 | ## If we get here, something went wrong 345 | 346 | msg "Unable to open $FILE in $APP." 347 | 348 | ## Show the file in the Finder, so the user can try to do something with it 349 | /usr/bin/open -R "$FILE" 350 | 351 | exit 1 352 | fi 353 | 354 | ## If we get here, `open` or `bbedit` exited successfully 355 | 356 | 357 | ## Make sure that the app we want to paste into is actually running 358 | ## it *should* be, but it's possible that it either crashed or the 359 | ## user quit it in the interim, so let's check 360 | 361 | pgrep -xq "$KMVAR_EditAnywhereApp" 362 | 363 | EXIT="$?" 364 | 365 | if [ "$EXIT" = "1" ] 366 | then 367 | 368 | ## If we get here, the app is NOT running, so let's tell the user 369 | ## that we are launching it. 370 | 371 | msg "Launching $KMVAR_EditAnywhereApp so we can paste to it" 372 | 373 | 374 | ## Here is where we actually launch the app 375 | open -a "$KMVAR_EditAnywhereApp" 376 | 377 | ## now we need to give it a few seconds to get itself running 378 | ## This is guesswork, because we don't know how long it will 379 | ## take for the app to launch and be ready to accept input 380 | sleep 5 381 | fi 382 | 383 | ## Tell the user we are ready to paste information back to the source app 384 | msg "Pasting text to $KMVAR_EditAnywhereApp" 385 | 386 | ## Activate the app 387 | ## NOTE: originally this was not happening fast enough 388 | ## for it to be ready to accept a 'paste' 389 | ## when this script finished 390 | ## so I added some extra 'padding' 391 | ## and an extra 'open' call 392 | ## This should not harm anything. 393 | 394 | open -a "$KMVAR_EditAnywhereApp" 395 | 396 | ## wait a second 397 | sleep 1 398 | 399 | ## No no, REALLY activate the app 400 | open -a "$KMVAR_EditAnywhereApp" 401 | 402 | 403 | ## copy the file back to the pasteboard 404 | pbcopy < "$FILE" 405 | 406 | ## OK, now we are done with the FILE so we have to either leave it there, 407 | ## delete it, or move it to the trash. 408 | ## I don't want to leave it there when it has already been used, 409 | ## and I don't want to delete it in case something went wrong 410 | ## So I'm going to move it to the trash instead 411 | ## AND I'm going to rename the file with the current time stamp so if I 412 | ## happen to have several of these and need to recover one, 413 | ## I can do that, as long as I haven't emptied my trash 414 | 415 | ## This will be 'edit_anywhere' without the path or extension 416 | ## unless you changed $FILE 417 | SHORT="$FILE:t:r" 418 | 419 | ## This will be 'txt' unless you changed $FILE 420 | EXT="$FILE:e" 421 | 422 | /bin/mv -n "$FILE" "$HOME/.Trash/$SHORT.`timestamp`.$EXT" 423 | 424 | exit 0 425 | #EOF 426 | 427 | TimeOutAbortsMacro 428 | 429 | TimeOutPeriod 430 | 86400 431 | TrimResults 432 | 433 | TrimResultsNew 434 | 435 | UseText 436 | 437 | 438 | 439 | ActionName 440 | Paste contents of file back to "Source" app 441 | Conditions 442 | 443 | ConditionList 444 | 445 | 446 | ConditionType 447 | Menu 448 | MenuConditionSelectionType 449 | Is 450 | MenuConditionType 451 | IsEnabled 452 | MenuModifiers 453 | 256 454 | MenuShortcut 455 | C 456 | MenuTitle 457 | Paste 458 | 459 | 460 | ConditionListMatch 461 | All 462 | 463 | ElseActions 464 | 465 | 466 | IsActive 467 | 468 | IsDisclosed 469 | 470 | KeyCode 471 | 9 472 | MacroActionType 473 | SimulateKeystroke 474 | Modifiers 475 | 256 476 | ReleaseAll 477 | 478 | 479 | 480 | IsActive 481 | 482 | IsDisclosed 483 | 484 | MacroActionType 485 | IfThenElse 486 | ThenActions 487 | 488 | 489 | IsActive 490 | 491 | IsDisclosed 492 | 493 | MacroActionType 494 | SelectMenuItem 495 | Menu 496 | 497 | Edit 498 | Paste 499 | 500 | TargetingType 501 | Front 502 | 503 | 504 | TimeOutAbortsMacro 505 | 506 | 507 | 508 | CreationDate 509 | 459387347.72605699 510 | IsActive 511 | 512 | ModificationDate 513 | 460499322.459104 514 | Name 515 | Edit Anywhere 516 | Triggers 517 | 518 | 519 | FireType 520 | Pressed 521 | KeyCode 522 | 11 523 | MacroTriggerType 524 | HotKey 525 | Modifiers 526 | 6912 527 | 528 | 529 | UID 530 | 63DA32F6-8BA8-49AD-B4BC-C9AC7761D87E 531 | 532 | 533 | Name 534 | Global Macro Group 535 | ToggleMacroUID 536 | 4948A9C1-5CD3-4AA1-A25D-9D29C5471ED8 537 | UID 538 | DA8512F7-F323-46B1-8319-752E0495CFD0 539 | 540 | 541 | 542 | -------------------------------------------------------------------------------- /images/define-your-editor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjluoma/edit-anywhere/b8b91cd7e59b2b02f55fdb16f45784a81898cba4/images/define-your-editor.jpg --------------------------------------------------------------------------------