…to use the original Webster dictionary under linux.

Today I read a brilliant article about English dictionaries and how to use them. It was inspiring in its colorfulness use of words and very well written, it really left me with the feeling, I need to write more. It also had an appendix about how to set up an online version of it. But it uses MacOS of course, so I had to check what works on Linux, to get a dictionary running as well. Here it is:

On Linux there have been multiple Dictionaries out there. Some were discontinued or abandoned after legal conflicts, some were left because of better alternatives. So it looks like most people settled to use GoldenDict as the standard dictionary app to use.

So you can install it via apt like so:

sudo apt-get install goldendict

Since that sparking article really left me with the desire to use the Webster dictionary from 1913, we have to download this as well. Luckily in the appendix of that article James provides an Download link to his MacOS App which contains what we need. This is an archive containing a tar.bz2-archive within the dictionary folder which we extract somewhere, our GoldenDict app can use it.

The last thing we have to do is teaching GoldenDict to use that specific dictionary. We can do that through the menu entry Edit -> Dictionary, hitting add, and choosing the directory of our previously extracted dictionary.

E voilá, if we search now within GoldenDict we get those really great definitions that really are interesting to read and explain so colorful, that a word really means.

…that you can and should use localeCompare to sort strings alphabetically.

Imagine you want to sort some German strings alphabetically. (Take this for example:)

const countries = [
  'Deutschland',
  'Ägypten',
  'Norwegen',
  'Albanien'
]

If you would sort them using Array.sort() method, you will get this result, which might not be what you want:

countries.sort()
// results in: ['Albanien', 'Deutschland', 'Norwegen', 'Ägypten']

But if you the .localeCompare method that is defined on any instance of String you can sort the string with a more locale aware algorithm. Try this:

countries.sort((a, b) => a.localeCompare(b))
// results in: ['Ägypten', 'Albanien', 'Deutschland', 'Norwegen']

The .localeCompare method takes even more options (in most browsers), to adjust its comparing algorithm. You can read all about it on the fabulous MDN documentation about it.

…that you can use a .gemrc file to not install documentation.

Everyone loves [Rubygems][Rubygems]. And you probably have heard of the --no-rdoc & --no-ri flags, right? The flags that fasten up your gem installation since you do not have to generate the RDoc and ri documentation? Ah, I see you also have heard about it. Well, I figured those flags are now deprecated. Time to replace them with new stuff. It is called --no-document now.

Best thing to add it to your ~/.gemrc file (and create one if you don’t have one yet). Create a ~/.gemrc file like this:

gem: --no-document

Now you don’t have to worry about this anymore.

…about 'set -o pipefail' in bash scripts.

If you use set -e to let your bash script fail when a command fails and you have some pipes within your script, you might also want to run set -o pipefail as well, since it allows bash to also discover that pipes fail.

See here for more details.

…that there is the only flag for rubocop.

Rubocop is a great tool to keep you code consistent, sane and informs you about some performance pitfalls.

Lately, I wanted to slowly add rubocop to an existing codebase. Rubocop has the -a parameter – which is short for --auto-correct – which corrects all the offenses. Having a thousand offenses and trying to auto fix them all, will generate quite the Pull Request. But there is also the --only parameter that allows you to check (and fix) only some or one type of offense.

So a neat way to add all the missing magic frozen_string_literal: true comments everywhere, might look like:

rubocop --only Style/FrozenStringLiteralComment -a

…how to add functionality to existing rake tasks.

Sometimes you just want to add some extra functionality to some existing rake task.

So image having these rake tasks defined:

namespace :do do
  task :foo do
    puts "foo"
  end

  task :after do
    puts "after"
  end

  task :before do
    puts "before"
  end
end

We can prepend the do:before task to the do:foo task like this:

Rake::Task["do:foo"].enhance ["do:before"]

# output would be:
# before
# foo

And let something run after a task like this:

Rake::Task["do:foo"].enhance do
  Rake::Task["do:after"].invoke
end

# output would be:
# foo
# after

Really neat if you want to add some more stuff, to existing rails tasks for example. I got that idea from here, btw.

