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.

Search Maven artifacts with Babashka

Since Maven Central changed the search I had to fix my helper script. Time to try out Babashka.

#!/usr/bin/env bb
(require '[cheshire.core :as json])

(defn artifact [{:keys [g a v latestVersion]}]
  (str g ":" a ":" (or v latestVersion)))

(defn query [q]
  (let [query-params {:start 0 :rows 50}]
    (if (str/includes? q ":")
      (let [[g a] (str/split q #":" 2)]
        (assoc query-params 
           :q (str "g:" g " AND " "a:" a)
               :core "gav"))
      (assoc query-params :q q))))

(defn request [q]
  (-> (org.httpkit.client/get
        "https://search.maven.org/solrsearch/select"
        {:content-type "application/json"
         :query-params (query q)})
      deref
      :body
      (json/parse-string true)
      :response
      :docs))

(assert (= 1 (count *command-line-args*)))

(->>
  *command-line-args*
  first
  request
  (map artifact)
  (run! prn))

Using gocr and flameshot to get text from screenshots

From time to time I have the need to get text from an image, when someone shares a screen-shot, but not the URL in it or when I want to copy code from a stopped youtube video. So ideally I want to select a region of my screen and turn that into text.

First install gocr and flameshot. Then create a script, that runs gocr and opens the resulting text (in my case I want to open a terminal with vim). E.g. ~/bin/ocr:

#!/bin/sh
rxvt -e sh -c "gocr -i \"$1\" | vim -"

Then create a "desktop" entry for flameshot to pick up. ~/.local/share/applications/ocr.desktop:

[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Exec=.../bin/ocr %f
Name=OCR
Categories=Graphics;

(Note, that the path there is absolute, or you have to figure out, what works for you... I couldn't be bothered to look into this)

Then start flameshot gui (I have that on my Print Screen-key), select the region to OCR, press CTRL-o (or click the button to open the screenshot with an application), then pick the OCR-Application from the desktop entry, which then opens the text.

ES6 object property shorthand with Groovy

Recently someone asked on StackOverflow whether there is an equivalent in Groovy for the JavaScript shorthand for properties of the object literal. It basically looks like this:

const a = 'foo';
const b = 42;
const c = {};
const obj = { a, b, c };
// the same as: const obj = { a: a, b: b, c: c };

While this feature is not supported in Groovy directly, it's easy to reproduce using a very underused feature: a macro. Macros are supported in Groovy since 2.5.

Create new file to contain all macros. E.g. Macros.groovy:

import org.codehaus.groovy.ast.tools.GeneralUtils
import org.codehaus.groovy.macro.runtime.*
import org.codehaus.groovy.ast.expr.*
import org.codehaus.groovy.syntax.*

class Macros {
    @Macro
    static Expression mapOf(MacroContext ctx, final Expression... exps) {
        return new MapExpression(
            exps.collect{
                new MapEntryExpression(GeneralUtils.constX(it.getText()), it)
            }
        )
    }
}

Then compile this file (this is important to do first, or else Groovy gets confused when something references the class, but it's not there):

# groovyc Macros.groovy

Next make the macro known. There must a file META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule in the classpath containing the following lines to make Macros from above work:

moduleName=Some name
moduleVersion=0.1-SNAPSHOT
extensionClasses=Macros

And then finally try it out:

def labels=["a", "b"]
def values=[1, 2]
println(
    [labels, values]
        .transpose()
        .collect{ label, value -> 
            mapOf(label,value) 
        }
)

And run it:

# groovy test.groovy
[[label:a, value:1], [label:b, value:2]]