BBEditLib (AppleScript)

February 4 2003

-----------------------------------------------------------------------------------------------------------------
--
BBEditLib  @Emmanuel M. Décarie: emm@scriptdigital.com - http://scriptdigital.com/divers/bbeditlib.html
--
Version 1.0.3 / February 4 2003
--
This is a library that provide subroutines to deal with BBEdit from AppleScript.
--
Subroutines that start with '_' are considered reserved to the lib and should not be called directly.
--
For now the lib deal only with the disk browser window.
--
---------------------------------------------------------------------------------------------------------------

script generalmessages
   
property askBrowserName : "Disk Browser Window Name?"
   
property askFileName : "File name?"
   
property askFolderName : "Folder name?"
end script

script errormessages
   
   
property parent : generalmessages
   
   
property notDiskBrowserWindow : "Sorry this is not a disk browser window."
   
property noFilesSelected : "Sorry, can't get selected file(s) in the disk browser window."
   
property noWindowsOpen : "Sorry, there is no disk browser window open."
   
property selectOneFile : "Sorry, there is more than one file selected."
   
property tooManyFilesSelected : "Sorry, there is too many  files selected."
   
property methodNotSupported : "Sorry, this method is not presently supported."
   
property finderCantMoveSelToTrash : "One or more files in the selection can't be move to the trash. If the file or files are not folder(s), I can try harder but the problematic file(s) will be completely deleted!"
   
property cantDeleteFile : "Can't delete selection because: "
   
property cantDuplicateFile : "Can't duplicate file because: "
   
property finderCantGetContainerOfSel : "The Finder can't get the parent folder of the selection because: "
   
property fileExists : "Sorry, the selected file already exists."
   
property errorArgs : "Sorry, but there is a problem with the arguments given to the method because: "
   
property cantCreateFile : "Can't create file because: "
   
property cantRevealFile : "Can't reveal file because: "
   
property cantRenameFile : "Can't rename file because: "
   
property notTextWindow : "Sorry, this is not a text window."
   
property generalerror : "Sorry, can't run the script because: "
   
property needAContainer : "Sorry, mismatch arguments, you gave an alias to a file when I need an alias to a container."
   
property finderCantGetSelectedFile : "Sorry, the Finder can't get the selected file or folder because: "
   
end script


--
--------------------------------------------------------------------------------
--
Testing...
--
--------------------------------------------------------------------------------

