Local Links

External Links

Contact

Search this site

Arbed - Scripting


Similar to Xojo's IDE Scripting, Arbed can be scripted to browse a project and modify it. With Arbed, this can be done in much more detail than it's currently possible with the IDE.

Arbed scripts are plain text files with extension ".rbs" or, preferrably, ".arbs". When they're opened in Arbed, there will be a "Run" button that will execute the script on the frontmost project window.

Scripting API

First off, the scripting is based on XojoScript. Refer to Xojo's documentation of the scripting language and to its function overview for basic functions that are available to you in Arbed's scripting.

The Arbed-specific API currently consists of the following functions:

Const PropTypeInteger = 1231975456 // 'Int '
Const PropTypeDouble = 1147300896 // 'Dbl '
Const PropTypeString = 1400140398 // 'Strg'

Class PrjItem
  Function HasSubItems () as Boolean // returns true if SubItems() returns a non-empty iterator
  Function SubItems () as PrjItemIterator // returns an iterator for the item's members
  Function HasProperties () as Boolean // returns true if Properties() returns a non-empty iterator
  Function Properties () as PrjItemIterator // returns an iterator for the item's properties
  Function Parent () as PrjItem // returns the item's parent
  Function Kind () as String // same as you see in the "Kind" column in the Arbed code editor
  Function Type () as String // The class name used by Arbed internally for this item
  Function IsOfType (type as String) as Boolean // Tests if item is a member of the given internal class
  Function IsDynamicConstant () as Boolean (v1.9.6)
  Function IsProperty () as Boolean // returns true if item is a Property (vs. member/subItem)
  Function IsTextualProperty () as Boolean // returns true if the Property contains numeric or textual (not binary) values (v1.9.6)
  Function ItemID () as Integer // top level items have an ID <> 0
  Function ContainerID () as Integer // refernence to another top level item's ItemID
  Function Name () as String // plain name of an item, may be empty
  Function Label () as String // "smart" name of an item (methods include their signature)
  Function Identifier (withSignature as Boolean = false) as String // semantic path to the item
  Function Location (withSignature as Boolean = false) as String // project path to the item
  Function Declaration () as String
  Function DisplayValue () as String // returns values of Properties and Constants in a human readable form (v1.9.6)
  Function GetSource (ByRef value as String) as Boolean
  Function GetValue (ByRef value as String) as Boolean // Gets the raw value of Properties and Constants, may be binary!
  Function SetSource (sourceText as String, trimLines as Boolean = false) as Boolean
  Function SetValue (value as String) as Boolean
  Function SetValue (value as Integer) as Boolean // (v1.9.2)
  Function SetValue (value as Double) as Boolean // (v1.9.2)
  Function SetValue (value as Boolean) as Boolean // (v1.9.2)
  Function CanSetName () as Boolean
  Function SetName (value as String) as Boolean
  Function Delete () as Boolean
  Function AttributesProp (addIfMissing as Boolean = false) as PrjItem // Gets (optionally adds) the Attributes item (v1.7) 
  Function Scope () as Integer // return: 1 = public or global, 2 = protected, 3 = private (v1.7)

  // The following method lets you look up a ShortProp, and optionally add it (then you also have to pass a type)
  Function ShortPropByName (name as String, addIfMissing as Boolean, propType as UInt32 = PropTypeString) as PrjItem
End Class

Class PrjItemIterator
  Function GetNextPrjItem (ByRef item as PrjItem) as Boolean
  Function Count () as Integer
End Class

Class FoundItem
  Function PrjItem () as PrjItem
  Function Value () as String
  Function Value (assigns newValue as String) as Boolean
End Class

Class FoundItemIterator
  Function GetNextFoundItem (ByRef item as FoundItem) as Boolean
End Class

Function FindText (txt as String) as FoundItemIterator
Function PrjItemRoot () as PrjItem
Function PrjItemByID (itemID as Integer) as PrjItem // complements PrjItem.ItemID
Function PrjItemByLocation (location as String) as PrjItem // complements PrjItem.Location

// If you make many modifications to the project, wrap them to make it faster:
Sub StartUpdating ()
Function EndUpdating () as Boolean

Class Dictionary // since Arbed 1.6
  Sub Constructor ()
  Function Clone () as Dictionary
  Function Count () as Integer
  Function Key (idx as Integer) as String
  Function Value (key as String) as String
  Function Lookup (key as String, default as String) as String
  Sub Value (key as String, assigns value as String)
End Class

Class BinaryDict
  // (same as Dictionary, just that the keys are case sensitive)
End

// Global helper functions, since Arbed 1.6 (some require later versions)
Function EndOfLine as String // Returns RB's EndOfLine value
Function EndOfLineOfText(text as String) As String // Returns EOL used by text (or LF on OSX and Linux, CR+LR on Windows if text contains no EOL) (v1.6.1)
Function ReplaceLineEndings(text as String, replaceEOLwith as String) As String // Same as RB's function (v1.6.1)
Function Str(f as Double, format as String) As String // Same as RB's function (v1.6.1)
Function Str(i as Int64, format as String) As String // Same as RB's function (v1.6.1)
Function StrEqual (a as String, b as String) as Boolean // returns true if both strings are equal in their binary representation (like StrComp(a,b,0)=0)
Function ShellExecute (cmd as String, ByRef result as String) as Integer // Invokes RB's Shell.Execute, returning its Result and ErrorCode properties
Function TargetOS as String // Returns "OSX" when Arbed runs on Mac OS X, "Win" on Windows and "Linux" otherwise
Sub Beep // RB's Beep (v1.6.2)

