code and command snippets

last edit:

out-of-context lines of python

if __name__ == "__main__":
    l = ["a", "b", "c"]
    for (i, v) in enumerate(l): print(i, v)
    random.randint(a, b) # returns N such that a <= N <= b
import fileinput
for line in fileinput.input():

import sys
# -X int_max_str_digits

def median(*args): return sorted(args)[len(args)//2]
function for finding the index of all occurrences in a (byte)­string
def find_all(what, fromwhere):
  last = -1
  idxs = []
  while last < len(fromwhere):
    pos = fromwhere.find(what, last+1)
    if pos > -1:
      last = pos
  return idxs

perl oneliners

read in whitespace-separated decimal integers on stdin, output them in hexadecimal:
perl -nE "foreach (split q( )) { printf(qq(%x\n), \$_); }"

read in lines, output their contents four at a time, separated by a comma and space:
perl -E "\$,=q(, ); my @a; while (<STDIN>) { chomp; push @a, \$_; if (scalar @a ==4) { say @a; @a=(); } } say @a;"

(the value of the $, variable is undefined initially, so for even just a space you must set its value; otherwise the output will just be smushed all together. if you don't like perl -E and the say function, just use print and set the value of $\ to "\n".)

manually writing a file with given bytes, using xxd

xxd -p -r > outfile

Using -p for plain or postscript format and -r for reverse. Data can be fed to it with whitespace between (or even within) hex bytes, and either uppercase or lowercase:

3C3031323E 20 3A0a 787864 202d70202D720A d 09 dc 3 A 9 D 185 C 491 cf 856 dcf 81 EFBC 8 e 0 a
echo "c3a5 c3a4 c3b6 c3bc 0a" | xxd -p -r

An example where you pass terminal escape codes to make everything bold on red: echo "1b5b313b34316d" | xxd -p -r ; echo "undo with 1b5b306d"

report whether two files are different or identical

diff -q -s file1 file2

stat(1): file information, without having to use ls

print out file size, and only file size: stat -c %s [filename]

print out file size and file name: stat -c "%s %N" [filename]

print out first file size, then human-readable modification time: stat -c "%s %y" [filename] (use "%Y" for unix time)

print out access rights in both octal and human-readable form, then username and group name of owner: stat -c "%a %A %U %G" [filename]

approximate ls output: stat --printf="%A %h %U %G %s\t%y\t%N" [filename]

tweaking gnome without gnome-tweaks

gsettings list-recursively | sort | less
gsettings list-keys org.gnome.desktop.interface | sort
gsettings get attach-modal-dialogs
# etc

gsettings set org.gnome.desktop.interface clock-show-seconds true
gsettings set org.gnome.desktop.calendar show-weekdate true
gsettings set org.gnome.desktop.wm.preferences button-layout ':minimize,maximize,close'
gsettings set attach-modal-dialogs false
gsettings set max-screencast-length 180

making gnome files not have such an obnoxiously wide sidebar and removing that "starred" sidebar entry (from this stack­overflow):

$ cd ~/.config/nautilus/
$ mkdir ui # if it doesn't exist already
$ cd ui
$ gresource extract /bin/nautilus /org/gnome/nautilus/ui/nautilus-window.ui > nautilus-window.ui
# now edit that file (it's xml):
# find the line with "show-starred-location" and set it false
# the line below had "width-request" 240; i set it to 160
# now we need to make a user-specific systemd service to enable it
$ cd ~/.config
$ mkdir --parents systemd/user/dbus.service.d/ ; cd systemd/user/dbus.service.d
$ vim enviroment.conf
# its contents:
# then reboot, or at least relog

.desktop files

[Desktop Entry]
Comment=Program, v.1.8.1

GNOME 3 monitors ~/.local/share/applications/ for new .desktop files; you'll probably want to copy your .desktop file there. The commands desktop-file-validate thing.desktop and desktop-file-install --dir=DIR thing.desktop exist, but I'm not sure they're necessary.

Working .desktop file for Discord for Fedora, because Discord's own doesn't work; put it in ~/.local/share/applications/discord.desktop, and Discord's files into /usr/share/Discord:

[Desktop Entry]
Comment=All-in-one voice and text chat for gamers that's free, secure, and works on both your desktop and phone.
GenericName=Internet Messenger

screenshot from the terminal with imagemagick

import filename (creates it as a postscript file, which is readable text (albeit with pixel data written out), actually pretty interesting)

import filename.png (also try .jpg etcetera)

if import doesn't work as is, try magick import .... doc.

add text to the bottom left corner of an image with imagemagick

convert input.jpg -gravity Southwest -fill "#e37226" -font Unifont -weight medium -pointsize 16 -annotate 0 "the text" -quality 90 output.jpg

(the "0" after "-annotate" is the angle the text is printed at. see also the annotating examples on ImageMagick's site and the command line options.)

doing this for every file listed in a text file: for file in `cat filelist-plain` ; do convert $file -gravity Southwest -fill "#e37226" -font Unifont -weight medium -pointsize 16 -annotate 0 "$file" -quality 90 annotated/$file ; done

ssl cert/cert-sign-request viewing commands

viewing a request (csr): openssl req -in thing.csr -noout -text

viewing a public certificate: openssl x509 -in thing.crt -noout -text

viewing a private key: openssl rsa -in thing.crt -noout -text

viewing certificates etc. in an smtp connection: openssl s_client -connect -showcerts -starttls smtp

vowel reduction for linguistic fun

perl -n -E 's/[aeiouy]/e/g;s/[AEIOUY]/E/;s/ï/y/;s/Ï/Y/;print' < input — turn english vowel letters (including Y) into E; if the input text file is edited beforehand and has its consonantal Y's replaced with Ï and ï then those will get turned back to y.

perl -n -E 's/ä|ö/e/g;s/Ä|Ö/E/g;s/[eiy]/e/g;s/[EIY]/E/g;s/[aou]/o/g;s/[AOU]/O/g;print' < input — a variant for finnish that preserves vowel frontness and backness.

import fileinput
cfq = {}
for l in fileinput.input():
    for c in l:
        if c not in cfq:
            cfq[c] = 1
            cfq[c] += 1
for (k, f) in map(lambda k: (k, cfq[k]), sorted(cfq.keys())):
    print(repr(k), f)

gcc's unsigned integer division magic

dividing by a constant d is implemented as multiplying by a big number that is the inverse of the constant multiplied by a big power of two (2k), then dividing the extra power of two out with a right-shift. (explanatory source.) if d is a power of two, this can just be a straight right-shift. for non-powers of 2, k should be word-width+⌈log₂ d⌉ so that multiplication with every integer of word-width works

n d = n d × 2 k 2 k = 2 k d × n 2 k and

import sys
def out(bb):
out(b"Under the line of hyphens will be every byte,\n")
out(b"arranged 32 to a line, except that the first\n")
out(b"line's tenth character (0x0A) will be 0x20.\n")
out(bytes.fromhex("00010203 04050607 0809200B 0C0D0E0F"))
out(bytes(range(0x10, 0x20)) + b"\n")
out(bytes(range(0x20, 0x40)) + b"\n")
out(bytes(range(0x40, 0x60)) + b"\n")
out(bytes(range(0x60, 0x80)) + b"\n")
out(bytes(range(0x80, 0xA0)) + b"\n")
out(bytes(range(0xA0, 0xC0)) + b"\n")
out(bytes(range(0xC0, 0xE0)) + b"\n")
out(bytes(range(0xE0, 0x100)) + b"\n")
import sys
def out(bb):
out(b"After the next line will be every byte from 0x80 to 0xFF,\n")
out(b"as two lines of 64 bytes.--------------------------------\n")
out(bytes(range(0x80, 0xC0)) + b"\n")
out(bytes(range(0xC0, 0x100)) + b"\n")

forth: ackermann 3-variable φ function

: 3dup ( n1 n2 n3 - n1 n2 n3 n1 n2 n3 ) { a b c } a b c a b c ;

: ackermann_phi ( n n n - n ) ( m n p ) dup 0 = if drop + else swap dup 0 = if drop dup 1 = if drop drop 0 else 2 = if drop 1 endif endif else swap 3dup swap 1 - swap recurse rot drop swap 1 - recurse endif endif ;

python: playing with tracery

Using this python port. Some classical context-free grammars from comp-sci classes.

import tracery
rules = {
    'original': ['#palindrome#', '#parens#', '#anbn#'],
    # palindromes are length-limited but others can in principle recurse forever
    'palindrome': ['#palin1#', '#palin2#', '#palin3#', '#palin4#'],
    'palin1': ['0#palin2#0', '1#palin2#1'],
    'palin2': ['0#palin3#0', '1#palin3#1'],
    'palin3': ['0#palin4#0', '1#palin4#1'],
    'palin4': ['00', '11', '0', '1'],
    'parens': ['#paren1#', '#paren2#', '#paren3#', '#paren4#'],
    'paren1': ['#paren2##paren2#', '(#paren2#)', '[#paren2#]'],
    'paren2': ['#paren3##paren3#', '(#paren3#)', '[#paren3#]'],
    'paren3': ['#paren4##paren4#', '(#paren4#)', '[#paren4#]'],
    'paren4': ['a', 'b', '[#parens#]', '(#parens#)'],  
    'anbn': ['#a4b4#', '#a3b3#', '#a2b2#', '#a1b1#'],
    'a4b4': '<#a3b3#>',
    'a3b3': '<#a2b2#>',
    'a2b2': '<#a1b1#>',
    'a1b1': ['<>', '< #anbn# >']
grammar = tracery.Grammar(rules)

chroot rescue

/boot = 7a52...
/boot/efi = 5be9...
ls /dev/disk/by-uuid -l

mkdir /mnt/sysimage
mount /dev/mapper/vg-root /mnt/sysimage
mount /dev/sda5 /mnt/sysimage/boot
mount /dev/sda4 /mnt/sysimage/boot/efi
chroot /mnt/sysimage
mount -t proc proc /proc # (if warned to do so)

python: random hex colour triplet

from random import randint
print(f"{randint(0, 256**3):06x}")

strip whitespace from beginnings of lines

sed -Ee 's/^( +)//'


force login with password: ssh -o PreferredAuthentications=password ...

After upgrading to Fedora 33 some ssh key logins don't work any more. This is because Fedora 33 now uses a stricter form of something-or-other. The correct way to fix this is to have the other side update its ssh server. The easy way to correct this is to go to your ~/.ssh/config, then, under a Host line, add the line:

find commands

I find the syntax of find(1) to be really hard to remember.

Explore the current directory and all its subdirectories, and print out a relative path to a filename matching a given case-insensitive glob pattern: find . -iname *.css -print


exit status of previous command is in the variable $?

for varname in word1 word2 ... wordN ; do cmd1 $varname; cmd2 $varname; ... done


Release mouse: CTRL+F10

minecraft: old version of player_graves

Destroy lingering particles: /kill @e[type=minecraft:area_effect_cloud]

Destroy old graves: /execute at @e[type=minecraft:armor_stand] run function player_graves:admin/claim_grave

Enable the datapack in the first place to be able to execute player_graves commands: /datapack enable [use tab autocomplete] (our server used file/player graves

/function player_graves:admin/claim_grave

some particular javascript

async function subscribe() {
  let x = document.getElementsByClassName("js-update-support-count")[0];
    while(true) {
    await sleep(30000);;

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));


DIMACS file format

mandatory prefix before the clauses: p cnf [num-variables] [num-clauses]

WoW Classic

Macro to print the amount of XP you still have left until next level, and the approximate number of mobs you need to kill (change the variable xpPerKill accordingly): /run xpPerKill = 650; maxXP = UnitXPMax("player"); left = maxXP - UnitXP("player"); print(string.format("XP left: %i, %.2f %%", left, 100*left/maxXP)); print(string.format("Kills to level-up: %.2f", left/xpPerKill));

Macro to print coordinates: /run z = C_Map.GetBestMapForUnit("player"); pos = C_Map.GetPlayerMapPosition(z,"player"); print(C_Map.GetMapInfo(z).name, math.ceil(pos.x*10000)/100, math.ceil(pos.y*10000)/100)

Macro to test whether a given quest (given as the quest ID) is completed: /run print(IsQuestFlaggedCompleted(5741))

Macro to print time played, then take a screenshot, with an appropriate delay so the time played is in the screenshot:
/run x=0; for i=0, 5000000 do x=x+i; end; x=x+1;
/run Screenshot();

command line printing (linux)

lp -d "Printer Name" -o media=a4 file.txt

Printer name is the same as in, for example, GNOME's printer settings. With my particular printer this prints monospaced, about 78 or 79 characters per line, 65 or 66 lines per page. Uses LF line endings; CR+LF turns into two line breaks. Some Unicode support, but I haven't tested it extensively, is at least capable of basic Latin with characters like æ and €, found in the first 256 characters of Unicode. Margins are pretty much nonexistent, just a few millimeters giving the smallst margins the printer is capable of. If I remember correctly it also doesn't really do the margins that well either, it still formats the page as it were US Letter, which is a bit wider and a bit shorter than A4, and therefore you don't get 80 characters per line but 78 or 79 and a bit, with the 80th character well outside the page, and the 81st on the next line below; very annoying. Has a very annoying habit of using ligatures such as fi and ffi, which looks absolutely horrible in monospace text and messes up manual justification: inefficient.

I managed to get around this by passing the parameter -o raw to lp, but this then breaks Unicode and thrusts you back into the 8-bit world; your text file will be interpreted in code page 437, but this might be printer-specific, as the option is supposed to send the bytes to the printer raw, so it's up to your printer what the charset is. The "raw" option also requires CRLF line endings!

Orientation can be switched with the option -o orientation-requested=4; "4" means landscape, rotated 90-degrees counterclockwise, "5" means rotated 90 degrees clockwise, and "6" means rotated 180 degrees. Two-sided printing can be asked for with -o sides=[option], "option" being "one-sided", "two-sided-long-edge" (for portrait printing), or "two-sided-short-edge" (for landscape printing).

lpr -P "Printer Name" -o media=a4 -o orientation-requested=4 -o raw -o sides=two-sided-short-edge foo.txt

WoW macros: coordinate frame

A self-updating coordinate display, without having to resort to an external plugin. It's made of two macros: you run the first one, dismiss the error message that appears, then run the second one. Tested on WoW Burning Crusade Classic 2.5.2.

First macro: /run f=gf or CreateFrame("Button","gf",UIParent,"UIGoldBorderButtonTemplate");f:SetPoint("TOPLEFT",0,0);f:SetWidth(80);

Second macro: /run p="player";c=C_Map; f:SetScript("OnUpdate",function(s,e) P=c.GetPlayerMapPosition(c.GetBestMapForUnit(p),p) f:SetText(format("(%.1f,%.1f)",P.x*100,P.y*100)) end)

List hardware, succintly, with lshw

sudo lshw -short | cut -c 54-

search engine urls

in-browswer speech synthesis (javascript)

const speak = (txt) => {
  const msg = new SpeechSynthesisUtterance();
  msg.text = txt;

a modicum more privacy for your created tarballs

add --numeric-owner to your GNU tar flags.


for two-letter strings AA, AB, ..., AZ, BA, ..., ZY, ZZ there are 26²=676 combinations, and for three-letter strings from AAA to ZZZ there are 17576. these two snippets will give two- and three-letter combinations, with 0 being aa or aaa, 675 being zz or azz, 17575 being zzz. There's no error correction whatsoever, which is why these are compact, even more compact than an implementation of base-36: giving an input of 17676 gives you {aa and −10 gives you `zq.

def b26(n): return chr(ord("a")+n//26)+chr(ord("a")+n%26)

def b26_3(n): return chr(ord("a")+n//676)+chr(ord("a")+n%676//26)+chr(ord("a")+n%26)

rot13 with tr

tr A-Za-z N-ZA-Mn-za-m

the C++ way to get unix time

#include <chrono>

auto time_now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());



uBlock: using a filter to add extra css

in this example, adding a border to the previous/next buttons on dinosaur comics (source of knowledge):$#.arrowholder { border: 1px dotted; }

in this example, adding an !important allow-scrolling rule to tumblr's body element (to bypass the log-in wall) (source of knowledge):$?#body { overflow: scroll !important; }


less -N: enable line numbers.

less -r: show raw control characters verbatim, instead of with caret notation. less -R: caret-notate control characters, but allow ANSI color escape codes through.

LESSCHARSET=latin1 less file: read file with a different character set, Windows-1252 in the example here. Problem: it also assumes your terminal uses that same charset. To convert to Unicode and then show that, I've used the piped command iconv -f windows-1252 -t utf-8 file | less

less -L: skip the LESSOPEN environment variable, which (for example) preprocesses tar files into a listing of their contents and decompresses compressed files.


finding where the heck i put my DOOM installation, not knowing exactly how it's capitalized or whether it's Chocolate Doom or GZDoom, but knowing that it's at least not at the top level:
find . -mindepth 1 -iname '*doom*' -print


start up (chocolate) doom with a specified base game (IWAD) and a custom file on top (PWAD): chocolate-doom -iwad DOOM.WAD -file test.wad

git config

--system, --global, --local, --worktree, --file <filename>

git config --list: list effective values currently

git config, git config

sed: rudimentary terminal syntax highlighting of comment lines

sed -Ee '/^#/ s/^(#.*)$/^[[36m\1^[[0m/'

You need to input the characters marked as ^[ as a literal ASCII escape character: press Ctrl-V, then press ESC. The code [36m specifies cyan text.