Things that live here:

  1. Work log, where I note things I feel I'll have to Google later.
  2. Journal, very similar but about non-IT topics.
  3. Blog for rare longer-form posts (last one below).

Feel free to look at what you can find here and enjoy yourself.


~17% of my country is occupied by Russia, and horrible things are happening there. You can help stop this! If you can donate - I contribute to (and fully trust) Come Back Alive and Hospitallers, but there are also other ways to help.


Latest posts from the Work log

Day 2183

Using inkscape CLI

Using the Command Line - Inkscape Wiki

  • inkscape action-list shows all available actions

  • man inkscape is the latest and best

  • inkscape AMPERSAND.png --export-type="svg" --export-area-page --batch-process works but asks me about import options

inkscape --shell, man page gives examples:

file-open:file1.svg; export-type:pdf; export-do; export-type:png; export-do
                   file-open:file2.svg; export-id:rect2; export-id-only; export-filename:rect_only.svg; export-do

OK this works for no questions about how to import it:

> file-open:AMPERSAND.png
> export-filename:AM.svg
> export-do

Centerline tracing

Autotrace is awesome!

This alone works really nicely:

autotrace -centerline AMPERSAND.png  -output-file AMPERSAND.svg

Fish script for batch processing, courtesy of ChatGPT:

#!/usr/bin/fish

# Check if autotrace is installed
if not type -q autotrace
    echo "autotrace is not installed. Please install it first."
    exit 1
end

# Loop through each .png file provided as an argument
for file in $argv
    # Check if the file extension is .png
    if string match -r '\.png$' $file
        # Set the output filename by replacing .png with .svg
        set output_file (string replace -r '\.png$' '.svg' $file)

        # Execute autotrace with centerline option
        autotrace -centerline $file -output-file $output_file

        # Confirmation message
        echo "Processed $file to $output_file"
    else
        echo "Skipping $file: not a .png file"
    end
end

And a more simple one:

#!/usr/bin/fish
for file in $argv
    autotrace -centerline $file -output-file "$file.svg"
end

Options

ChatGPT says this:

autotrace -centerline -input-format png -output-format svg -output-file traced_dejavu.svg -dpi 300 -error-threshold 0.5 -corner-threshold 85 -filter-iterations 2 -noise-removal 0.99 -line-threshold 0.5 -corner-surround 3

(et 1 is best)

Day 2181

Trivial HTML and JS audio player

One control, play/pause.

const buttons = document.querySelectorAll('.play-pause-btn');

buttons.forEach(button => {
    const audio = document.getElementById(button.dataset.audio);

    button.addEventListener('click', () => {
        if (audio.paused) {
            // Pause all other audio files
            document.querySelectorAll('audio').forEach(a => {
                a.pause();
                a.currentTime = 0; // Reset other audio files
            });
            document.querySelectorAll('.play-pause-btn').forEach(btn => {
                btn.textContent = '▶';

            });

            // Play the clicked audio
            audio.play();
            button.textContent = '⏸︎';

        } else {
            audio.pause();
            button.textContent = '▶';
        }
    });

    // Reset button icon when audio ends
    audio.addEventListener('ended', () => {
        button.textContent = '▶';
    });
});

Multiple players:

<div class="player-container">
	<button class="play-pause-btn" data-audio="audio1">▶️</button>
	<audio id="audio1" src="audio1.mp3"></audio>
</div>

<div class="player-container">
	<button class="play-pause-btn" data-audio="audio2">▶️</button>
	<audio id="audio2" src="audio2.mp3"></audio>
</div>
.player-container {
    display: inline;
    vertical-align: text-bottom;
    align-items: center;
    margin-bottom: 20px;
}
.play-pause-btn {
    font-size: 32px;
    background: none;
    border: none;
    cursor: pointer;
    margin-right: 10px;
}

Panflute and pandoc for parsing qmd and other files

I missed an ability to recursively look for elements matching a condition in panflute, so:

def _recursively_find_elements(
    element: Element | list[Element], condition: Callable
) -> list[Element]:
    """Return panflute element(s) and their descendants that match conditition.
    """
    results = list()

    def action(el, doc):
        if condition(el):
            results.append(el)

    if not isinstance(element, list):
        element = [element]

    for e in element:
        e.walk(action)


    return results

# sample condition
def is_header(e) -> bool:
	cond = e.tag == "Header" and e.level == 2  # and "data-pos" in e.attributes
	return cond

Ah, to read:

ddoc = pf.convert_text(
	markdown,
	input_format="commonmark_x+raw_html+bracketed_spans+fenced_divs+sourcepos",
	output_format="panflute",
)

