Tech Notes

This is my personal user-experience notes of using Linux Distributions, GNU softwares, scripting and Web development. The contents such as wikis, commands, codes, etc. on this page and sub pages are supposed to be used by your own consideration at your own risk. So, doing your own research and climbing learning curve is recommended. I am not responsible for anything bad happened to you or your computing system due to using any content from here.

mexii

It is simple but innovative and complicated logic. Movement is in new method by pressing Enter. The indicators in the prompt line, @ [0%]: shows the direction, @ is downward and # is upward. And 0 is movement lock off, LOCKED=0 and 1 is movement lock on, LOCKED=1. % is where input letter is to appear. In this script, the chain of variables acting like toggle and relative switches is the best.

Sway Per-window Keyboard Layout

In Sway, swaymsg -m is to monitor (watch) events. For example, swaymsg -m -t subscribe '["window"]' is to watch (monitor) window event in Sway. Sway (5), Sway-ipc (7) and swaymsg (1) man pages are to read.

Based on event monitoring of swaymsg -m -t subscribe '["window", "input"]', the following script was written to implement per-window keyboard layout in sway.

~
#!/bin/dash

if [ "$(id -u)" -eq 0 ]; then
    exit 0
fi
trap 'rm "$LOGFI"' EXIT
trap 'exit 0' INT
SCRIPTNAME="$(basename -- "$0")"
if pidof -x "$SCRIPTNAME" -o "$$"; then
    pkill -INT "$SCRIPTNAME"
    exit 0
fi
MSHTD=/tmp/minsoehan.msh.9.d
LOGFI="$MSHTD"/mswaykbd.log
KBID="1:1:AT_Translated_Set_2_keyboard"
mkdir -p "$MSHTD"
echo "0:0" > "$LOGFI"
swaymsg -m -t subscribe '["window", "input"]' | jq -r --unbuffered '
    if .change == "close" then
        "CLOSE:" + (.container.id | tostring)
    elif .change == "focus" then
        "FOCUS:" + (.container.id | tostring)
    elif .input.identifier == "'$KBID'" then
        "KBLCH:" + (.input.xkb_active_layout_index | tostring)
    else
        empty
    end' | while read -r EVENT; do
    TYPE=$(echo "$EVENT" | cut -d ':' -f 1)
    VALU=$(echo "$EVENT" | cut -d ':' -f 2)
    case $(echo "$EVENT" | cut -d ':' -f1) in
        "CLOSE")
            TODELE="$VALU"
            ;;
        "FOCUS")
            PREEVT=$(tail -n 2 "$LOGFI" | head -n 1)
            PRECTN=$(echo "$PREEVT" | cut -d ':' -f 1)
            if [ "$VALU" -eq "$PRECTN" ]; then
                PREKBL=$(echo "$PREEVT" | cut -d ':' -f 2)
            else
                PREKBL=$(grep ^"$VALU": "$LOGFI" | tail -n 1 | cut -d ':' -f 2)
            fi
            if [ -z "$PREKBL" ]; then
                PREKBL=0
            fi
            NOWKBL=$(swaymsg -t get_inputs | jq -r --arg id "$KBID" '.[] | select(.identifier == $id) | .xkb_active_layout_index')
            if [ "$PREKBL" -ne "$NOWKBL" ]; then
                swaymsg input type:keyboard xkb_switch_layout "$PREKBL"
            fi
            echo "${VALU}:${PREKBL}" >> "$LOGFI"
            if [ -n "$TODELE" ]; then
                sed -i "/^${TODELE}:/d" "$LOGFI"
                unset TODELE
            fi
            ;;
        "KBLCH")
            CTNID=$(swaymsg -t get_tree | jq -r '.. | try select(.focused == true) | .id')
            echo "${CTNID}:${VALU}" >> "$LOGFI"
            ;;
    esac
done

And the following script is to have keyboard layout id on the status bar:

mshstatus

For me, it took many years to understand trap and signal for immediate updating in status on a bar like swaybar. According to gnu bash manual, it can be understood that sleep [n] & and wait $! is key to implement mechanism of immediate trigger in status blocks. Importantly, wait $! must be right after sleep command with & for going into background, for example, sleep 9 &:

