Skip to content

2022

Introduction

  • New: Xprop.

    You can use xprop to get the name and details of any running graphic application by clicking on it.

Computer Science

CICD

Github Actions

  • New: Store file as a secret.

    If you want to store a file (multiline, binary...) as a secret, first encode it with base64:

    base64 -i < {{ file_path }} | tr -d '\n' | xclip -i -selection clipboard
    

    Then paste it to a new secret. To restore the file diring the workflow, add:

    - name: restore file
      run: echo ${{ secrets.SECRET }} | base64 -d > {{ file_path }}
    
  • New: Conditional execution.

    To allow a step to fail without that implying failing the whole workflow and then execute some steps according to the result, do:

    - name: commitizen
      id: commitizen
      continue-on-error: true
      uses: commitizen-tools/commitizen-action@0.11.0
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
    
    - name: Some other task
      if: steps.commitizen.outcome == 'success'
      run: something
    

DBMS

Database Normalization

  • New: Add definitions and examples.

GNULinux

  • New: Download only the audio in MP3.

    youtube-dl --extract-audio --audio-format mp3 [url]
    

Adjust external monitor brightness

  • New: Script to adjust external monitor brightness.

    If you want to adjust the external monitor brightness according to the main display, you can run the following script after every brightness change to the main monitor.

    xrandr -q | grep -q "DisplayPort-4 connected" || exit 0
    
    (
      # Wait for lock on /var/lock/adjust_external_monitors_brightness.exclusivelock (fd 200) for 20 seconds
      flock -x -w 20 200 || exit 1
    
      # main screen brightness (from 0 to 255)
      main=$(cat /sys/class/backlight/amdgpu_bl0/brightness)
    
      # external monitor
      l27_max=100 # max brightness
      l27_0=40 # equivalent brightness of main for l27 min brightness
      l27_100=255 # equivalent brightness of main for l27 max brightness
    
      # equivalent brightness for the external monitor
      l27=$(( 100 * ( (main > l27_0 ? main : l27_0) - l27_0 ) / (l27_100 - l27_0) ))
    
      # try to set it until success
      until ddccontrol -r 0x10 -w $l27 dev:/dev/i2c-11 | grep -q "Writing 0x10";
      do
        sleep 1;
      done
    
    ) 200>/var/lock/adjust_external_monitors_brightness.exclusivelock
    

    You will need to make a few adjustments:

    • Change DisplayPort-4 to whatever corresponds to your external monitor.
    • Change /sys/class/backlight/amdgpu_bl0/brightness if you use Intel.
    • Adjust the variables (l27_max, l27_0, l27_100).
    • Get the corresponding i2c device (change i2c-11) by running ddccontrol -p.

Alacritty

  • New: Setup remote shell automatically.

    An usefulzsh function is:

    s () {
        infocmp | ssh $@ 'tic -x /dev/stdin'
        ssh $@
    }
    

    Which will setup the shell always before connecting.

Android

  • New: Automatic version code generation.

    If you use semantic versioning and you don't want to increment the version code manually, replace the related config from android/app/build.gradle with:

    def flutterVersionName = localProperties.getProperty('flutter.versionName')
    if (flutterVersionName == null) {
        flutterVersionName = '1.0.0'
    }
    
    def semanticVersion = flutterVersionName.split('\\+')
    def versionCore = semanticVersion[0]
    def build = semanticVersion.length >= 2 ? semanticVersion[1].toInteger() : 0
    def (major, minor, patch) = versionCore.tokenize('.').collect{it.toInteger()}
    def flutterVersionCode = 1000000 * major + 10000 * minor + 100 * patch + build
    

    Then whenever pubspec.yaml version veriable changes and you build an APK or appbundle, the version code will be generated from it.

    Examples (version name -> version code):

    • 1.2.0 -> 1020000
    • 3.0.1+99 -> 3000199
  • New: Signing the APK/AppBundle.

    First of all, create a key if you don't have one with:

    keytool -genkey -v -keystore {{ keystore_file }} -alias {{ key_alias }} \
      -keyalg RSA -keysize 4096 -validity 10000
    

    Replace signingConfigs with:

      signingConfigs {
           release {
            keyAlias "$System.env.KEY_ALIAS"
            keyPassword "$System.env.KEY_PASSWORD"
            storeFile file("$System.env.KEY_PATH")
            storePassword "$System.env.STORE_PASSWORD"
        }
       }
       buildTypes {
           release {
               signingConfig signingConfigs.release
           }
       }
    

    Now, you can set the corresponding environment variables. This configuration is particularily useful if you want to have a CI build and sign the releases.

    Check store file as secret to save the generated keystore file as a CI secret.

