Skip to content

Instantly share code, notes, and snippets.

View wjkoh's full-sized avatar
🎯
Focusing

Woojong Koh wjkoh

🎯
Focusing
View GitHub Profile
@wjkoh
wjkoh / esc_to_switch_to_english.json
Last active September 2, 2025 16:59
MacOS: Press Escape to switch to English (sends Escape multiple times)
{
"description": "Press Escape to switch to English (sends Escape multiple times)",
"manipulators": [
{
"conditions": [
{
"input_sources": [{ "language": "^en$" }],
"type": "input_source_unless"
}
],
@wjkoh
wjkoh / sitemap.go
Created August 31, 2025 18:36
Go: How to Generate sitemap.xml
package main
import (
"encoding/xml"
"io"
)
const defaultXmlNs = "http://www.sitemaps.org/schemas/sitemap/0.9"
type Url struct {
@wjkoh
wjkoh / htmx_response_error.html
Last active August 21, 2025 07:52
HTMX + Alpine.js: Displaying HTTP Errors Using the HTML <dialog> Element
<!-- Copy and paste the following to every html file. -->
<div x-data="{ open: false, title: '', content: '' }"
x-on:htmx:response-error.window="title = $event.detail.xhr.statusText; content = $event.detail.xhr.responseText; open = true">
<dialog x-bind:open="open">
<article>
<h2>Error: <span x-text="title"></span></h2>
<p><code x-text="content"></code></p>
<footer>
<button x-on:click="open = false">OK</button>
</footer>
@wjkoh
wjkoh / camelcase.go
Last active August 20, 2025 07:40
Go: camelCase
package main
import (
"fmt"
"strings"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
@wjkoh
wjkoh / go_trimpath.md
Last active August 15, 2025 07:06
Go: Do you know `-trimpath`?

-trimpath

remove all file system paths from the resulting executable. Instead of absolute file system paths, the recorded file names will begin either a module path@version (when using modules), or a plain import path (when using the standard library, or GOPATH).

https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies

Without -trimpath, e.g., go run .

@wjkoh
wjkoh / audio_duration.go
Created August 10, 2025 06:21
Go + FFmpeg: How to Find the Duration of Audio and Video
func Duration(ctx context.Context, filename string) (time.Duration, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cmd := exec.CommandContext(ctx, "ffprobe", "-i", filename, "-show_format", "-output_format", "json")
stdout, err := cmd.StdoutPipe()
if err != nil {
return time.Duration(0), nil
}
if err := cmd.Start(); err != nil {
return time.Duration(0), nil
@wjkoh
wjkoh / segment_audio.go
Last active August 10, 2025 06:19
Go + FFmpeg: How to Segment (Chunk) Audio File
type File struct {
Name string
Start time.Duration
End time.Duration
ContentType string
}
func SegmentAudio(ctx context.Context, filename string, maxDuration time.Duration, dir string, pattern string) ([]*File, error) {
if dir == "" {
dir = os.TempDir()
@wjkoh
wjkoh / parse_hms.go
Last active August 7, 2025 09:30
Go: How to Parse HH:MM:SS and HH:MM:SS.ttt
func ParseHMS(hms string) (time.Duration, error) {
fields := strings.Split(strings.TrimSpace(hms), ":")
var s string
switch len(fields) {
case 2:
s = fields[0] + "m" + fields[1] + "s"
case 3:
s = fields[0] + "h" + fields[1] + "m" + fields[2] + "s"
default:
return time.Duration(0), fmt.Errorf("parse h:m:s: %s", hms)
@wjkoh
wjkoh / go_detect_content_type.go
Last active August 5, 2025 07:22
Go: Detect Content Type or MIIME Type
package main
import (
"io"
"log"
"net/http"
"os"
)
func detectContentType(r io.Reader) (string, error) {
@wjkoh
wjkoh / go_interfaces.md
Last active August 3, 2025 08:08
Go Interfaces: The Art of "What" Over "How"

Go Interfaces: The Art of "What" Over "How"

"Program to an interface, not an implementation." This isn't a new, flashy Go-specific slogan; it's a time-tested principle in software design that's relevant across many programming languages. The core idea is simple yet powerful: focus on what a thing can do, not what it's made of. 🧐


What are Go Interfaces?

In Go, an interface is a type that specifies a set of method signatures. If a type defines all the methods in an interface, it is said to satisfy that interface. The beauty of Go's approach is that this satisfaction is implicit—you don't need to explicitly declare that your type implements a particular interface.