Open Source Consultant, Software Developer and System Administrator

If you are interrested in hiring a consultant for the effective use of open source software on an enterprise grade, take a look around in the About section to see, what I have to offer.

Blog and snippets

Various snippets or code parts I found useful, so I keep them here for reference.

Run Cargo via Docker for local development

My setup to run cargo via Docker as the current user. Put that in your Makefile or as shell alias.

docker run --rm -ti \                            # run, remove afterwards, use terminal
        -w /src -v `pwd`:/src \                  # map cwd to /src and make it the WORKDIR
        --user `id -u`:`id -g` -e USER=`id -u` \ # map to current user
        -e CARGO_HOME=/src/.cargo_registry \     # change the CARGO_HOME into the src
        rust:1.38 \                              # image:version
        cargo

(Note: don't add the comments, the shell won't kike it)

Figwheel with Vim-Fireplace 2.0

With recent changes in Cider and the new Vim-Fireplace 2.0 release, let's update the setup for it.

In a project created by e.g. lein new figwheel hello-world, add the new setup for Ciders Piggieback:

:profiles {:dev {:dependencies [[cider/piggieback "0.4.1"]]
                 :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}}}

Merge this settings with existing code from the template. Note, that both the group of the artifact and the namespace for Piggieback changed.

With the template you can not open Vim, start the REPL, and run (fig-start).

Now with Vim-Fireplace 2.0 to work via Piggieback, you call:

:CljEval (cider.piggieback/cljs-repl (figwheel-sidecar.repl-api/repl-env))

Trying out PetitParser for Java

Inspired by this SO question I wanted to find a nice tool for Groovy/Java to write a parser in the hope to find something, that is as nice to start with as Instaparse. So far I am quite pleased with PetitParser.

@Grab("com.github.petitparser:petitparser-core:2.2.0")
import org.petitparser.tools.GrammarDefinition
import org.petitparser.tools.GrammarParser
import org.petitparser.parser.primitive.CharacterParser as CP
import org.petitparser.parser.primitive.StringParser as SP
import org.petitparser.utils.Functions as F

class SearchQueryGrammerDefinition extends GrammarDefinition {
    SearchQueryGrammerDefinition() {
        define("start",
                ref("term")
                .separatedBy(ref("operation")))
        define("operation",
                SP.ofIgnoringCase("and")
                .or(SP.ofIgnoringCase("or"))
                .trim()
                .map{ it.toLowerCase() })
        define("term",
                ref("keyword-term")
                .or(ref("simple-term")))
        define("simple-term",
                ref("quoted-or-unquoted-term"))
        define("quoted-or-unquoted-term",
                ref("unquoted-term")
                .or(ref("quoted-term")))
        define("keyword-term",
                ref("keyword")
                .seq(CP.of(":" as Character))
                .seq(ref("quoted-or-unquoted-term")))
        define("unquoted-term",
                CP.anyOf(' "').neg().plus().flatten().trim())
        define("quoted-term",
                CP.anyOf('"')
                .seq(SP.of('\\"').or(CP.pattern('^"')).star().flatten())
                .seq(CP.anyOf('"'))
                .map{ it[1].replace('\\"', '"') })
        define("keyword",
                CP.letter()
                .seq(CP.word())
                .star()
                .flatten())
    }

    /** Helper for `def`, which is a keyword in groovy */
    void define(s, p) { super.def(s,p) }
}

class SearchQueryParserDefinition extends SearchQueryGrammerDefinition {
    SearchQueryParserDefinition() {
        action("keyword-term", { [(it[0]): it[2]] })
        action("simple-term", { ['*': it] })
    }
}

class SearchQueryParser extends GrammarParser {
    SearchQueryParser() {
        super(new SearchQueryParserDefinition())
    }
}

println(new SearchQueryParser().parse('metabolism and heart and TAXONOMY:40674 AND curation:"Non \\"curated\\"" and cancer'))
// => Success[1:82]: [{*=metabolism}, and, {*=heart}, and, {TAXONOMY=40674}, and, {curation=Non "curated"}, and, {*=cancer}]

Fennel Vim setup

Since this gets asked in #fennel from time to time, here is my Vim setup for Fennel:

call plug#begin('~/.vim/plugged')
" ...
Plug 'guns/vim-sexp', {'for': ['fennel']}
Plug 'tpope/vim-sexp-mappings-for-regular-people', {'for': ['fennel']}
Plug 'kovisoft/paredit', {'for': ['fennel']}
Plug 'bakpakin/fennel.vim', {'for': 'fennel'}
" ...
call plug#end()

let g:sexp_enable_insert_mode_mappings = 0
let g:sexp_filetypes = 'fennel'

See https://gist.github.com/christoph-frick/ddba9ea1bdccef1972cd4cec9b453a8b