…React v16.8 introduces hooks to counter class awkwardness.

A neat little feature which comes with version 16.8 of React are hooks.

What are Hooks?

Hooks allow you to add state to functional components, or make side effects work in those. Or even bundle up your own stateful logic into an own hook method, that makes the logic be reusable without having to leak the state all over the place.

I could reproduce the highlights of hooks here, but the React people are explaining it well enough. Just [read their overview][hooks-overview].

…where to put app specific configs and files.

…and the answer is not necessarily in the users home directory.

Imagine you write a desktop app and you need to persist some configuration the user has chosen. Where do you put those files? My default answer – as I have been a developer on a Mac – would have been ~/Library/Application Support/com.example.AwesomeApp/. But since I am working with Linux now, and those people have different ideas where to put stuff and like to have total control, I would have said something like: “In a dotfile maybe?”

But there seems to be a specification for handling this – of course, there is. So the short answer is, if there is the environment variable $XDG_CONFIG_HOME defined, use that value, if not, default to ~/.config for config files. And for other app-specific files use $XDG_DATA_HOME or ~/.local/share

So if you build a desktop app, you know now, where to put stuff.

…dmenu is a great way to optimize cli scripting.

Dmenu is a simple but elegant tool from the suckless community. What it does is simply generating a dynamic menu – hence the name – using the input (text file, or piped) where every line is one menu item and let you choose from those options via keyboard cursor keys or typing the whole or partial words and in the end returning the result to stdout.

So this would simply generate a menu with two options (and a question):

$ echo "yes\nno" | dmenu -p "Are you ok?"
yes

Why is that so need? Well. I had two scripts fixing the screen setup for me, one called screenhome and the other screenwork. While that works, typing it out is annoying if you change between both setups a lot – since auto completion will suggest the last used one. Plus that are two scripts. With dmenu I could simply but them in one little script. It looks something like that:

#!/bin/bash
# This script is for fixing my screen setup.

choices="home\nwork"

chosen=$(echo -e "$choices" | dmenu -i)

case "$chosen" in
    home)
        xrandr --output HDMI-1 --above eDP-1 &&
  	    xfconf-query -c xfce4-panel -p /panels/panel-1/length -s 100 ;;
    work)
        xrandr --output HDMI-1 --above eDP-1 &&
  	    xfconf-query -c xfce4-panel -p /panels/panel-1/length -s 75
esac

I know, fixing the screen setup like this might not be the most elegant solution there could be, but that’s the one I found so far. But that is just for illustrating what you can do with it.

It can be installed by all regular means or build by hand – which is needed when you want to change the configuration like colors and stuff, since they are set on compile time (see example here).

…bundler can be used without a gemfile.

I didn’t know that up until now, but obviously, you can inline bundler within your ruby scripts. No need to have a dedicated Gemfile or to call bundler before calling your script. Just do:

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'rest-client'
end

puts RestClient.get('https://news.ycombinator.com/')

You can see the source on their GitHub repo. This becomes espescially interesting not only for small scripts, but also to have small executable files, that behave like a regular executable.

A small example

Image being able to do this from your command line:

$ weather berlin
Today it is -2.51°C in Berlin with few clouds.

Easily done:

#!/usr/bin/env ruby
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'json'
  gem 'rest-client'
end

API_KEY = 'XXX' # put your api key here
city = ARGV.count > 0 ? ARGV.first : 'Hamburg,de'

body = RestClient.get("https://api.openweathermap.org/data/2.5/weather?q=#{city}&appid=#{API_KEY}&units=metric")

response = JSON.parse(body)

temp = response['main']['temp']
city = response['name']
weather = response['weather'][0]['description']

puts "Today it is #{temp}°C in #{city} with #{weather}."

Put this into a weather file, make it exectuable chmod +x weather and then put it into your PATH variable.

…not all jekyll plugins do work with GitHub pages

You learn through experience. First do something and see it does not work and then throw it away – or you read along here, to avoid configuring jekyll plugins, that simply are not allowed to be run within GitHub pages.

