Auto-Save “Untitled” Script Debugger Tabs

In Script Debugger I often create new “Untitled” tabs just to test some lines of code. After a couple of hours I end up with 1 or 2 “real” tabs (the actual script) and a dozen of “Untitled” tabs.

This can get annoying when I quit SD, because it doesn’t keep the “Untitled” tabs for the next session, instead it asks me to save each one individually with a proper name.

Since these “Untitled” tabs are just temporary documents, I’m not interested in saving each one “properly”. However, if the project isn’t finished yet, I do want to keep them for the next session.


Here’s where the macro comes in:

The macro scans SD’s open documents for “untitled” documents. If it finds one it saves it as text script in a predefined location (i.e. your folder for temporary scripts). File name will be the current time stamp (Apple Reference Time), so it is assured that each “Untitled” gets a different name.

Next time when I open SD, these files will be auto-opened (assuming the SD preferences are set accordingly).


It comes with three triggers:

  • When SD activates:

    • All “Untitled” tabs are saved.
  • Hotkey ⌃⌥⌘S:

    • All “Untitled” tabs are saved.
    • Selects Save All from SD’s File menu.
  • Hotkey ⌘Q:

    • All “Untitled” tabs are saved.
    • Quits SD.
    • Sans the temporary folder and trashes previously saved temporary scripts that are older than 1 week (last used date).[1]

[1] In the downloadable macro purging is disabled by default. Before enabling it make sure that your temporary folder doesn’t contain any other files that might match the naming scheme, or change the naming scheme to your needs.

To use the macro you have to set the path to your preferred temporary scripts location. (Drag the desired folder into the text field of the green action.)

Save “Untitled” SD Tabs.kmmacros (11.5 KB)


Edit (2016-10-16 01:20 Z):

Here is an additional Launcher Macro:

Save “Untitled” SD Tabs (Additional Launcher).kmmacros (3.3 KB)

This launcher macro just provides a “Deactivates” trigger for the main macro.

  • The launcher macro must be in the Global Macro Group.
  • The main macro (‘Save “Untitled” SD Tabs’) must be in the Script Debugger macro group.

If you use this launcher macro you should remove the “Activates” trigger from the main macro.

Make sure that the link to the main macro (Execute macro: Save “Untitled” SD Tabs) is valid on your computer!
If it doesn’t work reselect the main macro from the Execute macro drop-down menu.


Update (2016-10-17 13:24 Z):

I added a If Script Debugger is running condition to the launcher macro. Otherwise it would relaunch SD immediately after quitting. (Due to the AppleScript test in the main macro.)

2 Likes

@Tom, this looks like a very useful macro. Thanks for creating and sharing.

Can you please clarify what is meant by All “Untitled” tabs are saved for each of the triggers?

  • Are all of these saved to the temp text files, OR, do any of them actually save as .scpt files? The second HotKey, ⌃⌥⌘S, looks like to might save as .scpt files.

Also, how are the temp text files restored?
Shouldn't that be part of the first trigger, "When SD activates"?

Thanks.

Well that’s the point of the macro. See the description.

Example: Open some new tabs (they will be named “Untitled”, “Untitled 2”, etc.) → Trigger the macro → They will get saved as <timestamp>.applescript

Are all of these saved to the temp text files, OR, do any of them actually save as .scpt files?

As text scripts (i.e. .applescript). You can change this in the AS action, if you prefer .scpt:

Change save theDoc as text script to save theDoc as compiled script and change the extension from .applescript to .scpt.

⌃⌥⌘S, looks like to might save as .scpt files.

No, this does the same. It’s just a combination of macro trigger and hotkey for SD’s Save All. I have added it because when I do a Save All I also want any “Untitled” tabs to get named and saved without prompt.

If you already have a different hotkey for SD’s Save All, then change it to your hotkey. (Change also the 2nd switch, so that the hotkey is passed through to SD.)