To output readably:

pf.stringify(el).strip() 

Pandoc/panflute get line numbers of elements

  • input_format has to be commonmark[_x]+sourcepos
    • sourcepos isn’t too well documented, only w/ commonmark
    • it basically sets el.attributes['data-pos'] a la 126:1-127:1
    • line_no always matching what I expect
def _parse_data_pos(p: str) -> tuple[tuple[int, int], tuple[int, int]]:
	"""Parse data-pos string to (line, char) for start and end.
	
	Example: '126:1-127:1' -> ((126, 1), (127, 1))
	
	Arguments:
		p: data-pos string as generated by commonmark+sourcepos extension.
	"""
	start, end = p.split("-")
	start_l, start_c = start.split(":")
	end_l, end_ch = end.split(":")
	return (int(start_l), int(start_c)), (int(end_l), int(end_ch))

Day 2172 / Fish import env. variables from a .env file

Fish Shell function for sourcing standard .env files :

 . (sed 's/^/export /' .env | psub)

(And yet another mention of Taskfile that I’ll definitely look into nowG)

Day 2128 / Headless printing of HTML to PDF with selenium and quarto reveal presentations

I want to automatically get the PDF version of quarto/reveal presentations. The usual way would be to open the presentation in export mode e, then print with no margins through the usual print window.

I want to do this automatically as part of a CI/CD pipeliene.

Options

Selenium-print

selenium-print · PyPI / bubblegumsoldier/selenium-print uses selenium+chromium to do this.

As for the printing options available in Chrome, this looks relevant:

selenium-print/seleniumprint/drivers/chrome_pdf_driver.py at main · bubblegumsoldier/selenium-print

        pdf = self.driver.execute_cdp_cmd("Page.printToPDF", {"printBackground": True})

OK, so it’s all a static option.

Chrome DevTools Protocol - Page domain has the other available options — which is what I need.

The rest of the code feels like a wrapper to this — maybe I can drop the entire library and just use these single bits?

Decttape (?)

Day 2113

Mirroring a Gitlab repo to Github using ci-cd pipelines

Gitlab mirroring didn’t work for me after trying for hours, I give up. CI/CD it is.

Generating PAT Github tokens for an organization

TL;DR use your own personal settings, then “dev settings” (!), then create one but set the resource owner to the organization.

(As of 2024-10-14. Hard to find clear AND CORRECT documentation on this.)

Create access token for organization · community · Discussion #74701.

fish reading file into (env) variable

set VARNAME (cat ~/myfile | string collect)

Here string collect makes sure it’s a multiline variable instead of an array composed of one element per line.

Day 2110 / Matching similar fonts

Day 2109 / Git shallow clone

On a slow connection or other constraints, you can check out only the last N commits or only a specific branch:

git clone --depth 3 --branch some-branch https://some-repo.org

Git - git-clone Documentation

Day 2101

GPT4 is much better than gpt 4o

As of 2024-10-02 20:16 at least.

give me the ag command to look inside markdown and yaml files only

GPT4o1:

`ag --include='*.md' --include='*.yaml' --include='*.yml' 'search_pattern'`

GPT42:

`ag "search_pattern" --markdown --yaml`

Git ignoring files local-only without gitignore

TIL1:

  • ./git/info/exclude is your local .gitignore outside the repository tree!
  • git update-index --assume-unchanged .gitignore makes git stop checking the changes for that file in the working tree. --no-assume-unchanged to take it back.23

Finally a place for my local ignores that won’t appear in autocomplete suggestions for git add and friends. In Pycharm I have changelists, and now I finally have a solution for my just-as-usual vim/git/CLI workflow as well.

BUT:

  • exclude won’t work if the file is already tracked (says SO but for me it works?..)

Day 2100

yay don't ask for confirmation + the `yes` command to answer prompts

Wanted to do sth like this all the time, but the help basically told me to copypaste multiple arguments etc.

Will come back to bite me but nice to have the option I guess

Question: How can I install packages without having to confirm? · Issue #1033 · Jguer/yay:

echo y | LANG=C yay --noprovides --answerdiff None --answerclean None --mflags "--noconfirm" $PKGNAME

(--noconfirm is not documented in help and man, and of course can create problems1)

BUT ALSO

yes is a command that exists.

Then: yes | yay ... or yes | LANG=C yay

And generally really neat to have a command for answering “yes” to prompts.

And then quick unsafe bad dangerous command to update everything that includes 241001-1512 Yay better compression algos:

