How to do 'include' files in scripts

Posted by Nick Gammon on Fri 24 May 2002 10:35 PM — 4 posts, 29,638 views.

Australia Forum Administrator #0
If you want to break your script file into smaller files, you can use these techniques to "include" the sub-files.

Thanks to Krenath, Magnum and Rire for contributing ...



VBscript


Function GetFileContents(sFileName)
  Dim FSO, ScriptFile
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Set ScriptFile = FSO.OpenTextFile(sFilename,1)
  GetFileContents = ScriptFile.ReadAll
  Set ScriptFile = Nothing
  Set FSO = Nothing
End Function

World.Note "Include Script File: IncludeA.vbs"
ExecuteGlobal GetFileContents("C:\mushclient\includea.vbs")
World.Note "Include Script File: IncludeB.vbs"
ExecuteGlobal GetFileContents("C:\mushclient\includeb.vbs")





Jscript


// ---------------------------------------- 
var FileScriptingObject = new ActiveXObject("Scripting.FileSystemObject"); 

function Include( FileName ) { 
  var File = FileScriptingObject.OpenTextFile( FileName, 1 ); 
  var Code = File.ReadAll(); 
  File.Close(); 
  return( Code ); 
} 

// YOU CANNOT EXECUTE THIS STATEMENT FROM INSIDE OF ANY 
// BLOCK OR OTHER SCOPE. IF YOU DO, THE INCLUDED FILE 
// WILL ONLY APPLY TO THAT SCOPE. 

World.Note ("Include Script File: IncludeA.js");
eval( Include( "c:\mushclient\includea.js" ) );	
World.Note ("Include Script File: IncludeB.js");
eval( Include( "c:\mushclient\includeb.js" ) );
#1
Kudos to everyone assisting with this, it works great and makes things seem a bit more modular(well, I'm forcing myself to code it as modular at least, now)

After implementing it, I found a few things to throw in and thought I would share.



Const myguild = "Fighter"

world.Note "Loading primary script."
VBInclude "SpeedWalk"
VBInclude myguild


Function ScriptDir
  Dim strDir
'GetInfo 35 is the script path and name
  strDir = Split(world.GetInfo(35), "\")
'Delete the filename, but leave the last item in the array, so that the last '\' remains(easy way to do it)
  strDir(UBound(strDir)) = ""

'Rejoin the array back together, without the filename, so only the path ending with a '\'
  ScriptDir = Join(strDir, "\")
End Function

Sub VBInclude(ByVal strFileName)
  Dim FSO, ScriptFile
  Dim strFullFileName
  Dim strScriptName

'Create the complete filename including path, name, and extension(this is VB, so it should end in .vbs)
  strFullFileName = ScriptDir & strFileName & ".vbs"

  Set FSO = CreateObject("Scripting.FileSystemObject")

'Does this file even exist?  If not, report as such and stop processing
  If (Not FSO.FileExists(strFullFileName)) Then
    world.Note "Failed importing: " & strFullFileName & vbCrLf & _
               "  Reason: File Not Found"
    Exit Sub
  End If

  Set ScriptFile = FSO.OpenTextFile(strFullFileName, 1)
  ExecuteGlobal ScriptFile.ReadAll
  Set ScriptFile = Nothing
  Set FSO = Nothing

' Are we traversing directories in the pathname?  
' If so, we want just the primary filename at this point
  If (InStr(1, strFileName, "\", 1) <> 0) Then
    strFileName = Split(strFileName, "\")(UBound(Split(strFileName, "\")))
  End If

'Try to find the description for this included file, 
' but if it doesn't exist, we don't want an error to be visible to the user
On Error Resume Next
  strScriptName = Eval(strFileName & "ScriptName")
On Error GoTo 0
'If it didn't exist, just use the filename, 
' otherwise use the description and filename
  If (IsEmpty(strScriptName)) Then
    strScriptName = strFullFileName
  Else
    strScriptName = strScriptName & vbCrLf & "  (" & strFullFileName & ")"
  End If
  world.Note "Importing script: " & strScriptName
End Sub


In Speedwalk.vbs


...

Function SpeedWalkScriptName
  SpeedWalkScriptName = "Speedwalking Script"
End Function

...


You can pull scripts from any directory relative from the directory of your main script.(the one containing this code)
eg: VBInclude "..\scripts\OtherScript"
(I've just included code allowing paths in the name, minimal testing shows it works)

If the file requested doesn't exist, it will tell you the file doesn't exist.

The <name>ScriptName function doesn't have to exist. If it doesn't, it will only report the filename included. If it does, it will report the description and filename included.
USA #2
I'm now using the following script file as my "Main.VBS". It'll load all files in the Modules directory under Mushclient (at least, where I have it installed on my machine...)

All the other scripts are stashed in the Modules directory and load automatically. I'm planning on making a small change so the code below can additionally look in the Worlds folder for the appropriate world directory and rummage for scripts there. Once I play around a little more, I'll be able to remove the hardcoded paths.

Such code should allow us to create totally modular files that just drag-and-drop for installation into MUSHclient. All relevant aliases, macros, etc. Can be created by script upon loading the script module. Don't know about you, but I'm excited :)

Quote:

ExecuteAllModules()

Function GetFileContents(sFileName)
  Dim fso,file
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Set File=FSO.OpenTextFile(sFilename,1)
  GetFileContents=File.ReadAll
  Set File = Nothing
  Set FSO = Nothing
End Function

Sub ExecuteAllModules
   Dim fso, Folder, File, Files
   Set fso = CreateObject("Scripting.FileSystemObject")
   Set Folder = fso.GetFolder("c:\Program Files\mushclient\modules")
   Set Files = Folder.Files
   For Each File in Files
      ON ERROR RESUME NEXT
    World.Tell "Loading Module " & File.name & "..."    
    ExecuteGlobal GetFileContents _
       (trim("c:\program files\mushclient\modules\ ") & File.name)
    If ERR Then 
      World.Note "FAILED: " & Err.Description
    Else 
      World.Note "Loaded."
    End IF
    ON ERROR GOTO 0
   Next
End Sub

'stub out events so MushClient doesn't complain.  
'They can be redefined later inside modules.
sub OnWorldOpen
end sub
sub OnWorldClose
end sub
sub OnWorldConnect
end sub
sub OnWorldDisconnect
end sub
sub OnWorldOpen
end sub
sub OnWorldClose
end sub
sub OnWorldConnect
end sub
sub OnWorldDisconnect
end sub
sub OnWorldGetFocus
end sub
sub OnWorldLoseFocus
end sub
Amended on Wed 29 May 2002 05:04 PM by Krenath
Canada #3
This is all very cool, but keep in mind Nick is working to implement a new way for installing "plugins", so much of this may be obsolete with newer versions. :)

Currently, I've put off any major scripting projects till the new version is released.

Of course, it will likely still apply for people who choose to install "plugins" this way, or for those using older versions.