Also, how are the temp text files restored?
Shouldn't that be part of the first trigger, "When SD activates"?

SD > Preferences > General > Remember open scripts

No, the Activates trigger just ensures that new “Untitled” tabs are named and saved when coming back to SD. (Activate ≠ Launch.)

Initially the trigger was a Deactivates trigger, but then I had to move the macro to the SD-specific macro group (= only enabled when SD at front) because of the ⌃⌥⌘S and ⌘Q triggers. (Deactivates triggers don’t work in an application-specific macro group.)

But as long as you use ⌘Q to quit SD, the Activates trigger isn’t strictly necessary, so you can also scrap it, if you prefer.

You could also add a launcher macro (which launches the original macro) to the Global Macro Group and provide it with a Deactivates trigger.

Edit (2016-10-16 01:34 Z): I added a launcher macro with a Deactivates trigger to the original post.

Hey Guys,

I’ve done this sort of thing a variety of ways over the last couple of decades.

Here’s my latest save-session script:

--------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2014/03/08 03:02
# dMod: 2016/06/19 19:02
# Appl: Script Debugger
# Task: Save Script Debugger Session:
#       Save sym-links to open script files & unsaved script source to saved-sessions folder.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Script_Debugger, @Save, @Session
# Vers: 1.2.1
--------------------------------------------------------------------------------

try
   
   set saveLoc to "~/Documents/Code_Projects/Script_Debugger/Saved-Sessions/"
   set svFldrBaseName to "sd-saved-session-"
   
   set AppleScript's text item delimiters to linefeed
   tell application "Script Debugger"
      tell (documents whose path contains "/") to set {fileList, nameList} to {text items of (file spec as text), name}
      tell (documents whose path does not contain "/" and source text ≠ "") to set unSavedSrc to source text
   end tell
   
   set newSvFldr to expandTilde(saveLoc) & svFldrBaseName & dateStamp()
   
   if fileList ≠ {} or unSavedSrc ≠ {} then
      
      repeat with i from 1 to length of fileList
         tell (a reference to item i of fileList)
            set its contents to "ln -s " & my qf((POSIX path of (its contents))) & " " & (my qf(item i of nameList)) & ";"
         end tell
      end repeat
      
      set beginning of fileList to "cd \"$DIR\";"
      set beginning of fileList to "mkdir -p \"$DIR\";"
      set beginning of fileList to "DIR=" & qf(newSvFldr) & ";"
      set _cmd to fileList as text
      
      do shell script _cmd
      
      set _cntr to 0
      repeat with _src in unSavedSrc
         if (contents of _src) ≠ "" then
            set _cntr to _cntr + 1
            writeUTF8(_src, (newSvFldr & "/Unsaved-Script-Source-" & zPad(_cntr) & ".applescript.txt"))
         end if
      end repeat
   else
      error "Nothing is available to save!"
   end if
   
   set newSvFldr to alias POSIX file newSvFldr
   tell application "Finder"
      update newSvFldr's parent
      delay 0.05
      reveal newSvFldr
   end tell
   
on error e number n
   stdErr(e, n, true, true) of me
end try

--------------------------------------------------------------------------------
--» HANDLERS
--------------------------------------------------------------------------------
on dateStamp()
   tell (current date) to (((its year) * 10000 + (its month) * 100 + (its day)) as text) & text 2 thru -1 of ((1000000 + (its hours) * 10000 + (its minutes) * 100 + (its seconds)) as text)
   tell result to (text 1 thru 4) & "." & (text 5 thru 6) & "." & (text 7 thru 8) & "-" & (text 9 thru 10) & "." & (text 11 thru 12) & "." & (text 13 thru 14)
end dateStamp
--------------------------------------------------------------------------------
on zPad(_num)
   text 2 thru -1 of ((_num + 100) as text)
