Description
fscript is a program that allows F-Script scripts to be run from the command line, and to can also present an interpreter prompt in a shell, rather than requiring a GUI program. fscript also provides some useful classes and methods that make the language more appropriate for general scripting tasks, such as line-oriented input/output, regular expressions, and a library importing system.
In this documentation, fscript is used to refer exclusively to the command-line program, while "F-Script Interpreter" refers to the internal FSInterpreter object that actually does the real work of running the script.
Using fscript
The fscript program is installed in /usr/bin, so we may use it directly to run scripts:
$ fscript myscript.fs
However, other scripting languages like Perl and Python allow a "shebang" line at the beginning of the script file to tell the shell which interpreter program to use, so that the script can be executed directly. It would be nice to be able to do the same thing with F-Script scripts; however, #!/usr/bin/fscript is not a comment in F-Script, as it is in those other languages, and will cause a syntax error. As a work-around, when fscript loads a file - either as the main script or as a library with sys import: - it looks for a shebang command on the first line of the script file. If the first line is exactly "#!/usr/bin/fscript", the fscript strips this line before handing the script's contents to the F-Script interpreter.
If no filename is provided, fscript will open an interactive interpreter prompt. Type sys exit to quit.
Currently, fscript does not use any command-line switches to change behavior, although it may in the future.
fscript currently does only links to the Foundation Kit, so scripts that are run with it cannot use any classes from the Application Kit, and thus cannot put up graphical applications. This is a planned addition for the future.
The fscript program has several built-in classes and categories that provide common scripting-language functionality, such as line-oriented file handles, regular expressions, and Perl-like looping constructs. These additions are listed at the end of this document.
fscript traps all syntax errors and other exceptions that are not handled by the script itself. Unlike the regular F-Script interpreter, fscript reports both the line number and character number of the error's location, rather than just the offset into the script text.
fscript adds several important methods to the global sys object::
- in
- Returns an FSFile object representing standard input
- out
- Returns an FSFile object representing standard output
- err
- Returns an FSFile object representing standard error
- args
- Returns an array containing the command-line arguments, if any, that were supplied to the script. In the manner of Perl's
@ARGV array, the name of the script is not included as the first element.
- scriptname
- Returns a string containing the name of the main program, which will not be the name of the currently executing script if it was pulled in with import:
- help
- Returns an object that offers help on several features of the interpreter. Currently available help topics:
import , version , quit , and frameworks
In versions prior to 2.2, these were global variables. To reduce namespace pollution, they have been moved into the sys object.
fscript requires the F-Script framework to be installed in /Library/Frameworks. As of version 2.0, the fscript executable has the PCRE library compiled in, so the old AGRegex package is no longer necessary. If you are replacing an older version of fscript, you can remove this package.
One of F-Script's advantages is that the excellent classes from the Cocoa platform are available. Below is the bash shell script used to generate the HeaderDoc for this project:
#!/bin/bash
# This file compiles headerdoc for all the headers in the project, then compiles
# the top-level headerdoc
# The script caches file modifications times in the header_mod_times file to
# avoid unnecessary reprocessing
MOD_FILE=header_mod_times
# rebuild all files if desired
if [ "$1" = clean ]; then
rm -f "$MOD_FILE"
fi
# create a file to cache modification times
if [ ! -f "$MOD_FILE" ]; then
touch "$MOD_FILE"
fi
OUTPUT_DIR=Documentation
# We'll create a symlink to the project-specific HeaderDoc config file
CONFIG_LOC=~/Library/Preferences/com.apple.headerdoc2HTML.config
if [ -f "$CONFIG_LOG" ]; then
mv "$CONFIG_LOC" "$CONFIG_LOC.temp"
fi
ln -s "$PWD/Documentation/headerdocconfig" "$CONFIG_LOC"
HEADERS='ArrayUtil FSSystemUtility FSNSNumberMod FSFile StringSprintf StringRegex FSNSMutableDictionary FileTest BlockForeach'
for HEADER in $HEADERS; do
FILE_MOD_TIME=`stat -f "%N %m" "$HEADER.h"`
FILE_MODIFIED=`grep "$FILE_MOD_TIME" "$MOD_FILE"`
if [ -z "$FILE_MODIFIED" ]; then
echo headerdoc2html -H -o $OUTPUT_DIR/ "$HEADER.h"
headerdoc2html -H -o $OUTPUT_DIR/ "$HEADER.h"
fi
done
stat -f "%N %m" *.h > "$MOD_FILE"
headerdoc2html -H -o $OUTPUT_DIR/ "fscript.hdoc"
gatherheaderdoc "$OUTPUT_DIR"
# get rid of the temp config file and put the old one back if any
rm -f "$CONFIG_LOC"
if [ -f "$CONFIG_LOG.temp" ]; then
mv "$CONFIG_LOC.temp" "$CONFIG_LOC"
fi
Note how it caches modifying times by using stat , grep , I/O redirection, and other hacks.
Here's an equivalent program in F-Script, using some of the additional methods and features from the command-line program:
#!/bin/fscript
"
This file compiles headerdoc for all the headers in the project, then compiles
the top-level package headerdoc.
The script caches file modifications times in the file header_mod_times to
avoid unnecessary reprocessing
"
modFileName := 'header_mod_times'.
"list of header names - use F-Script array messaging to append .h extension"
headers := { 'ArrayUtil', 'FSSystemUtility', 'FSNSNumberMod', 'FSFile', 'StringSprintf', 'StringRegex',
'FSNSMutableDictionary', 'BlockForeach', 'FileTest' }
@ ++ '.h'.
outputDir := 'Documentation'.
configLoc := '~/Library/Preferences/com.apple.headerdoc2HTML.config' stringByExpandingTildeInPath.
"if the mod times file exists and we were not told to run clean, use it"
"otherwise, use a blank file"
clean := (args count > 0) ifTrue:[ (args at:0) = 'clean'] ifFalse:[ false ].
oldModTimes := ((filem test_f:modFileName) & (clean not)) ifTrue:[
NSDictionary dictionaryWithContentsOfFile:modFileName.
]
ifFalse:[
NSDictionary dictionaryWithObjects:(NSDate distantPast enlist:(headers count)) forKeys:headers.
].
newModTimes := NSMutableDictionary dictionary.
"move existing config file out of the way and replace with a link to our file"
tempConfigLoc := configLoc ++ '.temp'.
(filem fileExistsAtPath:configLoc) ifTrue:[
filem movePath:configLoc toPath:tempConfigLoc handler:nil.
].
filem createSymbolicLinkAtPath:configLoc pathContent:'Documentation/headerconfig'.
"For each header file, check to see if it has been changed since the last time we ran this
script; if so, regenerate documentation files"
updateModTimes := NO.
[ :header | |fileModTime|
fileModTime := filem test_m:header.
((oldModTimes objectForKey:header) < fileModTime) ifTrue:[
"run headerdoc on the modified header file"
out println:('headerdoc2html -H -o ' ++ outputDir ++ '/ ' ++ header).
sys execNoOutput:'headerdoc2HTML' args:{'-H', '-o', outputDir++'/', header}.
updateModTimes := YES.
].
newModTimes setObject:fileModTime forKey:header.
]
value: @ headers.
"Save new modification times"
saveModTimes ifTrue:[
newModTimes writeToFile:modFileName atomically:YES.
].
"generate program header"
runh2h value:'fscript.hdoc'.
"create document structure"
sys execNoOutput:'gatherheaderdoc' args:{outputDir}.
"move existing config file back"
(filem test_f:tempConfigLoc) ifTrue:[
filem movePath:tempConfigLoc toPath:configLoc handler:nil.
].
Not that much longer, and a lot more readable! It also uses actual data structures like dictionaries and arrays, and stores them in a property list, avoiding potential bugs and security problems from shell expansion and parsing.
- Download the F-Script package (including framework, GUI interpreter, F-Script Anywhere, and other tools): download
-
fscript command-line program installer: download
- Source code for fscript: download
- The FSClass framework, which lets you write classes directly in F-Script (useful with the
sys import: method): download
The fscript installer installs three files: the framework FSRegex7 (source and separate binary available here) in /Library/Frameworks, the fscript executable in /usr/bin, and a manpage in /usr/share/man/man1.
- 2008-01-10
- Version 2.2
- Updated to be compatible with F-Script 2.0 alpha 6
- PCRE updated to version 7.8
- The global variables
in , out , err , scriptName , and args have been turned into methods on the sys object
- The global variable
filem has been removed
- 2008-01-10
- Version 2.0
- Updated to run on Mac OS X 10.5
- Now supports running in 64-bit mode
- Now requires F-Script 2.0
- The regular expression library has been integrated into the tool itself; the AGRegex framework is no longer required as a separate library. The AGRegex and AGRegexMatch classes have been renamed FSRegex and FSRegexMatch
- Improved the regular expression matching category on NSString
- PCRE engine updated to version 7.4
- "help version" and the -v flag now print the active machine architecture
- The "help" command now supports an additional option, "help frameworks", which will list the identifier and version of all loaded bundles and frameworks
- 2007-08-16
- Version 1.6
- Fixed a bug that made command-line arguments inaccessible
- 2007-08-16
- Version 1.5
- Add a
help object with information on importing files, quitting the interpreter, and versions of F-Script, the interpreter, and the PCRE library
- Clarified messages for 'file not found' errors
- Added '-v' (version) and '-c' (check syntax) command-line options
- The interactive interpreter can now be quit by typing 'Control-D' as well as
sys exit.
- FSRegex7 framework updated to PCRE 7.2
- Included several useful scripts in the Library directory (requires FSClass)
- Fixed formatting errors in -NSString sprintf: and -FSFile printf:withValues:
- Miscellaneous bug fixes
- 2007-02-13
- Version 1.2
- Added +dictionaryWithPairs: and +dictionaryWithFlatPairs: to NSDictionary
- Fixed a bug in 'sys import:'
- Added bold-faced prompts to compatible ANSI and color-xterm terminals
- 2007-02-07
- Version 1.1
- Fixed a bug that would cause 'sys execShell:' to crash
- Added interactive interpreter
- 2007-01-21
- Version 1.0
None known.
The fscript command-line program and libraries are made available under the GNU General Public License version 2:
License for fscript
fscript - command line interface and enhancements for F-Script
Copyright (C) 2007 Andrew Weinrich
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (file COPYING) for more details.
fscript incorporates some third-party code, the licenses for which are reproduced here:
Licence for PCRE
As of fscript 2.0, the tool directly incorporates version 7.4 or later of the Perl-Compatible Regular Expression Library. The source code to the library is included with the source disk image.
Copyright (c) 1997-2007 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
License for AGRegex
The Objective-C wrapper around the PCRE library for fscript was derived from the AGKit framework, particularly the AGRegex classes.
Copyright (c) 2002 Aram Greenman. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License for readln
The code for the FSFile readln method was adapted from the class IOSocketLineReader of the Halime newsreader application:
//
// ISOSocketLineReader.m
// Halime
//
// Created by iso on Mon May 21 2001.
// Copyright (c) 2001 Imdat Solak. All rights reserved.
//
Halime status 1.0rc2b
This is the source code of Halime 1.0rc2b. The source code is delivered to
you under the GPL - GNU General Public License (s. COPYING).
You may NOT use it to create any product called "Halime" or which name
resembles "Halime" in any way.
Otherwise, you are permitted to do with the code whatever you want.
Imdat Solak
November 4th, 2003
-------------------------------------------------------------------------------
|