From stack to program
A stack needs OXT-Beyond to open it. A standalone application does not: it is the engine and your stacks built into one program, which runs on a computer that has never seen OXT-Beyond. File > Save as Standalone Application builds one, into a folder for each platform you chose, next to the stack file.
Before the first build, open File > Standalone Application Settings. The settings are kept in the stack itself, so they are saved, and shared, with it:
- General: the program's name, and its inclusions (below).
- Stacks: the other stack files to build in, such as libraries and behaviors kept in files of their own.
- Copy Files: files and folders that go beside the program: pictures, sounds, help pages, a starting database.
- One pane for each platform: whether to build for it, and its icon, version and copyright.
- Bug Reports: what the user sees when an error is not caught (below).
Inclusions: what the program needs
The engine alone has every xTalk command, but not the libraries and extensions the IDE loads as it starts: the internet library, database support and its drivers, JSON, the HTTP server, widgets, OXT-Beyond's own extensions. A standalone carries only those it is given. Search for required inclusions looks through your scripts and adds what they use. Select inclusions lets you tick them yourself, on the Inclusions pane.
The search reads the words in your scripts, so it cannot see a library used through do (Dynamic code) or a command whose name is built in a string. If a standalone says a handler cannot be found when the IDE ran it happily, a missing inclusion is the first thing to look for: tick it by hand. For a database, tick both Database and the driver, such as SQLite (Databases).
Where is it running?
The same scripts run in the IDE and in the program, and now and then they must know which. the environment is development in the IDE and standalone application in a built program, and adds command line when it runs without windows. the platform is Win32 on Windows (both 32 and 64 bit), MacOS or Linux, and the processor says which kind of processor. Here is what they said on the computer that checks this page, which runs every example without windows:
put "environment:" && the environment
put "platform:" && the platform
put "processor:" && the processor
put "engine version:" && the version
environment: development command line platform: Linux processor: x86_64 engine version: 9.7.1-BeyondEngine
A common use is a tool or a test button that only the developer should see:
on preOpenStack
set the visible of button "Run tests" to (the environment begins with "development")
end preOpenStack
Files that travel with it
Files listed on the Copy Files pane are put beside the program, and specialFolderPath("resources") finds them. In the IDE the same call gives the folder of the stack file, so keep the files in the same place beside the stack while you work, and one path works in both:
function resourceFile pName
return specialFolderPath("resources") & "/assets/" & pName
end resourceFile
on openCard
set the filename of image "Logo" to resourceFile("logo.png")
if there is not a file resourceFile("help.html") then
answer warning "The help pages are missing. Please reinstall the program."
end if
end openCard
Use / between folders on every platform, Windows included: the engine turns it into what the system wants (Reading and writing files).
Where to keep the user's data
A program cannot save itself. Its main stack is built into the program file, and the folder it is installed in is usually read-only for the user. So anything that must outlast a run (settings, the user's work, a cache) goes in a file in one of the user's own folders (Reading and writing files). A small settings file can be a whole array, turned into bytes with arrayEncode (Split, combine and friends) and back with arrayDecode. This example keeps it in the temporary folder, so that it tidies up after itself:
local sSettings
function settingsFile
return specialFolderPath("temporary") & "/oxt-lesson-settings.dat"
end settingsFile
command saveSettings
put arrayEncode(sSettings) into URL ("binfile:" & settingsFile())
end saveSettings
command loadSettings
put empty into sSettings
if there is a file settingsFile() then
put arrayDecode(URL ("binfile:" & settingsFile())) into sSettings
end if
end loadSettings
put "dark" into sSettings["theme"]
put "20,40,660,520" into sSettings["windowRect"]
saveSettings
put empty into sSettings
loadSettings
put "theme:" && sSettings["theme"]
put "window:" && sSettings["windowRect"]
delete file settingsFile()
loadSettings
put "after the file is gone:" && the number of elements of sSettings
theme: dark window: 20,40,660,520 after the file is gone: 0
A real program keeps it where each system expects: specialFolderPath("support") on Windows (the user's AppData folder) and macOS (Application Support), and a folder in .config in the home folder on Linux. Give the program a folder of its own there, made the first time it is needed. The user's own documents belong in specialFolderPath("documents"), or wherever they choose with ask file (Dialogs).
function settingsFolder
local tFolder
switch the platform
case "Win32"
case "MacOS"
put specialFolderPath("support") & "/Lesson App" into tFolder
break
default
put specialFolderPath("home") & "/.config/lesson-app" into tFolder
end switch
if there is not a folder tFolder then create folder tFolder
return tFolder
end settingsFolder
Errors out in the world
In the IDE an error that nothing catches opens the script editor at the line. In a standalone there is no script editor: the Bug Reports pane decides what the user sees. A program can also handle them itself: an uncaught error sends errorDialog, with the error's details, to the object whose script failed, and from there along the message path, so a handler in the main stack's script hears them all. Writing them to a log file gives you something to read when a user says "it went wrong":
on errorDialog pError
local tLog
put specialFolderPath("documents") & "/Lesson App errors.txt" into tLog
put the internet date & return & pError & return & return after URL ("file:" & tLog)
answer error "Sorry, something went wrong. The details were saved in" && tLog
end errorDialog
Catching errors where they can happen, with try (Errors), is still better: there the script knows what it was doing and can carry on. errorDialog is the net under everything else.
Script-only stacks and version control
A stack file holds cards, controls, pictures and scripts in a binary format. A version control system such as git can keep it, but cannot show what changed in it or merge two people's changes. A script-only stack is a plain text file that holds a stack's script and nothing else: its first line names the stack, and the rest is the script (the engine ends the file with a line break), ready for git and any text editor. Libraries and behaviors (Libraries, Behaviors) suit it well, so a program can keep almost all its code in script-only stacks and only its windows in a binary stack:
put specialFolderPath("temporary") & "/oxtLessonTools.livecodescript" into tPath
create script only stack "oxtLessonTools"
put the scriptOnly of stack "oxtLessonTools"
set the script of stack "oxtLessonTools" to "function shout pText" & return & \
" return toUpper(pText) & " & quote & "!" & quote & return & "end shout"
set the filename of stack "oxtLessonTools" to tPath
save stack "oxtLessonTools"
delete stack "oxtLessonTools"
put URL ("file:" & tPath)
start using stack tPath
put shout("hello")
stop using stack tPath
delete file tPath
true script "oxtLessonTools" function shout pText return toUpper(pText) & "!" end shout HELLO!
List the script-only stacks in the main stack's stackFiles, a stack name and a path relative to the main stack's file on each line, and the engine finds each by its name the first time a script refers to it, opening the file then. The Stacks pane of the settings lists them too, to build into the standalone.
Programs without windows
A standalone can also be a tool for the terminal, or a job a server runs. Started with -ui, it runs with no windows at all. the commandArguments holds what followed the program's name on the command line, a numbered array; write ... to stdout prints, and to stderr prints errors apart from the output; and quit with a number ends it with that exit code, 0 for success. A program with no windows must quit when it is done, or it waits for events forever:
-- run as: sum -ui 4 5 6.5
on startup
local tArguments, tTotal
put the commandArguments into tArguments
if the number of elements of tArguments is 0 then
write "usage: sum -ui NUMBER..." & return to stderr
quit 2
end if
put 0 into tTotal
repeat for each element tArgument in tArguments
if tArgument is not a number then
write "not a number:" && tArgument & return to stderr
quit 1
end if
add tArgument to tTotal
end repeat
write tTotal & return to stdout
quit 0
end startup
That is exactly how this site's lessons are checked: an OXT-Beyond engine started with -ui runs every example, compares what it puts with what the page shows, and quits with the result.
Try it yourself
Write a tiny settings library: setPref saves a value under a name and writes all the settings to a file at once, and getPref gives a value back, reading the file first if the settings are not in memory. Save a theme and a font size, forget them, and show that getPref still knows them, and that a setting never saved is empty.
Show a solution
local sPrefs
function prefsFile
return specialFolderPath("temporary") & "/oxt-lesson-prefs.dat"
end prefsFile
command setPref pKey, pValue
put pValue into sPrefs[pKey]
put arrayEncode(sPrefs) into URL ("binfile:" & prefsFile())
end setPref
function getPref pKey
if sPrefs is not an array and there is a file prefsFile() then
put arrayDecode(URL ("binfile:" & prefsFile())) into sPrefs
end if
return sPrefs[pKey]
end getPref
setPref "theme", "dark"
setPref "fontSize", 14
put empty into sPrefs
put "theme is" && getPref("theme")
put "fontSize is" && getPref("fontSize")
put "missing is empty:" && (getPref("missing") is empty)
delete file prefsFile()
theme is dark fontSize is 14 missing is empty: true
In a real program, prefsFile would use the settings folder of the section above, and the whole library would be a script-only stack that the main stack starts using as it opens.
Words in this lesson
Save as Standalone ApplicationStandalone Application Settingsinclusionsthe environmentthe platformspecialFolderPathresourcesarrayEncodearrayDecodeerrorDialogscript only stackthe scriptOnlythe stackFilesthe commandArgumentsstdoutstderrquitEach one finds every lesson that uses it. The Dictionary has the whole story of each, with its syntax and more examples.