APT

  • New: List all installed packages and their versions.

    apt list --installed
    

Bash

  • New: Get min or max from two variables.

    Use the ternary operator. For example, for MAX(10, $VAR) do:

    $((VAR > 10 ? VAR : 10))
    
  • New: Run a command until the ouptut contains some text.

    until somecommand | grep -q "Up to date";
    do
      sleep 1;
    done
    
  • New: Flcok.

    To ensure only one instance of the script runs some code, you can use flock as follows:

    (
      # Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
      flock -x -w 10 200 || exit 1
    
      # Do stuff
    
    ) 200>/var/lock/.myscript.exclusivelock
    
  • New: Beep alert.

    You can generate a beep alert (if enabled in the system) and a window highlight with:

    echo -e "\a"
    

Basics

  • New: Get command output or default value if emtpy.

    echo | sed 's/^$/default value/'
    
  • New: Get the cursor position.

    Useful for recording part of the screen with (ffmpeg)[ffmpeg].

    watch -n 0.1 xdotool getmouselocation
    

Debian

  • New: Find what package a file belongs to.

    dpkg -S /path/to/file
    

demicode

  • New: Get BIOS version.

    dmidecode -t bios -q
    

dpkg

  • New: Most common commands.

    • dpkg -S (--search): Find package(s) owning file(s).

FFmpeg

  • New: Concatenate and convert files.

    ffmpeg -i "concat:1.ogg|2.ogg" out.mp3
    
  • New: Cropping.

    ffmpeg -ss 30 -t 70 -i inputfile.mp3 outputfile.mp3
    
    • -ss refers to the starting time.
    • -t is the duration after the starting time to consider.

Git

  • New: Show commit information.

    To see the information of a particular commit use:

    git show <revhash>
    
  • New: Push tags.

    To push the local tags to the remote server:

    git push --tags
    
  • New: Move last n commits to a new branch.

    So you forgot to create a feature branch ah? No problem, let's move the last few unpushed commits to a new branch:

    git checkout -b new_branch # create a new branch from the current one
    git checkout old_branch # go back to the original branch
    git reset --hard HEAD~3 # undo the last 3 commits
    git checkout new_branch # go to the new branch and continue there
    
  • New: Modify specific commit message.

    git rebase --interactive '<commit-id>^'
    

    Then replace pick with r and save to modify the commit message.

  • New: Merge conflict style.

    Take the pain out of git conflict resolution: use diff3

    git config --global merge.conflictstyle diff3
    

    After running this command to turn on diff3, each new conflict will have a 3rd section, the merged common ancestor.

    <<<<<<< HEAD
    GreenMessage.send(include_signature: true)
    ||||||| merged common ancestor
    BlueMessage.send(include_signature: true)
    =======
    BlueMessage.send(include_signature: false)
    >>>>>>> merged-branch
    
  • New: View file evolution.

    You can use git log -L to view the evolution of a range of lines. Example:

    git log -L 15,23:filename.txt
    

    means trace the evolution of lines 15 to 23 in the file named filename.txt.

  • New: Compare file accross references.

    To compare a file accross references (branches, tags, commits...) do:

    git diff <reference1> <reference2> -- <file>
    
  • New: Revert file to specific commit.

    git checkout c5f567 -- file1/to/restore file2/to/restore
    

GPG

  • New: Generate a key.

    Use gpg --gen-key or gpg --full-gen-key for more options.

  • New: Export public key.

    gpg --output public.pgp --armor --export username@email
    