You can find all allowed plugins within the Pages gem. To be precise, you will find the whitelist of allowed Jekyll plugins here: See all GitHub Pages approved jekyll plugins.

It appears to be a lot of work for the GitHub security team, to add more gems here, since they all have to be checked on every version bump. So keep yourself happy and just restrict yourself to those plugins, if you want to host your page on GitHub pages.

…how to make canonical urls pretty in jekyll

Jekyll is a great static site generator, with a great ecosystem of plugins to create almost all you need. But since every plugin is handling things a wee bit different, sometimes the results are not consistent throughout the page.

Since we always want to render nice canonical URLs with no unnecessary index.html files, I figured having a nice liquid plugin is the best choice, since the current Jekyll pagination plugin is always putting an index.html at the end with no (apparent) way to strip it away.

But since there are plugins for almost every usecase, I found this nice liquid filter plugin for beautifying URLs. Simply copy that code into the _plugins dir and use it like this:

<meta property="og:url" content="https://til.jaz-lounge.com/jekyll/jekyll-beautify-urls" />

…there are nice names for Phoenix conn status codes

In ruby there is this neat way to define response statuses, something like:

render status: :not_found

And there is something (really) similar as well within the Plug.Conn elixir package.

So in Phoenix you can do this two nice things:

send_resp(conn, 404, "Nothing found!")
send_resp(conn, :not_found, "Nothing found!")

…how to easily react on some keys within event handlers

Of course, you can do the following thing in vue.js to determine if someone hit enter on your input:

<input @keyup="handleKeyUp" />

You most likely know the concept of modifiers in vue.js as well, right? To always call event.preventDefault() on an event handler, you can do

<input @keyup.prevent="handleKeyUp" />

Did you also know, that for common command keys there are also modifiers that call the handler only for given key?

<!-- this will be only called when enter key is released -->
<input @keyup.enter="handleEnterKey" />

See the list of modifiers here. Since v2.5.0 it got even better and you can react on all key names defined in KeyboardEvent.key if you kebap-case them. Like:

<!-- this will be only called when enter key is released -->
<input @keyup.page-down="handlePageDownKey" />

…how to use virtual environments in python 3

Virtual environments are a great way to not clutter your global namespace with all the python packages you might only use in one project. Also if you use the same packages but in different versions in multiple projects.

First install it (here is the ubuntu-like version):

sudo apt install python3-pip python3.venv

Then you can create a virtual env for your project using the venv module in python3. So in your project path do:

python3 -m venv .env # creates a folder .env where all the environment is stored

Whenever you are in your project folder you can activate this environment and everything you install and required goes and comes from that active environment.

source .env/bin/activate # call this in your project-path

This will put a deactivate command to your path, that you can call, when you want to deactivate that environment again.

deactivate

I like to put the .env files into my project folders, since they are mostly closely related, but theoretically you don’t have to do this. You could put all the different environments into a (user-)global path like ~/.venvs/ and activate those when you need them:

python -m venv ~/.venv/my-env1
source ~/.venv/my-env1/bin/activate

…how to reload modules in iex

You may know about how to load files into your iex. Right?

c "my-module.exs"

If you actively work on it, and want to reload it, that you can also do this:

r MyModule

Also note that, not according to the docs, the file where this module is defined will recompiled, but only in memory. So maybe some typespecs and doc may then be outdated, since they are never loaded into memory.

…there are awesome man pages within elixir iex

One awesome discovery for me was, that you can browse the docs of commands directly from within the iex console.

Try it, within iex:

h String.Split
h Phoenix # try this with iex -S mix within a phoenix project of course

…how to call an elixir method dynamically

If you have the need to dynamically call a method in elixir, of course there is a method for that, which is called apply (apply/2, apply/3), which optionally takes a module as first parameter, and an atom as second, and a list of arguments a third.

Here are some neat examples:

apply(fn x -> x * 2 end, [2])
defmodule Test do
  def one, do: IO.puts("one")
  def two, do: IO.puts("two")
end

[:one, :two] |> Enum.each(fn method -> apply(Test, method, []) end)