echo y | LANG=C PKGEXT='.pkg.tar'  yay  --answerdiff None --answerclean None --mflags "--noconfirm"

Yay better/faster compression algos

yay took forever to compress pycharm. Like, 5-10 mins at least.

TODO documentation, but if you don’t care about package size but care about speed, this will speed up everything considerably:

PKGEXT='.pkg.tar' yay -S pycharm-professional

git-sizer analyses local git repos for problems

github/git-sizer: Compute various size metrics for a Git repository, flagging those that might cause problems (linked by Repository limitations and recommendations)

TL;DR too many files? too large one? too many tags? Find out!

Day 2099 / Google My Maps for shared maps

  • You can share lists in Google Maps, making them editable by everyone with a google account
  • Google My Maps is much cooler, with layers etc

Google My Maps

  • Really nice tutorial on everything: Visualize your data on a custom map using Google My Maps – Google Earth Outreach
  • To share it editable, you share -> Share on Drive
  • drag and drop doesn’t always work
  • style and colors
    • layer can be styled uniformly (easy)
    • style by data column: per-field, e.g. description, like a groupby
    • individual styles per element
  • you can drag and drop items between layers only if they’re styled individually??
  • If you style by e.g. description, assign icons/colors, then style individually to move them, then back to style by description, it seems to save the previous settings

Latest post from Blog

'The Hacker Manifesto', переклад українською

Оригінал: .:: Phrack Magazine ::.
Контекст: Маніфест хакера — Вікіпедія / Hacker Manifesto - Wikipedia
Існуючий дуже класний переклад, не відкривав, поки не закінчив свій: Маніфест хакера | Hacker’s Manifesto | webKnjaZ: be a LifeHacker

                               ==Phrack Inc.==

                    Том I, випуск 7, Ph-айл[0] 3 з 10

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Наступне було написано невдовзі після мого арешту...

	                        \/\Совість хакера/\/

	                               автор:

	                          +++The Mentor+++

	                           8 січня 1986р.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

	Сьогодні ще одного спіймали, пишуть у всіх газетах. "Кібер-скандал:
підлітку повідомили про підозру", "Кіберзлочинця затримали після
проникнення в систему банку".
	Тупа школота[1], вони всі однакові.

	Та чи ви, з вашою трафаретною ментальністю[2] та знаннями 
інформатики зразка першої половини пʼятидесятих[3], коли-небудь дивилися 
в душу хакера?[4] Чи вас колись цікавило, що є причиною його поведінки[5], 
які сили на нього впливали, що його сформувало?
	Я хакер, ласкаво прошу у мій світ...
	Мій світ почався ще зі школи... Я розумніший за більшість інших
дітей, і дурниці, які нам викладають, мені набридають.
	Тупий відстаючий[6], вони всі однакові.

	Восьмий, девʼятий, десятий, одинадцятий клас[7]. В пʼятнадцятий
раз слухаю, як вчителька пояснює, як скорочувати дроби. Мені все ясно. "Ні, 
Вікторія Миколаївна[8], я не написав проміжні кроки, я розвʼязав все усно..."
	Тупий підліток. Мабуть списав. Всі вони такі.

	Сьогодні я зробив відкриття. Я знайшов компʼютер. Ха, почекай-но,
це круто. Він робить те, що я від нього хочу. І якщо він помиляється,
це тому, що помилився я. А не тому що він мене не любить...
                         Або відчуває від мене загрозу...
                         Або думає що я тіпа самий умний[9]...
                         Або не любить викладати[10] і йому тут не місце...
	Тупий підліток. Він постійно тільки грає в свої ігри. Всі вони такі...

	Потім це відбулось... відчинились двері в світ... несучись телефонною 
лінією як героїн венами наркомана, надсилається електронний пульс,
шукається спасіння від невігластва навколо...[11] Знаходиться борд.[12]
	"Це воно... це те, до чого я належу..."
	Я з усіма тут знайомий... попри те, що я з ними ніколи не 
зустрічався, не розмовляв, і колись можливо більше нічого не чутиму про 
них... Я їх всіх знаю...
	Тупий підліток. Знову займає телефонну лінію... Вони всі однакові.

	Та можете не сумніватись,[13] що ми всі однакові... Нас годували
дитячими сумішами з ложки, коли ми хотіли стейк... а ті куски мʼяса, які 
до нас все ж потрапляли, були вже пережовані і без смаку. Над нами
панували садисти, або нас ігнорували байдужі. Для тих, хто хотіли чомусь 
нас навчити, ми були вдячними учнями, але їх було як краплин дощу в
пустелі.

	Цей світ зараз наш... світ електрона і комутатора, світ краси