~
...
sleep 9 &
wait $!
...

Note: $! is process id (pid) of previous command.

AWK Programming Language

The awk utility interprets a special-purpose programming language that makes it possible to handle simple data-reformatting jobs with just a few lines of code.

Progressive Web App (PWA)

Progressive Web Apps (PWAs) are web apps built and enhanced with modern APIs to deliver enhanced capabilities, reliability, and installability while reaching anyone, anywhere, on any device, all with a single codebase.

Reads

https://developers.google.com/codelabs/pwa-in-play#0
https://web.dev/learn/pwa/
https://github.com/GoogleChromeLabs/bubblewrap/tree/main/packages/cli https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps

Steps

  1. Make Website PWA Ready
  2. Build PWA using bubblewrap
  3. Signing the App

1. Make Website PWA Ready

Create /app.webmanifest file with the following content:

/app.webmanufest
{
  "name": "MGMAemp",
  "short_name": "MGMAemp",
  "start_url": "/",
  "scope": "/",
  "icons": [
    {
      "src": "/favicon/web-app-manifest-192x192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "maskable"
    },
    {
      "src": "/favicon/web-app-manifest-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ],
  "theme_color": "#ffffff",
  "background_color": "#ffffff",
  "display": "standalone"
}

Suggestion Online favicon generators like https://realfavicongenerator.net/ generates not only favicons, but also site.webmanifest file with PWA basic content:

Image Processing for Website

Image processing became essential part of web development nowadays. It is my way of image processing in Arch Linux with following steps:

  1. Resizing big image before optimizing using ImageMagic or FFmpeg
  2. Optimizing image using:
  3. Convert image to webp format using cwebp of libwebp

Install Required Software in Arch Linux

~
pacman -S jpegoptim pngquant libwebp libwebp-utils

Resize Image

Using ImageMagic

Astro Notes

JSON import type errors

When we do:

index.astro
import mpps from "../../../content/members/documents/pps-myan/pps-myan.json";
import epps from "../../../content/members/documents/pps-eng/pps-eng.json";

VSCode/TS will show red underlines because:

  • By default, TypeScript doesn’t always know how to type *.json imports.
  • Unless you have "resolveJsonModule": true in your tsconfig.json, VSCode/TS will complain (red underline), even though Astro’s bundler (Vite) will run it fine.

Fix:

tsconfig.json
{
  "compilerOptions": {
    "resolveJsonModule": true,
    "esModuleInterop": true
  }
}

Combining Layouts, Astro and Md

You may want unify them into a single layout by detecting whether the props come from *.astro, an astro page or *.md, a Markdown/MDX page.

Reset Local Repo to Match Remote Repo Exactly

At any point, you may want to completely reset your local project so it matches the remote repo exactly (discarding any local changes, extra files, etc.).

Here are the safe ways depending on how “hard” a reset you need:

Option 1: Reset branch to remote (keeps untracked files)

bash
git fetch --all
git reset --hard origin/main
  • Discards local commits
  • Resets all tracked files to the remote state
  • Leaves untracked files (stuff Git doesn’t know about) in your working directory

Option 2: Reset branch and also delete untracked files

bash
git fetch --all
git reset --hard origin/main
git clean -fd
  • -f means force
  • -d means removing untracked directories too
  • After this, your working directory (local project repo) matches to the remote repo exactly.

Option 3: Really start fresh (nuke & re-clone)

bash
cd ..
rm -rf your-project-folder
git clone https://github.com/your-username/your-repo.git
cd your-repo
  • Above is simplest and cleanest
  • This guarantees no leftover files or configs
  • Useful if you’ve had a lot of messy local changes

origin/main vs origin main

origin/main is a ref name (a branch), single argument.

Astro Blog Build

This is personal record for building a blog site using Astro web framework with Cloudflare integration. Consult with this pages: https://docs.astro.build/ and https://codeberg.org/minsoehan/cloudflare-astro-blog-sample for more details.

Create Cloudflare Worker with Astro Framework

terminal command
npm create cloudflare@latest -- project-name --framework=astro

When you run this command, C3 creates a new project directory, initiates Astro’s official setup tool, select empty template there, and configures the project for Cloudflare. It then offers the option to instantly deploy your application to Cloudflare.