grep

  • New: Common options.

    • -r: recursively search a directory.
    • -i: ignore case.
    • -l: print only the path of the files that have at least one match.
  • New: Limit results line length.

    First 400 bytes of the line:

    grep "foobar" * | cut -b 1-400
    

    This might leave the match out, but it's simple to use and enough for most cases. The other option is:

    grep -rEo ".{0,10}wantedText.{0,10}" *
    

GTK

  • New: How to change themes.

    GTK is a free and open-source cross-platform widget toolkit for creating graphical user interfaces.

    To change the theme, either use lxapparence or manually edit ~/.config/gtk-3.0/settings.ini. You will be forced to do the second option if the theme is for gtk-3 only.

i3 window manager

  • New: Get pressed key name.

    Some key names are hard to guess, such as XF86AudioRaiseVolume, and you need their name to use them in bindings. You can use xev for that.

LibreOffice

  • New: LibreOffice Calc IF().

    Syntax: IF(Test, Then Value, Otherwise Value).

    Example:

    =IF(A2>500,"High","Low")
    

Makefile

  • New: Paralelize steps.

    Add the following lines to the beginning of the Makefile:

    NPROCS = $(shell grep -c 'processor' /proc/cpuinfo)
    MAKEFLAGS += -j$(NPROCS)
    

MarkDown

  • New: Disable specific rule for a block.

    <!-- markdownlint-disable MD033 -->
    <figure markdown>
      ![Domain model](img/domain_model.png){ loading=lazy }
      <figcaption>Proposed model.</figcaption>
    </figure>
    <!-- markdownlint-enable MD033 -->
    

MkDocs

  • New: Image with caption.

    <!-- markdownlint-disable MD033 -->
    <figure markdown>
      ![Domain model](img/domain_model.png){ loading=lazy }
      <figcaption>Proposed model.</figcaption>
    </figure>
    <!-- markdownlint-enable MD033 -->
    

NeoMutt

  • New: Mailboxes commands.

    • c?<Tab>: (on top of a mailbox) Shows all subdirectories and allows to open them.
  • New: Delete/undelete all messages.

    To delete or undelete all:

    1. Press D or U.
    2. Enter ~A to mark all.

neovim

  • New: Add install instructions.

    To install the latest stable release, do:

    curl -sSL "https://github.com/neovim/neovim/releases/download/stable/nvim-linux64.tar.gz" | \
      tar -C "${HOME}/.local" -xz --strip-components=1 -f -
    
  • New: Vim-surround shortcuts.

    • ysiw": Surround the word under the cursor with double quotes.
    • csiw"': Change the quotes surrounding the word under the cursor from double quotes to single quotes.
    • ds': Delete the single quotes surrounding the word under the cursor.
    • ysi)": Surround the text inside parentheses with double quotes.
    • cs)]: Change the parentheses surrounding the text inside parentheses to square brackets.
  • New: Edit remote files with SSH.

    Just run:

    nvim scp://user@host//tmp/file
    

    Notice the extra /. You can also specify just a directory to browse it interactively.

  • New: Cherry pick lines to commit.

    tpope/vim-fugitive: fugitive.vim: A Git wrapper so awesome, it should be illegal

    1. Open the git summary with :Git (or :G).
    2. Expand the file which contains the lines you want to stage with > (or = to toggle). This will only show the changed chunks plus some extra lines of context above and below the changed lines.
    3. V to start visual mode and select the lines you want to stage with hjkl.
    4. s to stage the visual selection (or - to toggle)
    5. Repeat 2-4 as needed
    6. cc to commit
  • New: Search for visual selection.

    vnoremap // y/\V<C-R>=escape(@",'/\')<CR><CR>
    
    To use the mapping, visually select the characters that are wanted in the search, then type // to search for the next occurrence of the selected text.

  • New: Marks.

    A mark allows you to record your current position so you can return to it later.

    Usage:

    • :marks: show existing marks.
    • ma: set mark a in current position of current file, accessible only from the current file.
    • mA: set mark A in current position of current file, accessible from anywhere.
    • 'a: Go to mark a.
    • ]': jump to next line with a lowercase mark.
  • New: Sed replace with newline.

  • New: Without RegEx.

    Use :sno instead of :s to disable magic.

  • New: Shortcut to open previous buffer.

    Open the previous buffer: <C-^> (or <C-6> in some keyboards).