бода[14]. Ми користуємося існуючою послугою не платячи за те, що могло б 
бути дуже дешевим, якби ним не завідували ненажерливі бариги[15], і ви 
називаєте нас злочинцями. Ми досліджуємо... і ви називаєте нас 
злочинцями. Ми шукаємо знання... і ви називаєте нас злочинцями. Ми 
існуємо без кольору шкіри, без національності і без релігійної 
нетерпимості... і ви називаєте нас злочинцями. Ви будуєте атомні бомби, 
ви ведете війни, ви вбиваєте, обманюєте, і брешете нам, намагаючись 
заставити нас повірити, що ви це робите для нашого блага, і попри все - 
це ми тут злочинці.

	Так, я злочинець. Мій злочин - моя допитливість. Мій злочин - 
оцінювати людей по тому, що вони кажуть і думають, а не по тому, як 
вони виглядають. Мій злочин в тому, що я вас перехитрив, і ви мене 
ніколи не пробачите за це.

	Я хакер, і це мій маніфест. Можливо ви зупините мене як особу, але ви 
ніколи не зупините нас всіх... зрештою, ми всі однакові.
	

Замітки:

  1. Ph-айл: worst of both worlds between phile and файл
  2. Damn kids: тупі/кляті/грьобані діти/школота1/малолітки2? Дякую цьому твіту Букви, який дає мені моральне право використовувати слово “школота”, бо нічого інше не клеїлося (“Окаяні дітлахи!")
  3. three-piece-psychology: інтерпретую як невисоку оцінку розвитку внутрішнього світу. Тому: пересічним/шаблонним/банальним/трафаретним3/примітивним/нехитрим/безхитрим; psychology: ‘інтелект’ але не зовсім, мені подобається ‘ментальність’
  4. and 1950’s technobrain: Німецький переклад, який сподобався англіцизмами та дав ідею перекласти technobrain в значенні “знання про компʼютери”, а не слово в слово: Berühmte Manifeste 2 – openPunk
  5. хакер/гакер: Вікіпедія вважає обидва допустимими; сам Авраменко ссилаючись на ті самі правила українського правопису теж вважає обидва допустимими, але все ж любить “г” більше (Хакер чи гакер - експрес-урок - YouTube). А я не можу і не буду. Хакер. I will die on this hill.
  6. what makes him tick: TODO, нічого не подобається. Що його рухає/надихає, що у нього в середині, …
  7. underachiever: хай буде “відстаючий”. Хоча пригадую з ЗНО, що суфікси уч/юч обмежені у вживанні, правильніше ВІДСТАЛИЙ мені не подобається.
  8. junior high or high school: тут додаю драми замість дослівності, тому що все ближче до оригіналу, що я можу придумати, занадто канцеляристично: “я закінчую базову чи повну загальну середню освіту”..?
  9. Ms. Smith:
  10. I’m a smart ass
  11. doesn’t like teaching: оплакую невикористаний варіант від душі “ненавидить себе, дітей, і педагогіку”. Дуже оплакую.
  12. a refuge from the day-to-day incompetencies is sought
  13. a board is found: мається на увазі електронна дошка оголошень (BBS — Вікіпедія), дід форумів і прадід іміджбордів. Найцікавіше слово для перекладу. Якщо буде “борд” то збережеться драматизм оригіналу, але є шанси, що хтось спутає з іміджбордами. Коли вони були популярні, нормальні люди в Україні їх не називали ніяк, російською були варіанти “доска”, “бибиэска”4. “BBS” був би найпростішим виходом; “електронна дошка оголошень” знову ж таки канцеляризм. По контексту далі очевидно, що мова йде про якесь спілкування, тому хай буде “борд”, принесу в жертву однозначність і зрозумілість милозвучності.
  14. you bet your ass we’re all alike: як же складно підбирати такі речі. Умовні embeddings з ML тут були б в тему. “Дай мені щось на кшталт ‘авжеж’ тільки більш emphatical”. Попередня версія “Авжеж ми всі однакові!”
    1. You bet – phrases: базара нет, по любому, я вас умоляю
    2. Будьте певні5
    3. ЩЕ Б ПАК — СИНОНІМІЯ | Горох — українські словники
      1. Авжеж?6
  15. the beauty of the baud: Бод — Вікіпедія Нехай мій (і єдиний можливий) переклад буде всім настільки ж зрозумілим, наскільки мені був зрозумілий оригінал, коли я його читав вперше.
  16. profitteering gluttons

Hat tip to:

Random: