macOS plist utility

Share your advanced PureBasic knowledge/code with the community.
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

macOS plist utility

Post by Rinzwind »

Another KISS tool to customize app plist and Resources in both debug and release mode:

Code: Select all

; Last update: 191217
EnableExplicit

;/Applications/plist "%FILE" "%EXECUTABLE"

OpenConsole()

Global SourceFolder.s,SourceFileName.s, SourceFilePath.s, ExecutableFile.s, LogFile.s
Enumeration LogLevel
  #LogNothing
  #LogErrors
  #LogAll
EndEnumeration
Global LogLevel = #LogErrors

Procedure LPrint(msg.s, level = #LogErrors)
  Protected file
  
  If level > LogLevel
    ProcedureReturn
  EndIf
  PrintN(msg)
  
  file = OpenFile(#PB_Any, LogFile, #PB_File_Append)
  If file
    WriteStringN(file, msg)
    CloseFile(file)
  EndIf    
EndProcedure

Procedure Init()
  Protected c, ext.s
  
  ;SourceFilePath = ""
  ;ExecutableFile = ""
  If SourceFilePath = ""
    c = CountProgramParameters()
    If And c = 2
      SourceFilePath = ProgramParameter(0)
      If SourceFilePath = ""
        LPrint("Please save source first.", #LogErrors)
        ProcedureReturn #False
      EndIf
      ExecutableFile = ProgramParameter(1)
    Else
      LPrint(~"Usage: plist \"%FILE\" \"%EXECUTABLE\" (After Compile/Run)", #LogErrors)
      ProcedureReturn #False
    EndIf
  EndIf
  SourceFolder = GetPathPart(SourceFilePath)
  SourceFileName = GetFilePart(SourceFilePath)
  LogFile = SourceFolder + SourceFileName + "-plist.log"  
  DeleteFile(LogFile)
  ext = GetExtensionPart(ExecutableFile)
  If ext <> "app"
      LPrint("Application (.app) expected", #LogAll)
    ProcedureReturn #False
  EndIf    
  LPrint("SourceFilePath: " + SourceFilePath, #LogAll)
  LPrint("ExecutableFile: " + ExecutableFile, #LogAll)  
  ProcedureReturn #True
EndProcedure

Procedure Go()
  Protected src.s, dest.s, name.s, cmd.s
  name = GetFilePart(SourceFilePath, #PB_FileSystem_NoExtension)
  src = SourceFolder + name + ".plist"
  If FileSize(src) = -1
    src = SourceFolder + "Info.plist"
  EndIf
  dest = ExecutableFile + "/Contents/Info.plist"
  CopyFile(dest, SourceFolder + "Backup-" + name + ".plist") ; Backup original PB plist
  If FileSize(src) > 0
    If CopyFile(src, dest)  
      LPrint("Info.plist updated", #LogAll)
    Else
      LPrint("Info.plist could not be updated (" + dest + ")", #LogErrors)
    EndIf
  Else
    LPrint("No Info.plist found (" + src + ")", #LogAll)
  EndIf
  src = SourceFolder + name + ".Resources/"
  If FileSize(src) <> -2
    src = SourceFolder + "Resources/"
  EndIf
  dest = ExecutableFile + "/Contents/Resources/"
  If FileSize(src) = -2
    If FindString(dest, src) = 0
      cmd = "cp -rp '" + src + "' '" + dest + "'"
      If RunProgram("/bin/sh", "-c " + #DQUOTE$ + cmd + #DQUOTE$, "") 
      ;If CopyDirectory(src, dest, "", #PB_FileSystem_Recursive | #PB_FileSystem_Force) ; !CopyDirectory does not include executable permissions...
        LPrint("Resources folder updated", #LogAll)
        ;cmd = "find '" + dest + "' -type f -not -name '*.*' -exec chmod +x \{\} \;"
        ;RunProgram("/bin/sh", "-c " + #DQUOTE$ + cmd + #DQUOTE$, "")
      Else
        LPrint("Resources folder could not be updated (" + dest + ")", #LogErrors)
      EndIf
    EndIf
  EndIf
EndProcedure

If Init()
  Go()
EndIf

If FileSize(LogFile) > 0
  RunProgram("open", "-a TextEdit.app " + #DQUOTE$ + LogFile + #DQUOTE$, "")
EndIf

CloseConsole()
Compile as Console app plist and save somewhere.

-PB Menu Tools/Configure Tools/New
-Command Line: /..../plist
-Arguments: "%FILE" "%EXECUTABLE"
-Name: plist
-After Compile/Run AND After Create Executable (so create two entries)
-Wait until tool quits
-Hide Tool from the Main Menu

Next put your custom Info.plist in the same folder as the PB source (or name it <PB_FileNameWithoutExtension.plist>) and create an optional Resources (or <PB_FileNameWithoutExtension.Resources>) folder in the PB source folder if needed.

After compile, run or create app the .plist is copied into the .app package together with the Resources folder contents if found .

The Resources path is accessible with

Code: Select all

Global BundlePath.s = PeekS(CocoaMessage(0, CocoaMessage(0, CocoaMessage(0, 0, "NSBundle mainBundle"), "bundlePath"), "UTF8String"), -1, #PB_UTF8)
Global ResourcesPath.s = BundlePath + "/Contents/Resources/"
(there should be a build-in function/constant/variable for that IMHO)

ps. I might update this from time to time if I add some things or find bugs like I did now...