OpenLDAP

  • New: Show special entries and attributes in search.

    ldapsearch [...] +
    

PostgreSQL

  • New: Check that a string is a valid timezone.

    Use the constraint CHECK (now() AT TIME ZONE timezone IS NOT NULL). For example:

    CREATE TABLE locations (
        location_id SERIAL PRIMARY KEY,
        name TEXT,
        timezone TEXT NOT NULL CHECK (now() AT TIME ZONE timezone IS NOT NULL)
    );
    
  • New: Get the 20 slowest queries.

    SELECT substring(query, 1, 50) AS short_query,
                  round(total_time::numeric, 2) AS total_time,
                  calls,
                  round(mean_time::numeric, 2) AS mean,
                  round((100 * total_time / sum(total_time::numeric) OVER ())::numeric, 2) AS percentage_cpu
    FROM  pg_stat_statements
    ORDER BY total_time DESC
    LIMIT 20;
    
  • New: Count NULL values.

    SELECT COUNT(*) FROM table WHERE column IS NULL;
    
    COUNT only conseiders non null values so use COUNT(*) (which counts the row) instead of COUNT(column) because the later would always return 0 since the filter gets only the null values of column.

  • New: Stop remote connections.

    Some operations, like dropping a database, require that the database has no connections. To stop all remote connections and prevent them from connecting again, do:

    ALTER DATABASE somedatabase ALLOW_CONNECTIONS = OFF;
    
    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'somedatabase';
    

    But if you are using PostgreSQL 13 or above, for dropping a table you can directly do:

    DROP DATABASE db_name WITH (FORCE);
    
  • New: List databases.

    \l
    

Profanity

  • New: Most common commands.

    • \msg {user@server.tld}: Start a conversation.
    • \roster add {user@server.tld}: Add user to contacts.
    • \sub request {user@server.tld}: Request presence updates from user.
    • \omemo start: Start an OMEMO session.

PulseAudio

  • New: Restart PulseAudio.

    pulseaudio -k
    

sed

  • New: Use matched pattern.

    echo "foobarbaz" | sed 's/^foo\(.*\)baz$/\1/'
    

    Returns bar.

Wallabag

  • New: Block all feeds except starred.

    location ~ /feed/sgn/{token}/(?!starred) {
       deny all;
       return 403;
      }
    
  • Correction: Missing placeholder.

Hardware

  • New: Sticky touchpad after suspend.

    After suspension, the touchpad behaves weird: can't scroll, and acts as if you were clicking and dragging (sticky). The TrackPoint works correctly though.

    A first solution was to disable it and just use the TrackPoint. This is done as follows:

    xinput list # look for SynPS/2 Synaptics TouchPad
    xinput set-prop <number> "Device Enabled" 0
    

    This allows you to use the computer without the sticky mouse annoyance but doesn't actually solve the problem. For that, the solution that worked for me is removing the psmouse kernel module before suspending and then reloading it after waking up from suspension. You can first try to do this manualy and then if it works create this script in /lib/systemd/system-sleep/psmouse:

    case $1/$2 in
      pre/*)
        echo "Going to $2..."
        modprobe -r psmouse
        ;;
      post/*)
        echo "Waking up from $2..."
        sleep 2
        modprobe psmouse
        ;;
    esac
    

Programming

basics

  • Reorganization: Renamed file.
  • New: Recursively log object.

    If you console.log() an object, only the first levels of it will be shown. To recursively log the whole object, use:

    console.dir(yourObject, { depth: null });
    
  • New: Map a dictionary to a dictionary.

    Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v["someKey"]]));
    
  • New: Enum.

    There is no Enum in JavaScript but you can use:

    Object.freeze({ Apple: 0, Banana: 1, Cherry: 2});
    
  • New: Pyhton AIOHTTP.

    Basic example:

    import aiohttp
    import asyncio
    
    async def main():
        async with aiohttp.ClientSession() as session:
            async with session.get('http://httpbin.org/get') as resp:
                print(resp.status)
                print(await resp.text())
    
    asyncio.run(main)
    

    Other methods:

    ``python session.put('http://httpbin.org/put', data=b'data') session.delete('http://httpbin.org/delete') session.head('http://httpbin.org/get') session.options('http://httpbin.org/get') session.patch('http://httpbin.org/patch', data=b'data')

  • New: Headers.

    headers = {
        'Accepts': 'application/json',
        'X-API_KEY': 'secret',
    }
    
    async with aiohttp.ClientSession(headers=headers) as session:
        ...
    
  • New: Types in the Closure Type System.

JSDoc

  • New: JSDoc @example.

    `javascript /** * Solves equations of the form a * x = b * @example * // returns 2 * globalNS.method1(5, 10); * @example * // returns 3 * globalNS.method(5, 15); * @returns {Number} Returns the value of x for the equation. */ globalNS.method1 = function (a, b) { return b / a; };

  • New: JSDoc @type.

    Reference: Use JSDoc: @type.

