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 runningddccontrol -p
.
- Change
Alacritty⚑
-
New: Setup remote shell automatically.
An useful
zsh
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
withr
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
to23
in the file namedfilename.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
orgpg --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 usexev
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:
- Press
D
orU
. - Enter
~A
to mark all.
- Press
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
- Open the git summary with :Git (or :G).
- 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. V
to start visual mode and select the lines you want to stage withhjkl
.s
to stage the visual selection (or-
to toggle)- Repeat 2-4 as needed
cc
to commit
-
New: Search for visual selection.
To use the mapping, visually select the characters that are wanted in the search, then typevnoremap // y/\V<C-R>=escape(@",'/\')<CR><CR>
//
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 marka
in current position of current file, accessible only from the current file.mA
: set markA
in current position of current file, accessible from anywhere.'a
: Go to marka
.]'
: 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 useCOUNT(*)
(which counts the row) instead ofCOUNT(column)
because the later would always return 0 since the filter gets only the null values ofcolumn
. -
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 calleduvicorn
: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().
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.
- Create a principal in https://console.cloud.google.com/iam-admin/iam with the role Service Account User.
- Create and download a new key (JSON format) for the created principal.
- In Play Console go to Setup>API access and enable access for the created principal granting Admin (all permissions) to it.
- Add the key JSON content as a GitHub Secret (e.g.,
SERVICE_ACCOUNT_JSON
). - 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.