Journal de Chaource's Journal
 
[Most Recent Entries] [Calendar View]

Tuesday, August 9th, 2016

    Time Event
    12:53a
    Finally, we can do Unix shell programming in Scala
    Li Haoyi, of Scala.js fame, has succeeded in fulfilling the dream of replacing Bash / Perl / Awk / Python with a modern programming language.

    http://www.lihaoyi.com/Ammonite

    Top features:

    • Everything in this shell is compiled to JVM, then run
    • Everything is statically type-checked - including command flags, file paths, pieces of paths, or output of "ls"
    • Autocomplete and syntax highlighting: both for file paths and for Scala values
    • Since this is just a JAR library and a class loader, we get the full power of the Scala programming language, not just a subset
    • We can use any Scala or Java libraries from Maven repositories; they will be downloaded and locally cached
    • We can write "Ammonite/Scala scripts" and import them into your shell or run as standalone applications
    • The Ammonite/Scala shell can be embedded in third-party applications or used as a remote debug console over ssh


    I really would like to forget bash and start using amm. I am going to give it a serious try!

    First steps

    0. Install:
    mkdir ~/.ammonite && curl -L -o ~/.ammonite/predef.sc https://git.io/vo4wx
    sudo curl -L -o /usr/local/bin/amm https://git.io/vKSOR && sudo chmod +x /usr/local/bin/amm
    

    Run the Ammonite/Scala shell:
    amm
    


    1. There are three kinds of things we can do in Amm:

    - write plain Scala code; no need to write boilerplate "objects" to wrap plain values or functions

    import scala.util.Try
    val x = Try( 1/0 )
    def f(x:Int) = x+1

    - run a built-in shell command: ls, cd, ...

    - run an external command: git status, ...

    2. Filesystem paths and the names of external commands must be typed. Special syntax is used for these things; here are some basic examples.

    The following are equivalent:

    cd (Path("/private/tmp"))
    cd! Path("/private/tmp")
    cd! Path("private/tmp", root)
    cd! root/"private"/"tmp"
    cd! root/'private/'tmp
    cd! Path("tmp", root/'private)

    Return to the user's $HOME directory:

    cd! Path(sys.env("HOME"))

    The following are equivalent:

    cd! up
    cd! Path("..", wd)

    Similar syntax applies to other built-in commands, such as ls, rm, mkdir, cp, mv, read, write.

    Note that wd and cwd are Path values, not commands.

    For external commands, the % or %% prefix needs to be used. Command arguments can be symbols or strings.

    The following are equivalent:
    %git("status")
    %git('status)
    %git "status"
    %git 'status

    3. There are some special helpers for going over files in directories, reading lines from files, etc.

    4. Output of one expression can be "piped" into another (this is just syntactic sugar: | for map, |? for filter, || for flatMap, etc.)

    List all files in current directory, filter pathnames by regular expression using built-in `grep`:
    ls! wd |? grep! "li.*e".r
    


    This command will go over all files in current directory with .csv extension; for each file, read all lines as strings:
    @ ls! wd |? (_.ext == "csv") | read.lines
    res80: Seq[Vector[String]] = List(
      Vector(
        """
    ...
    


    (The result was truncated in the example above.)

    Note that we got a data structure Seq[Vector[String]], corresponding to the sequence of all files, and for each file, a Vector of its lines. Now we can use the full power of Scala collections to transform this data structure.

    So far this sounds very promising! I'm going to try living in `amm` instead of `bash` and start writing `amm` shell scripts.

    << Previous Day 2016/08/09
    [Calendar]
    Next Day >>

Journal de Chaource   About LJ.Rossia.org