// Global helper functions mimicking the same provided by Xojo's IDE Scripting, since Arbed 1.8
Sub Speak (txt as String, interrupt as Boolean = false)
Function ShowDialog (msg as String, expl as String = "", dftBut as String = "OK", cnclBut as String = "", altBut as String = "", icon as Integer = 0)
Function ProjectShellPath () as String
Function ProjectNativePath () as String // v1.9.2
Function SelectProjectItem (itemPath as String) as Boolean
Function Text () as String
Function Text (assigns source as String)

// Encryption, since Arbed 1.6
Function EncryptBlowfishMBS (s as String, key as String) as String // Uses the BlowfishMBS class
Function DecryptBlowfishMBS (s as String, key as String) as String // Reverse of EncryptBlowfishMBS
Function EncryptAESMBS (s as String, key as String, optionalIVector as String = "") as String // Uses the AESMBS class
Function DecryptAESMBS (s as String, key as String, optionalIVector as String = "") as String // Reverse of EncryptAESMBS

// Base64 and Hex encoding, since Arbed 1.6
Function EncodeBase64 (s as String) as String // Invokes RB's EncodeBase64(s,0) function
Function DecodeBase64 (s as String) as String // Invokes RB's DecodeBase64(s) function
Function EncodeHex (s as String) as String // Invokes RB's EncodeHex(s,0) function
Function DecodeHex (s as String) as String // Invokes RB's DecodeHex(s) function

// String encoding, since Arbed 1.6
Function DefineAsUTF8 (s as String) as String // Returns s.DefineEncoding(Encodings.UTF8)
Function ConvertToUTF8 (s as String) as String // Returns s.ConvertEncoding(Encodings.UTF8)
Function HasEncoding (s as String) as Boolean // Returns s.Encoding <> nil

// File and Directory operations, since Arbed 1.6.1
Function AppendToFile(path as String, data as String) As Boolean // Appends to existing file or creates file if nonexisting
Function ChooseFolderPath(title as String) As String // Shows a modal dialog to select a folder
Function ChooseOpenPath(extensions as String, title as String) As String // Shows a modal dialog to open a file
Function ChooseSavePath(extensions as String, title as String, suggestedPath as String) As String // Shows a modal dialog to save a file
Function CreateDirAtPath(path as String) As Boolean // Creates a directory. Returns true if creation worked or if there was already a directory there
Function DeleteItemAtPath(path as String) As Boolean // Deletes a file or empty directory
Function LastPathComponent(path as String) As String // Returns the name of a path to a file or folder
Function LengthOfFile(path as String) As Int64 // Returns the size of a file, or 0 for directories
Function LoadFromFile(path as String, ByRef data as String) As Boolean // Loads a file into a variable
Function MoveItemFromPathToNameOrPath(path as String, newNameOrPath as String) As Boolean // Moves or renames an item
Function PathComponents(path as String) As String() // Returns an array of all path segments
Function PathDoesExist(path as String) As Boolean // Returns true if the item at the path exists
Function PathIsAlias(path as String) As Boolean // Returns true if the item at the path is an Alias (or symlink)
Function PathIsDirectory(path as String) As Boolean // Returns true if the item at the path is a folder
Function PathSeparator() As String // Returns "/" on OSX and Linux, "\" on Windows
Function ReadDirectoryItems(path as String, getTrueItems as Boolean, ByRef names() as String) As Boolean // Loops over all items in a directory,
  // ... returning their names. Uses "FolderItem.TrueItem()" if getTrueItems=true, otherwise uses "FolderItem.Item()".
Function ResolveAliasPath(path as String) As String // Follows an Alias (or symlink), returning the destination path
Function SaveToFile(path as String, data as String, replaceExisting as Boolean = false) As Boolean // Writes a file

// RegEx operations, since Arbed 1.6.1
Class RegEx
  // The RegEx class (including RegExMatch and RegExOptions) are identical to the ones the RB framework offers. See its documentation.
End Class

// Selection operations, since Arbed 1.6.2
Function SelectedPrjBrowserItems () as PrjItemIterator // Returns the items that are selected in the left browser pane of the project window.
Function SelectPrjBrowserItem (item as PrjItem, selected as Boolean = true) as Boolean // Selected or unselects an item
Sub ClearPrjBrowserSelection () // Clears the selection
Function RevealPrjItem (item as PrjItem, focusOnSource as Boolean = true, setFocus as Boolean = true) as Boolean // Shows the item in the window.

// Sorting, since Arbed 1.7
Sub Sort (int32Array() as Int32)
Sub Sort (int64Array() as Int64)
Sub Sort (stringArray() as String, mode as Integer = 0) // mode as in StrComp, or mode=2 for case-insensitive compare (ASCII only)

Note: The function Parent used to be named Container before version 1.6. It was changed to avoid confusion with the unrelated function ContainerID.

Use the "print" command to output a line of text. If you print "<output-to-new-window>" first, the output will appear in a new window, otherwise it'll appear in the editor window.

Examples

Note: More scripts are included with the Arbed download (inside the "Scripts" folder).

This script gets the value of the App's Bundle Identifier and changes it by appending ".modified" to it.

(Note: "<Settings>" refers to most of the project-wide settings, including most App properties as well as some other build settings. You can look at all of them by using PrjItemRoot().Properties in place of SubItems in the example further below).

dim settings as PrjItem = PrjItemByLocation ("<Settings>")
dim addIfMissing as Boolean = true // if it's missing, we'll add it with the following type
dim newType as UInt32 = PropTypeString // or PropTypeInteger or PropTypeDouble
dim item as PrjItem = settings.ShortPropByName ("BundleIdentifier", addIfMissing, newType)
dim s as String
if item.GetValue(s) then
  print "old value: "+s
  if not item.SetValue("xyz.yourdomain.new-identifier") then
    print "set failed."
  end
else
  print "no value."
end

This script searches all Control properties named "TextFont" and "TextSize", resetting their values to defaults:

Sub FindReplacePDef (find as String, newValue as String)
  dim iter as FoundItemIterator = FindText (find)
  if iter = nil then
    Print "not found"
  else
    dim item as FoundItem
    while iter.GetNextFoundItem (item)
      dim lbl as String
      dim pi as PrjItem
      pi = item.PrjItem
      dim value as String
      if pi.Kind = "PDef" then
        if pi.GetValue (value) then
          value = ", value: "+value
        end
        Print "found: <"+item.Value+"> in "+pi.Location(true)+value
        if not pi.SetValue(newValue) then
          print "set failed"
        end
      end
    wend
  end
End Sub

FindReplacePDef "TextFont", "System"
FindReplacePDef "TextSize", "0"

This script lists all top level project items and their immediate members:

// Lists all top level project items (settings, classes, modules etc.),
// and lists all their immediate members and properties as well.

dim root as PrjItem = PrjItemRoot()
dim iter as PrjItemIterator = root.SubItems()
dim item as PrjItem

while iter.GetNextPrjItem(item) // iterate over top level items

  // let's check if the item is inside another (i.e. a module or folder)
  dim containerInfo as String = ""
  if item.ContainerID <> 0 then
    dim containerItem as PrjItem = PrjItemByID (item.ContainerID)
    if containerItem <> nil then
      containerInfo = ", container: " + containerItem.Label
    end
  end

  print item.Label + ": " + item.Kind + containerInfo

  // now iterate over this item's properties
  dim iter2 as PrjItemIterator = item.Properties()
  dim item2 as PrjItem
  while iter2.GetNextPrjItem(item2)
    showItem item2
  wend

  // now iterate over this item's non-property members
  iter2 = item.SubItems()
  while iter2.GetNextPrjItem(item2)
    showItem item2
  wend
wend

// A subroutine to display the item's kind or value
sub showItem (item as PrjItem)
  dim v as String
  if item.IsProperty and item.GetValue(v) then
    print "  " + item.Label + " = " + v
  else
    print "  " + item.Label + ": " + item.Kind
  end
end sub

This script finds all methods in the frontmost open project and adds the line System.DebugLog CurrentMethodName to each of them:

// Set up global variables that the methods can access and alter
dim changeCount as Integer
dim textToAddToTopOfSource as String

// Here the program starts
textToAddToTopOfSource = "System.DebugLog CurrentMethodName" + EndOfLine
scan (PrjItemRoot())
Print "Finished. " + Str(changeCount) + " methods were modified."
// Here the program ends

//
// This function finds all methods, events and other items that contain source code:
//
sub scan (container as PrjItem)
  dim item as PrjItem

  // first loop: find all methods and modify them as needed
  dim iter as PrjItemIterator = container.SubItems()
  while iter.GetNextPrjItem(item)
    if item.IsOfType ("MethodCodeBase") then
      processMethod (item)
    end
  wend

  // second loop: look into this item to find methods inside (-> recursion)
  iter = container.SubItems()
  while iter.GetNextPrjItem(item)
    if item.HasSubItems() then
      scan (item)
    end
  wend
end sub

//
// This function modifies the source code of a found method:
//
sub processMethod (item as PrjItem)
  dim src as String
  if not item.GetSource (src) then
    Print "Can't get source for "+item.Label
  else
    // check if the to-be-added text is already present
    if Left (src, Len(textToAddToTopOfSource)) = textToAddToTopOfSource then
      // already present
    else
      src = textToAddToTopOfSource + src
      if not item.SetSource (src) then
        Print "Can't set source for "+item.Label
      else
        // modification was successful
        changeCount = changeCount + 1
      end
    end
  end
end sub

Page last modified on 2020-08-18, 11:05 UTC (do)
Powered by PmWiki