end zPad
--------------------------------------------------------------------------------
on stdErr(e, n, beepFlag, ddFlag)
   set e to e & return & return & "Num: " & n
   if beepFlag = true then
      beep
   end if
   if ddFlag = true then
      tell me
         set dDlg to display dialog e with title "ERROR!" buttons {"Cancel", "Copy", "OK"} default button "OK"
      end tell
      if button returned of dDlg = "Copy" then set the clipboard to e
   else
      return e
   end if
end stdErr
--------------------------------------------------------------------------------
on expandTilde(_path)
   if _path is "~" or _path is "~/" then
      set _path to POSIX path of (path to home folder as text)
   else if _path starts with "~/" then
      set _path to (POSIX path of (path to home folder as text)) & text 3 thru -1 of _path
   else
      error "Bad path string!"
   end if
end expandTilde
--------------------------------------------------------------------------------
on qf(_text)
   return (quoted form of _text)
end qf
--------------------------------------------------------------------------------
on writeUTF8(_text, targetFilePath)
   try
      if targetFilePath starts with "~/" then
         set targetFilePath to POSIX path of (path to home folder as text) & text 3 thru -1 of targetFilePath
      end if
      set fRef to open for access targetFilePath with write permission
      set eof of fRef to 0
      write _text to fRef as «class utf8»
      close access fRef
   on error e number n
      try
         close access fRef
      on error e number n
         error "Error in writeUTF8() handler of library: gen.lib" & return & return & e
      end try
   end try
end writeUTF8
--------------------------------------------------------------------------------

This script saves a symlink to any saved files and the source-text of any unsaved files to a date-stamped “sd-saved-session-” folder.

Then I use a script to close unsaved documents without saving:

--------------------------------------------------------------------------------
tell application "Script Debugger"
   tell (documents whose path does not contain "/") to close without saving
end tell
--------------------------------------------------------------------------------

I will go back to using aliases instead of symlinks at some point in the near future, because symlinks are not found by Spotlight.

This is annoying, because creating symlinks is very much faster than creating aliases.

Probably by using the file manager with AppleScriptObjC I can get the aliases made fast enough that the time lag doesn’t bother me, but I’ll cross that bridge when I come to it.

-Chris

Chris, thanks for posting your script. Your approach is rather different.

Main purpose of my macro is to reproduce the behavior of Script Editor and many other programs:

It allows me to quit SD without having to go through the save dialog for each and every “Untitled” tab/window – and to have them auto-restored when I relaunch SD.

Your script saves a versioned history of the content of every “Untitled” tab. This is a handy thing on its own, but it doesn’t help me to get these tabs auto-restored when I have to relaunch SD. I still have to name/save each “Untitled” tab individually. (Unless I use your second script to close these tabs without saving, but then, of course, they won’t be auto-restored.)

In short, two different use-cases:

  • My macro: If…

    • you like to have all tabs auto-restored when relaunching SD, and/or
    • you like to be able to make use of SD’s Save All command.
  • Your script(s): If…

    • you want to keep a versioned history of your “Untitled” tabs, and
      • you don’t mind to name/save them individually when quitting SD, or
      • you prefer to get rid of them when relaunching SD.

PS:

One can also combine my macro with Chris’ scripts:

  1. Enable my macro but remove all triggers, except the ⌘Q trigger.
  2. Start working on your project.
  3. Once you have “Untitled” tabs, launch Chris’ script from time to time (so their contents will be exported).
  4. When it comes to quit SD you have two options:
    • Press ⌘Q: all “Untitled” tabs are quick-saved and will be auto-restored at relaunch.
    • Launch Chris’ “close unsaved documents without saving” script and press ⌘Q: all “Untitled” tabs are dismissed and will not be restored.

Hi @Tom. Thanks for creating and sharing this macro; it very creatively overcomes a significant annoyance with Script Debugger. :clap::clap: (I'm surprised SD doesn't handle untitled files like TextEdit.)

1 Like