Jinja

  • New: InkWell.

    Make a component clickable (with animations onf hover and tap):

    InkWell(
        onTap: () {
          // To do
        },
        child: Card(),
    )
    
  • New: Accessing the parent Loop.

    The special loop variable always points to the innermost loop. If it’s desired to have access to an outer loop it’s possible to alias it:

    <table>
    {% for row in table %}
      <tr>
      {% set rowloop = loop %}
      {% for cell in row %}
        <td id="cell-{{ rowloop.index }}-{{ loop.index }}">{{ cell }}</td>
      {% endfor %}
      </tr>
    {% endfor %}
    </table>
    

Basics

  • New: Adjust default plot size.

    Try running %matplotlib notebook after the imports.

  • New: Enumerate().

    To iterate over a list keys and values use enumerate(). Example:

    some_list = ['a', 'b', 'c']
    for index, value in enumerate(some_list):
      ...
    
  • New: Enum.

    Example:

    from enum import Enum
    
    class Color(Enum):
      RED = 1
      GREEN = 2
      BLUE = 3
    
  • New: Enum examples.

    >>> Color(1)
    <Color.RED: 1>
    >>> Color(3)
    <Color.BLUE: 3>
    
    >>> Color['RED']
    <Color.RED: 1>
    >>> Color['GREEN']
    <Color.GREEN: 2>
    
    >>> member = Color.RED
    >>> member.name
    'RED'
    >>> member.value
    1
    
  • New: Datetime nstance methods.

    • isoformat(): ISO 8601 formatted string.
  • New: Check syntax without running.

    Try to compile it:

    python -m py_compile script.py
    

Debugging

  • New: Flutter Provider.

    A relatively simple and efficient tool for state management in Flutter is provider.

  • New: Better-exceptions.

    Pretty and more helpful exceptions in Python, automatically.

    pip install better_exceptions
    export BETTER_EXCEPTIONS=1
    
  • New: Debugging with inspect.

    See a function definition at runtime

    from somewhere import somefunction
    from inspect import getsource
    
    print(getsource(somefunction))
    

    Get function signature at runtime

    from somewhere import somefunction
    from inspect import signature
    
    print(signature(somefunction))
    

Logging

  • New: Python logging.

    Basic configuration:

    import logging
    
    logging.basicConfig(
        format='%(asctime)s %(levelname)s %(message)s',
        level=logging.INFO,
        datefmt='%Y-%m-%d %H:%M:%S'
    )
    
    logging.info('Just a random string...')
    

pip

  • New: Uninstall all packages.

    pip freeze | xargs pip uninstall -y
    
  • New: Install.

    Options:

    • --ignore-installed: Ignore the installed packages, overwriting them.

pydantic

  • New: Logging.

    To add custom log messages to the uvicorn output, the dirty way, get the logger called uvicorn:

    logger = logging.getLogger("uvicorn")
    
  • New: Pydantic types.

    • pydantic.HttpUrl
    • pydantic.color.Color
  • New: Exporting.

    Options:

    • model.json(exclude_none=True)
    • model.dict(exclude_none=True)
  • New: Use alias for model.dict().

    From https://github.com/pydantic/pydantic/issues/205

