This is a study note for Ammonite. It allows scripting in Scala and comes with an operating system library and a shell library.
1 Introduction
Ammonite is a mondern Scala REPL that has syntax highlighting, multi-line editing, library importing and other desired features missing in the default Scala REPL. It is lightweight without the project setting and loading of sbt. The Ammonite-REPL supports the following features
- pretty printing using PPrint
- editing with syntax highlighting, multi-liine editing, key-binding, history search, block input
- importing scripts and Ivy dependencies
- session saving and loading
- auto completion
- configuratble with
~/.ammonite/predef.sc
- embeddable
- os operations
- shell operations such as pipe
Scala script let you save and run code without settings of a project. A script can import other scripts. Scripts may take arguments.
2 Ammonite REPL
Use brew install ammonite-repl
to install Ammonite. Intialization code can be defined in ~/.ammonite/predef.sc
.
2.1 Start and Quit
- Run Ammonite:
amm
- Exit:
exit
orCtrl-D
. - Interrupt current execution:
Ctrl-C
- Use
amm -w foo.sc
to watch the file and rerun it when there is a change in the script. Useamm -w -p foo.sc
to watch and open an REPL. - Configure truncation: one of two methods
- use show command:
show(cmd, height = numberOfLines)
- customize
pprinter
:repl.pprinter() = repl.pprinter().copy(defaultHeight = 5)
- use show command:
- Save/load sessions, session can be named
repl.sess.save()
repl.sess.load()
2.2 Editing
- Auto completion: use
tab
- delete a word:
Ctrl W
- delete to the beginning:
Ctrl U
- moving cursor
- start of the line:
Ctrl A
orHome
- end of the line:
Ctrl E
orEnd
- one word left/right:
Esc-B/F
orOpt-Left/Right
- start of the line:
- clear the screen:
Ctrl L
- Stop/Resume screen output:
Ctrl-S/Q
- Undo:
Ctrl _
- Redo:
Opt/Esc _
2.3 Builtins
The bulitin imports include repl
and uitilities.
The repl
object has the following values:
prompt()
: change promptfrontEnd()
: user inputhelp
: help textlastException
: the last exceptionsess
: sessiontypeOf(t)
: find type oft
fullImports
: show all importsshow(t: Any, width: Interger, height: Interger, indet: Integer)
: configure pretty-printing of a value- …
The interp
object has the following values, some are imported in scope by default:
watch(p: os.Path)
: rerun when a file changesload
: load external scriptsrepositories
: resolversexit(value: Any)
: exit the REPL- …
The REPL has the following utilities:
source
: peek source codetime {...}
: time to run a commandbrowse
: view large outputdesugar
: explain script code
2.4 Configuration
To config a repository
|
|
repl.prompt()
repl.frontEnd()
interp.colors()
Use interp.configureCompiler
to configure Scala compiler.
These values are Ref[T]
. It can be set with a static value using repl.prompt() = "abc"
or to a live value (evulated everytime) as repl.prompt.bind(wd.toString + "@")
.
Jvm flags can be passed as environment variables when run amm, for example: JAVA_OPTS="-Xmx1024m" amm
3 Scripts
Amm introduces some special import
syntax that the package name starts with $
, including $file
, $exec
, and $ivy
etc.
3.1 Import Scripts
To use block code, put multiple lines in a pair of curly braces {...}
. To evaluate a code block, use double curly braces {{...}}
.
Methods to import scripts
import $file.filePath
: load a script file.- Use
^
for a parent folder. - Use
import $file.filePath, filePath._
to load a script and its contents. - Rename
import $file.{Foo => Bar}
- Import mutiple scripts:
import $file.{Foo, Bar}
Import $exec.filePath
: import a script and dump its defintions
3.2 Import Libraries
To import Ivy libraries, usses import $ivy.id
. The artifact is specified inside a pair of backticks.
|
|
The ::
appends Scala major.minor
version.
The :::
appends the precision version of major.minor.pathc
and cross-published suffixes.
The :
is used for full name, mostly Java libraries.
To load a compiler plugin, use import $plugin.$ivy.id
. It doesn’t affect the run-time classpath.
Some scripts/libraries depend on runtime variables and need multi-stage importing. Use interp.load.module(script)
or interp.load.ivy(id)
to load, then import
them.
3.3 Script Arguments
Define a main
method to take commandline argument. The top-lvel definitions execute first, then the main
method arguments.
Passing arugment by name using --
, for example: --arg1 3
.
It supports vararg*
.
For mutlitple main
methods, using @main
decorator.
Use @doc("message")
to document methods.
3.4 Bundled Libraries
Amm comes with Requests-scala
for making HTTP calls, uPickle
to deal with JSON data.
|
|
3.5 Script Predef and Run Script
The ~/.ammonite/predefScript.sc.
is loaded before run a script form command line. You can link it with ~/.ammonite/predef.sc.
if they have the same content.
Use amm scriptPath.sc
to run a script file. To make it runnable from shell, add #!/usr/bin/env amm
to the script file beginning and make it executable.
Use --watch
/-w
to re-run a script if it changes.
Use --predef
/-p
to run a script and open an interactive REPL to debug script.
3.6 Execution Model
Amm has a bytecode cache in ~/.ammonite/cache
for compiled scripts. The script is wrapped in a package/object
wrapper where the pakcage
is the scirpt file path.
4 Ammonite Ops
4.1 Operations
Ammonite-Ops
is a library that provides common OS operations in Scala. After import ammonite.ops._
, you can use operations such as:
ls! path
andls.iter! path
: returnVector[Path]
orIterator[Path]
ls.rec! path
andls.rec.iter! path
: run recursivelyread! path
,read.lines! path
,read.bytes! path
write(path, content)
,write.over(path, content)
to overwrite an exsting filerm! path
: the same as recursiverm -rf
mv(src, dest)
cp(src, dest)
: the same as reursivecp -r src dest
exists! path
stat! path
ln(src, dest)
kill(9)! processId
4.2 File and Resource Paths
Amm has three path types:
Path
: an absolute pathRelPath
: a relative pathFilePath
: aBasePath
that could bePath
orRelPath
A path can formed by a Path
and strings/symbols seperated by a slash. For example pwd/
folder/“folder 2”/“file.txt” or pwd/up
. the up
means one level up. Predefiend path values are pwd
(a static value that is the folder where amm
runs), root
, home
, wd
(dynamic values changes with cd!
command).
Use 'symbol
or "string"
for path segments.
Relative path are strings/symbols not started with a /
and are seperated by slashes. A segement could be up
or ..
. Use path1 relativeTo path2
to find the relative path between them. Use Path(pathStr, base)
to use pathStr
if it is an absolute string, otherwise, use the base
path followed by pathStr
. The base
must be a value of Path
.
The resource
has a type of os.ResourcePath
, it is the result of Thread.currentThread().getContextClassLoader
appended with a /
. You can only read
from a resource path.
4.3 Extensions
Amm provides the following extensions:
things | f
:things map f
things || f
:things flatMap f
things |? f
:things filter f
things |& f
:things reduce f
things |! f
:things foreach f
f! thing
orthing |> f
:f(thing)
4.4 Subprocess
To run a system command in a subprocess, use %cmd
. It throws an InteractiveShelloutException
if the retur code is non-zero. It is useful to run another program interactively using the current teminal. For example %vim
or %python
.
Use %%('cmd, "arg1", ,,,)
for programmatic usage to return CommandResult
. The shell command can be a path such as root/'bin/'bash
. The CommandResult
has the following fields:
exitCode
field for exit codeout
field for standard output. Theout
has methods.string
,lines
and.bytes
.err
field for stand error
Yo can use symbol syntax as 'word
for single word and use dobule quotes for mutiple words string such as "folder1/fodler2"
.
You can pass any environment variables as arguments in %
or %%
. For example: %%('bash, "-c", "echo \"Hello$ENV_ARG\"", ENV_ARG=12)
Use backticks to execute commands that aren’t valid Scala identifier. For example:
|
|
5 Ammonite Shell
cd! path
: change working directory
wd
: the current working directory
The Amm shell uses Scala and support any JVM code or libraries.