Compare commits
7 Commits
56db390b0f
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| af1e54f67d | |||
| 50c85b4025 | |||
| 54f6ad3a84 | |||
| 2c0ba395ab | |||
| f2bb83da3a | |||
| 18a7d2aba9 | |||
| 31bea2ea9a |
@@ -22,7 +22,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Zola
|
- name: Install Zola
|
||||||
run: |
|
run: |
|
||||||
wget https://github.com/getzola/zola/releases/download/v${ZOLA_VERSION}/zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz
|
wget -nv https://github.com/getzola/zola/releases/download/v${ZOLA_VERSION}/zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz
|
||||||
tar -xvzf *.tar.gz
|
tar -xvzf *.tar.gz
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
|
|||||||
@@ -20,30 +20,17 @@ It is generated to static HTML via [Zola](https://www.getzola.org/).
|
|||||||
|
|
||||||
My primary employment is at [SUSE](https://www.suse.com) as a security QA engineer. I also work (or have worked) as a teacher at several Prague schools, mainly at [Gymnázium Jana Keplera](https://gjk.cz/).
|
My primary employment is at [SUSE](https://www.suse.com) as a security QA engineer. I also work (or have worked) as a teacher at several Prague schools, mainly at [Gymnázium Jana Keplera](https://gjk.cz/).
|
||||||
|
|
||||||
## Education
|
## Projects & Contributions
|
||||||
|
|
||||||
Both of my degrees have been obtained from the Faculty of Education at Charles University in Prague, specializing in computer science and education.
|
|
||||||
|
|
||||||
My Bachelor's thesis explores static website generators and includes a reference implementation using Zola.
|
|
||||||
|
|
||||||
- [Bachelor's Thesis Text](https://dspace.cuni.cz/bitstream/handle/20.500.11956/152842/130279410.pdf)
|
|
||||||
- [Defense Results](https://dspace.cuni.cz/handle/20.500.11956/152842)
|
|
||||||
|
|
||||||
Master's thesis focuses on implementing a custom ESP32 development board expandable by custom extension boards, along with a set educational materials which can be applied when teaching embedded programing. Both source files and educational materials can be found at [capyboard.dev](https://capyboard.dev) or at [my GitHub profile](https://github.com/realcharmer).
|
|
||||||
|
|
||||||
- [Master's Thesis Text](https://dspace.cuni.cz/bitstream/handle/20.500.11956/196503/120496276.pdf)
|
|
||||||
- [Defense Results](https://dspace.cuni.cz/handle/20.500.11956/196503)
|
|
||||||
|
|
||||||
## Projects
|
|
||||||
|
|
||||||
Some of my projects are published directly at this website or in Git:
|
Some of my projects are published directly at this website or in Git:
|
||||||
|
|
||||||
- [git.0x45.cz/em](https://git.0x45.cz/em)
|
- [git.0x45.cz/em](https://git.0x45.cz/em)
|
||||||
- [git.microlab.space/em](https://git.microlab.space/em)
|
|
||||||
- [github.com/realcharmer](https://github.com/realcharmer)
|
- [github.com/realcharmer](https://github.com/realcharmer)
|
||||||
|
|
||||||
Many of my projects and activities can also be found at [microlab.space](https://microlab.space), which is a student group at our university (founded by me in 2018) focused on all kinds of technology related projects and research.
|
Many of my projects and activities can also be found at [microlab.space](https://microlab.space), which is a student group at our university (founded by me in 2018) focused on all kinds of technology related projects and research.
|
||||||
|
|
||||||
|
I also maintain several [packages](https://repology.org/projects/?maintainer=em%400x45.cz) for [Void Linux](https://voidlinux.org/).
|
||||||
|
|
||||||
## Public speaking
|
## Public speaking
|
||||||
|
|
||||||
The following hyperlinks are existing recordings of some of my talks and presentations, most of which took place at [InstallFest](https://installfest.cz) and [LinuxDays](https://www.linuxdays.cz) in Prague.
|
The following hyperlinks are existing recordings of some of my talks and presentations, most of which took place at [InstallFest](https://installfest.cz) and [LinuxDays](https://www.linuxdays.cz) in Prague.
|
||||||
@@ -63,3 +50,18 @@ Czech:
|
|||||||
- [Cesta z pekla -- Instalujeme vlastní BIOS na ThinkPad x230](https://www.youtube.com/watch?v=03G4MchxqYA)
|
- [Cesta z pekla -- Instalujeme vlastní BIOS na ThinkPad x230](https://www.youtube.com/watch?v=03G4MchxqYA)
|
||||||
- [PGP Key Signing Party](https://www.youtube.com/watch?v=rDMCPtjPuGo)
|
- [PGP Key Signing Party](https://www.youtube.com/watch?v=rDMCPtjPuGo)
|
||||||
- [RGB Mixer](https://ftp.microlab.space/prednasky/rgb-mixer.mp4)
|
- [RGB Mixer](https://ftp.microlab.space/prednasky/rgb-mixer.mp4)
|
||||||
|
|
||||||
|
## Education
|
||||||
|
|
||||||
|
Both of my degrees have been obtained from the Faculty of Education at Charles University in Prague, specializing in computer science and education.
|
||||||
|
|
||||||
|
My Bachelor's thesis explores static website generators and includes a reference implementation using Zola.
|
||||||
|
|
||||||
|
- [Bachelor's Thesis Text](https://dspace.cuni.cz/bitstream/handle/20.500.11956/152842/130279410.pdf)
|
||||||
|
- [Defense Results](https://dspace.cuni.cz/handle/20.500.11956/152842)
|
||||||
|
|
||||||
|
Master's thesis focuses on implementing a custom ESP32 development board expandable by custom extension boards, along with a set educational materials which can be applied when teaching embedded programing. Both source files and educational materials can be found at [capyboard.dev](https://capyboard.dev) or at [my GitHub profile](https://github.com/realcharmer).
|
||||||
|
|
||||||
|
- [Master's Thesis Text](https://dspace.cuni.cz/bitstream/handle/20.500.11956/196503/120496276.pdf)
|
||||||
|
- [Defense Results](https://dspace.cuni.cz/handle/20.500.11956/196503)
|
||||||
|
|
||||||
|
|||||||
62
content/posts/tea-timer-in-bash/index.md
Normal file
62
content/posts/tea-timer-in-bash/index.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
+++
|
||||||
|
title = "Tea Timer in Bash"
|
||||||
|
date = 2025-10-29
|
||||||
|
|
||||||
|
[taxonomies]
|
||||||
|
categories = ["Linux"]
|
||||||
|
|
||||||
|
[extra]
|
||||||
|
author = "Emil Miler"
|
||||||
|
+++
|
||||||
|
|
||||||
|
I grew tired of unlocking my phone and starting a timer every time I brewed tea. Running a simple shell script is far more convenient, and writing it also gave me a chance to refresh my dulled shell scripting skills.
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
Here is the full script which I named `tea` in my file system:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
NOTIFICATION_SOUND=~/.scripts/notification.mp3
|
||||||
|
DELAY="${1:-180}"
|
||||||
|
DELAY_REMAINING=$DELAY
|
||||||
|
|
||||||
|
echo "Timer set to $DELAY seconds"
|
||||||
|
echo "Remaining: $DELAY_REMAINING"
|
||||||
|
|
||||||
|
while [ "$DELAY_REMAINING" -ne 0 ]; do
|
||||||
|
sleep 1
|
||||||
|
((DELAY_REMAINING--))
|
||||||
|
echo -e "\e[1A\e[KRemaining: $DELAY_REMAINING"
|
||||||
|
done
|
||||||
|
|
||||||
|
notify-send 'Tea is Ready' "Timer was set to $DELAY seconds"
|
||||||
|
pw-play "$NOTIFICATION_SOUND" &
|
||||||
|
```
|
||||||
|
|
||||||
|
So how does it work? First, we set some variables:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
NOTIFICATION_SOUND=~/.scripts/notification.mp3
|
||||||
|
DELAY="${1:-180}"
|
||||||
|
```
|
||||||
|
|
||||||
|
`NOTIFICATION_SOUND` contains the path for a sound which gets played after the timer runs out. `DELAY` sets the delay to `$1`, or to default of 180 seconds if the `$1` parameter is missing.
|
||||||
|
|
||||||
|
Next interesting part is the timing itself. It runs in a loop until `DELAY_REMAINING` reaches zero. The loop also contains a peculiar `echo`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo -e "\e[1A\e[KRemaining: $DELAY_REMAINING"
|
||||||
|
```
|
||||||
|
|
||||||
|
This basically replaces the last line in _stdout_, where `\e[1A` moves the cursor to the previous line and `\e[K` erases the line, therefore letting us overwrite the line with new content.
|
||||||
|
|
||||||
|
When the timer runs out, system notification is sent with `notify-send` and the predefined sound is played trough _pipewire_ using `pw-play`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
notify-send 'Tea is Ready' "Timer was set to $DELAY seconds"
|
||||||
|
pw-play "$NOTIFICATION_SOUND" &
|
||||||
|
```
|
||||||
|
|
||||||
|
The usage is simple: running `tea` with an optional parameter, such as `tea 120`.
|
||||||
@@ -36,7 +36,7 @@ body {
|
|||||||
|
|
||||||
header {
|
header {
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
margin-bottom: 5rem;
|
margin-bottom: 4rem;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@@ -62,7 +62,7 @@ nav {
|
|||||||
margin-bottom: 4rem;
|
margin-bottom: 4rem;
|
||||||
max-height: calc(100vh - 2em);
|
max-height: calc(100vh - 2em);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow-y: auto;
|
overflow-y: visible;
|
||||||
|
|
||||||
span.title {
|
span.title {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -87,33 +87,27 @@ nav {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ul.table-of-contents li {
|
ul.table-of-contents li {
|
||||||
|
overflow: visible;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #e1140a;
|
color: #e1140a;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&::before, &::after {
|
&::before {
|
||||||
content: "";
|
content: "";
|
||||||
background-color: #bbb;
|
background-color: #bbb;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: -8px;
|
||||||
top: 0;
|
top: 50%;
|
||||||
}
|
width: 4px;
|
||||||
&::before {
|
height: 4px;
|
||||||
height: 2px;
|
transform: translateY(-2px);
|
||||||
width: .5em;
|
|
||||||
}
|
|
||||||
&::after {
|
|
||||||
width: 2px;
|
|
||||||
height: .5em;
|
|
||||||
}
|
}
|
||||||
&:hover { color: #fff }
|
&:hover { color: #fff }
|
||||||
&:hover::before, &:hover::after { display: none }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li { padding: 0 .5em }
|
||||||
padding: 0 .5em;
|
li>a::before { border-radius: 50% }
|
||||||
&>a::before, &>a::after { display: none }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +269,7 @@ a {
|
|||||||
nav ul.table-of-contents li a {
|
nav ul.table-of-contents li a {
|
||||||
color: #ff6e67;
|
color: #ff6e67;
|
||||||
&::before, &::after {
|
&::before, &::after {
|
||||||
background-color: #383838;
|
background-color: #cdcdcd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{{ term.name }} category</h1>
|
<h1>{{ term.name }} category</h1>
|
||||||
<input id="search" class="search" type="text" placeholder="Search titles" oninput="filter_name(this.value)">
|
<div class="search-wrapper"></div>
|
||||||
{{ macros::list_posts(section=term, taxonomy=true) }}
|
{{ macros::list_posts(section=term, taxonomy=true) }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<div class="info">
|
<div class="info">
|
||||||
<span class="date">{{ page.date }}</span>
|
<span class="date">{{ page.date }}</span>
|
||||||
{%- if page.extra.author and author -%}
|
{%- if page.extra.author and author -%}
|
||||||
, <span class="author">{{ page.extra.author }}</span>
|
· <span class="author">{{ page.extra.author }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if page.taxonomies.categories %}
|
{% if page.taxonomies.categories %}
|
||||||
<div class="taxonomy">
|
<div class="taxonomy">
|
||||||
|
|||||||
Reference in New Issue
Block a user