--
tell diskBrowserWindow to set sel to getSelection({warning:true, maxSelection:1})
--
tell dialog to input(generalmessages's askBrowserName, "default string")


--
--------------------------------------------------------------------------------
--
dialog class
--
--------------------------------------------------------------------------------
script dialog
   
   
property parent : errormessages
   
   
on displayError(errormsg)
      display dialog errormsg with icon 0 buttons "OK" default button 1
      
return true
   
end displayError
   
   
on displayErrorWithCancel(errormsg)
      
try
         
return display dialog errormsg with icon 0 buttons {"Cancel", "OK"} default button 2
      
on error number -128 -- userCanceledErr
         
return false
      
end try
   
end displayErrorWithCancel
   
   
on input(inputMsg, defaultInput)
      
try
         
return display dialog inputMsg default answer defaultInput with icon 1 buttons {"Cancel", "OK"} default button 2
      
on error number -128 -- userCanceledErr
         
return false
      
end try
   
end input
   
end script

--
--------------------------------------------------------------------------------
--
unixpath class
--
--------------------------------------------------------------------------------
script unixpath
   
   --
--------------------------------------------------------------------------------
   --
unixpath method:
   --
      Get the posix path (unix path).
   --
      Doesn't handle accented characters. I'm open to suggestions that are not based on shell wildcards (too dangerous when deleting file(s)).
   --
--------------------------------------------------------------------------------
   --
argument:
   --
      macpath: an alias or path string
   --
return:
   --
      posix path string
   --
--------------------------------------------------------------------------------
   
on getPath(macpath)
      
set unixpath to POSIX path of macpath
      
set unixpathlist to every character of unixpath
      
repeat with i from 1 to length of unixpathlist
         --
took badchars list from http://www.macosxhints.com/article.php?story=20011217040113759
         
set badchars to {" ", "'", "!", "$", "\"", "*", "(", ")", "{", "[", "|", ";", "<", ">", "?", "~", "`", "\\"}
         
set thisItem to item i of unixpathlist as text
         
if thisItem is in badchars then set item i of unixpathlist to ("\\" & thisItem)
      
end repeat
      
set unixpath to unixpathlist as string
      
return unixpath
   
end getPath
   
end script


--
--------------------------------------------------------------------------------
--
disk browser window class
--
--------------------------------------------------------------------------------
script diskBrowserWindow
   
   
property parent : dialog
   
   --
--------------------------------------------------------------------------------
   --
getSelection method:
   --
      Get the selection in the files pane of the disk browser window and enforce that!
   --
      Pass an empty list if there is no arguments: getSelection ({})
   --
--------------------------------------------------------------------------------
   --
  argsRecord:
   --
      {[warning:false, maxSelection:number]}
   --
default args:
   --
      warning default to true if missing,
   --
      maxSelection default to no limits if missing
   --
return:
   --
      - A list of alias
   --
--------------------------------------------------------------------------------
   
on getSelection(argsRecord)
      
      --
set warning to true if missing
      
try
         
set warning to warning of argsRecord
      
on error
         
set warning to true
      
end try
      
      
set returnedArgs to _detectSelection(argsRecord)
      
set allTestsOK to allTestsOK of returnedArgs
      
      
if allTestsOK = false then
         
if warning = true then displayError(errormsg of returnedArgs)
         
return false
      
else
         
return sellist of returnedArgs
      
end if
   
end getSelection
   
   
   --
--------------------------------------------------------------------------------
   --
deleteFile method:
   --
      Move to trash the selected file(s) and folder(s).
   --
      If a file like '.DS_Store' can't be deleted by the Finder, try the unix shell with 'rm sel' (and no, it will never use 'rm -rf sel').
   --
      In the latter case, the file will be completly deleted.
   --
--------------------------------------------------------------------------------
   --
  argsRecord:
   --
      {thisSelection: selection, [warning: false, tryHarder: false]}
   --
default args:
   --
      warning default to true if missing,
   --
      tryHarder default to true if missing (will use the unix shell with 'rm sel').
   --
return:
   --
      - A record => {deletedSel:list of alias, deletedTryHarder:list of unix paths string}
   --
      - If there is an error, deletedSel or/and deletedTryHarder lists can be empty.
   --
      - false if the user cancelled the dialog.
   --
--------------------------------------------------------------------------------
   
on deleteFile(argsRecord)
      
      --
set warning to true if missing
      
try
         
set warning to warning of argsRecord
      
on error
         
set warning to true
      
end try
      
      --
required:  args: thisSelection
      
try
         
set sel to thisSelection of argsRecord
      
on error thisError
         
if warning = true then tell dialog to displayError(errormessages's errorArgs & thisError)
         
return false
      
end try
      
      --
optional tryHarder, if missing, default to true
      
try
         
set tryHarder to tryHarder of argsRecord
      
on error
         
set tryHarder to true
      
end try
      
      
set tryHarderToDelete to false
      
set tryHarderSel to {}
      
set deletedSelList to {}
      
set deletedTryHarderList to {}
      
      
try
         
tell application "Finder"
            
repeat with thisfile in sel
               
set filename to name of thisfile
               
try
                  move thisfile to trash
                  
set end of deletedSelList to contents of thisfile
               
on error thisError
                  --
display dialog thisError
                  
set tryHarderToDelete to true
                  
set end of tryHarderSel to contents of thisfile
               
end try
            
end repeat
         
end tell
         
         
if (tryHarder = true and tryHarderToDelete = true and tryHarderSel is not {}) then
            
tell application "BBEdit"
               
if warning = true then tell dialog to set answer to (displayErrorWithCancel(errormessages's finderCantMoveSelToTrash))
               
if answer = false then return false -- the user cancelled the dialog, abort
               
if button returned of answer is "OK" then
                  
set thisfile to ""
                  
repeat with thisfile in tryHarderSel
                     
try
                        
tell unixpath to set unixFilePath to getPath(thisfile)
                        
set cmd to "/bin/rm " & unixFilePath
                        do shell script cmd
                        
set end of deletedTryHarderList to unixpath
                     
on error thisError
                        
if warning = true then tell dialog to displayError(errormessages's cantDeleteFile & thisError)
                     
end try
                  
end repeat
               
end if
            
end tell
         
end if
         
         
return {deletedSel:deletedSelList, deletedTryHarder:deletedTryHarderList}
         
      
on error thisError
         
if warning = true then tell dialog to displayError(errormessages's cantDeleteFile & thisError)
         
return {deletedSel:deletedSelList, deletedTryHarder:deletedTryHarderList}
      
end try
      
   
end deleteFile
   
   
   --
--------------------------------------------------------------------------------
   --
duplicateFile method:
   --
      Duplicate the selection.
   --
--------------------------------------------------------------------------------
   --
  argsRecord:
   --
      {thisSelection: selection, [warning: false]}
   --
default args:
   --
      warning default to true if missing,
   --
return:
   --
      - A list of alias of duplicate file(s)
   --
      - false if there is an error.
   --
--------------------------------------------------------------------------------
   
on duplicateFile(argsRecord)
      
      --
set warning to true if missing
      
try
         
set warning to warning of argsRecord
      
on error
         
set warning to true
      
end try
      
      --
required:  args: thisSelection
      
try
         
set sel to thisSelection of argsRecord
      
on error thisError
         
if warning = true then tell dialog to displayError(errormessages's errorArgs & thisError)
         
return false
      
end try
      
      
set duplist to {}
      
set sel_lt to count of sel
      
repeat with i from 1 to sel_lt
         
try
            
tell application "Finder" to set FH to duplicate contents of item i of sel
            
set end of duplist to FH as alias
         
on error thisError
            
if warning = true then tell dialog to displayError(errormessages's cantDuplicateFile & thisError)
            
return false
         
end try
      
end repeat
      
      
return duplist
      
   
end duplicateFile
   
   
   --
--------------------------------------------------------------------------------
   --
nameBrowser method:
   --
      Name the name of frontmost disk browser window to whatever you want. The suggested name default to the name of the enclosing folder.
   --
      You can select in BBEdit one file or one folder to change the name of the disk browser window.
   --
      You can also create a new disk browser window if openBrowser is set to true
   --
      It will create only one disk browser if you use it from the Finder (see the script Open in BBEdit's Browser).
   --
--------------------------------------------------------------------------------
   --
  argsRecord:
   --
      {thisSelection: oneSelection, [warning: false, browserName: argString, inputMsg: argString, defautlInput: argString, defautlInputToContainerName: false, openBrowser: false, getParentContainer: false]}
   --
default args:
   --
      warning default to true if missing.
   --
      browserName default to false if missing, if set to true or a string, inputMsg and defaultInput will be disgarded, this bypass the dialog for asking the new name.
   --
         If  is set to true, this will set the disk browserName to the parent container of the selected file or folder.
   --
         If set to a string, the disk browser window will be renamed to string.
   --
      inputMsg default to generalmessages's askDiskBrowserName if missing
   --
      defaultInput default to the "" if  missing.
   --
      defautlInputToContainerName default to the name of the enclosing folder if true or missing.
   --
      openBrowser default to false if missing.
   --
      getParentContainer default to true if missing
   --
return:
   --
      - The new name of the disk browser window.
   --
      - false if there is an error or if the user cancelled the dialog.
   --
--------------------------------------------------------------------------------
   
on nameBrowser(argsRecord)
      
      --
set warning to true if missing
      
try
         
set warning to warning of argsRecord
      
on error thisError
         
set warning to true
      
end try
      
      --
required:  args:  thisSelection
      
try
         
set sel to thisSelection of argsRecord
      
on error thisError
         
if warning = true then tell dialog to displayError(errormessages's errorArgs & thisError)
         
return false
      
end try
      
      --
optional inputMsg, default to generalmessages's askBrowserName if missing
      
try
         
set inputMsg to inputMsg of argsRecord
      
on error
         
set inputMsg to generalmessages's askBrowserName
      
end try
      
      --
optional defautlInputToContainerName arg, default to true if missing
      
try
         
set defautlInputToContainerName to defautlInputToContainerName of argsRecord
      
on error
         
set defautlInputToContainerName to true
      
end try
      
      --
optional defaultInput arg, if missing, default to ""
      
try
         
set defaultInput to defaultInput of argsRecord
      
on error
         
set defaultInput to ""
      
end try
      
      --
optional browserName arg, if missing, default to false
      
try
         
set browserName to browserName of argsRecord
      
on error
         
set browserName to false
      
end try
      
      --
optional newBrowser arg, if missing, default to false
      
try
         
set newBrowser to newBrowser of argsRecord
      
on error
         
set newBrowser to false
      
end try
      
      --
optional getParentContainer arg, if missing, default to false
      
try
         
set getParentContainer to getParentContainer of argsRecord
      
on error
         
set getParentContainer to true
      
end try
      
      
tell application "BBEdit"
         
try
            
            
if class of sel is list then
               
set oneSelection to item 1 of sel
            
else
               
set oneSelection to sel
            
end if
            
            
if getParentContainer = true then
               
tell application "Finder" to set fcontainer to (container of oneSelection as alias)
            
else -- don't try to get the parent container
               
set fcontainer to oneSelection
            
end if
            
            --
sanity check in case getParentContainer = false to see if we have an alias to a container
            
if getParentContainer = false then
               
try
                  
tell application "Finder" to folder fcontainer exists
               
on error thisError
                  
if warning = true then tell dialog to displayError(errormessages's needAContainer)
                  
return false
               
end try
            
end if
            
            --
get container name
            
tell application "Finder" to set fcontainerName to (name of fcontainer)
            
         
on error thisError
            
if warning = true then tell dialog to displayError(errormessages's finderCantGetContainerOfSel & thisError)
            
return false
         
end try
         
         
try
            
if browserName = false then
               
               
if defautlInputToContainerName = true then set defaultInput to fcontainerName
               
               
tell dialog to set answer to input(inputMsg, defaultInput)
               
if answer = false then return false -- the user cancelled the dialog, abort
               
if button returned of answer is "OK" then
                  
set newname to text returned of answer
                  
if newBrowser = true then open fcontainer
                  
set name of disk browser window 1 to newname
                  
return newname
               
end if
            
else
               --
set the browser name to its container and bypass the dialog
               
if browserName = true then set browserName to fcontainerName
            
end if
            
            
if newBrowser = true then open fcontainer
            
set name of disk browser window 1 to browserName
            
return browserName
            
         
on error thisError
            
if warning = true then tell dialog to displayError(errormessages's generalerror & thisError)
            
return false
         
end try
         
      
end tell
      
   
end nameBrowser
   
   
   --
--------------------------------------------------------------------------------
   --
newFile method:
   --
      Create a new file or new folder.
   --
      If a file is selected, create the new file/new folder in the same folder.
   --
      If a folder is selected, create the new file/new folder in the selected folder.
   --
      Can create only one file/folder at a time
   --
--------------------------------------------------------------------------------
   --
  argsRecord:
   --
      {thisSelection: oneSelection, [warning: false, newFileName: argString, inputMsg: argString, defautlInput: argString, createNewFolder: true, openAfterCreated: true]}
   --
default args:
   --
      warning default to true if missing.
   --
      newFileName default to false if missing, if set, inputMsg and defaultInput will be disgarded, this bypass the dialog for asking the new file/folder name.
   --
      inputMsg default to generalmessages's askFileName or to generalmessages's aksFolderName if createNewFolder is true.
   --
      defaultInput default to  "" if  missing.
   --
      createNewFolder default to false if missing.
   --
      openAfterCreated default to false if missing, ignored if createNewFolder is true.
   --
return:
   --
      - An alias to the new file..
   --
      - false if there is an error or if the user cancelled the dialog.
   --
--------------------------------------------------------------------------------
   
on newFile(argsRecord)
      
      --
optional warning arg, default to true if missing
      
try
         
set warning to warning of argsRecord
      
on error
         
set warning to true
      
end try
      
      --
required:  thisSelection arg
      
try
         
set sel to thisSelection of argsRecord
      
on error thisError
         
if warning = true then tell dialog to displayError(errormessages's errorArgs & thisError)
         
return false
      
end try
      
      --
optional createNewFolder arg, if missing, default to false
      
try
         
set createNewFolder to createNewFolder of argsRecord
      
on error
         
set createNewFolder to false
      
end try
      
      --
optional inputMsg arg, if missing, default to generalmessages's askFileName or to generalmessages's askFolderName if createNewFolder is true
      
try
         
set inputMsg to inputMsg of argsRecord
      
on error
         
if createNewFolder = true then
            
set inputMsg to generalmessages's askFolderName
         
else
            
set inputMsg to generalmessages's askFileName
         
end if
      
end try
      
      --
optional defaultInput arg, if missing, default to ""
      
try
         
set defaultInput to defaultInput of argsRecord
      
on error
         
set defaultInput to ""
      
end try
      
      --
optional openAfterCreated arg, if missing, default to false
      
try
         
set openAfterCreated to openAfterCreated of argsRecord
      
on error
         
set openAfterCreated to false
      
end try
      
      --
optional newFileName arg, if missing, default to false
      
try
         
set newFileName to newFileName of argsRecord
      
on error
         
set newFileName to false
      
end try
      
      
tell application "BBEdit"
         
         
if newFileName is false then
            
tell dialog to set answer to input(inputMsg, defaultInput)
            
if answer = false then return false -- the user cancelled the dialog, abort
            
if button returned of answer is "OK" then
               
set newname to text returned of answer
            
end if
         
else