Typing

  • New: Awaitable type.

    • Awaitable: Promise/Future.
  • New: F821 undefined name when class method return type is the class name.

    Since the class is not defined yet, to use it as the return type that a class method returns you need to:

    from __future__ import annotations
    

Theory

Algorithms

  • New: Add union-find data structure definition and algorithms.

    In computer science, a disjoint-set data structure, also called a union–find data structure or merge–find set, is a data structure that stores a collection of disjoint (non-overlapping) sets.

    It can be used to store the connected components of an undirected graph.

    An example could be:

    0   1---2   3---4
    
    5---6   7   8   9
    
    • N is the number of nodes. Equals to 10 in the example.

    The data structure should support the following operations:

    • initialize(): Set the initial state of the graph.
    • find(p, q): Are nodes p and q connected?
    • union(p,q): Connect nodes p and q.

Media

Books

Atlas Shrugged

  • New: Atlas Shrugged 1957 novel by Ayn Rand.

    Atlas Shrugged is a 1957 novel by Ayn Rand. It contains Rand's most extensive statement of Objectivism. The book depicts a dystopian United States in which private businesses suffer under increasingly burdensome laws and regulations.

    The book is more than a thousand pages long. There are audiobooks (~60h long) and a movie divided in three parts.

The Problem of Political Authority

  • New: The Problem of Political Authority.

    Modern states commonly deploy coercion in a wide array of circumstances in which the resort to force would clearly be wrong for any private agent. What entitles the state to behave in this manner? And why should citizens obey its commands? This book examines theories of political authority, from the social contract theory, to theories of democratic authorization, to fairness- and consequence-based theories. Ultimately, no theory of authority succeeds, and thus no government has the kind of authority often ascribed to governments.

    The author goes on to discuss how voluntary and competitive institutions could provide the central goods for the sake of which the state is often deemed necessary, including law, protection from private criminals, and national security. An orderly and livable society thus does not require acquiescence in the illusion of political authority.

Other

  • New: Flutter commnad version.

    flutter --version: See Flutter and Dart version.

  • New: Enum.

    enum Day { monday, tuesday }
    

    Get the value of an enum element:

    Day.monday.name
    
  • New: If null operator (??).

    Get a default value if object is null:

    var value;
    ...
    value = value ?? 2;
    
  • New: Request a new certificate.

    If there is no HTTP sever running:

    certbot certonly --standalone --preferred-challenges http-01 -d {{ domain }} --register-unsafely-without-email --agree-tos -n
    

    If there is an HTTP running:

    certonly --webroot -w {{ web_path_letsencrypt }} --preferred-challenges http-01 -d {{ domain }} --register-unsafely-without-email --agree-tos -n
    
  • Correction: Add missing entries to nav.

  • New: Upload to Play Store with CI.

    1. Create a principal in https://console.cloud.google.com/iam-admin/iam with the role Service Account User.
    2. Create and download a new key (JSON format) for the created principal.
    3. In Play Console go to Setup>API access and enable access for the created principal granting Admin (all permissions) to it.
    4. Add the key JSON content as a GitHub Secret (e.g., SERVICE_ACCOUNT_JSON).
    5. Add the following step to your workflow (after flutter build appbundle):
    - name: Upload to Google Play
      uses: r0adkll/upload-google-play@v1.0.15
      with:
        serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
        packageName: {{ package_name }}
        releaseFiles: build/app/outputs/bundle/release/app-release.aab
        track: production
    
  • New: Support named routes.

    To support named routes (e.g., APP_HOST/some/route), add the following configuration to the host configuration file:

    location / {
        try_files $uri $uri/ /index.html;
    }
    

    Otherwise NGINX will return 404 when queried for a named route since the corresponding file won't exist in the root directory.

  • New: Array find method.

    .find(): returns the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned. E.g., array1.find(element => element > 10).

  • New: Iterate keys and values.

    for (const [key, value] of Object.entries(object)) {
      console.log(key, value);
    }
    
  • Reorganization: Renamed duplicated filenames.