Skip to content

Commit 41ef17f

Browse files
committed
first commit
0 parents  commit 41ef17f

6 files changed

Lines changed: 328 additions & 0 deletions

File tree

.gitignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
### Go template
2+
# If you prefer the allow list template instead of the deny list, see community template:
3+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
4+
#
5+
# Binaries for programs and plugins
6+
*.exe
7+
*.exe~
8+
*.dll
9+
*.so
10+
*.dylib
11+
12+
# Test binary, built with `go test -c`
13+
*.test
14+
15+
# Output of the go coverage tool, specifically when used with LiteIDE
16+
*.out
17+
18+
# Dependency directories (remove the comment below to include it)
19+
# vendor/
20+
21+
# Go workspace file
22+
go.work
23+
go.work.sum
24+
25+
# env file
26+
.env
27+

go.mod

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module awesomeProject35
2+
3+
go 1.25
4+
5+
require (
6+
github.com/boombuler/barcode v1.1.0
7+
github.com/fogleman/gg v1.3.0
8+
)
9+
10+
require (
11+
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
12+
golang.org/x/image v0.34.0 // indirect
13+
golang.org/x/text v0.32.0 // indirect
14+
)

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
github.com/boombuler/barcode v1.1.0 h1:ChaYjBR63fr4LFyGn8E8nt7dBSt3MiU3zMOZqFvVkHo=
2+
github.com/boombuler/barcode v1.1.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
3+
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
4+
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
5+
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
6+
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
7+
golang.org/x/image v0.34.0 h1:33gCkyw9hmwbZJeZkct8XyR11yH889EQt/QH4VmXMn8=
8+
golang.org/x/image v0.34.0/go.mod h1:2RNFBZRB+vnwwFil8GkMdRvrJOFd1AzdZI6vOY+eJVU=
9+
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
10+
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=

main.go

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"image/color"
6+
"log"
7+
"math"
8+
9+
"github.com/boombuler/barcode"
10+
"github.com/boombuler/barcode/code128"
11+
"github.com/fogleman/gg"
12+
"golang.org/x/image/font"
13+
"golang.org/x/image/font/gofont/goregular"
14+
"golang.org/x/image/font/opentype"
15+
)
16+
17+
// NOTE: The scanner always appends <CR> (Enter). Therefore:
18+
// - All Code values below DO NOT include "<CR>" or a newline.
19+
// - They are mostly ":"-style ex commands where Enter is expected.
20+
21+
// VimOp represents a single barcode entry.
22+
type VimOp struct {
23+
Code string // Exact string encoded in the barcode (no <CR>)
24+
Label string // Short label shown under barcode
25+
Description string // Human description
26+
}
27+
28+
// Curated set of multi-keystroke commands where automatic <CR> is useful.
29+
var vimOps = []VimOp{
30+
// --- Files: write / quit / reload / sudo tricks ---
31+
{":w", ":w", "Write current file"},
32+
{":wa", ":wa", "Write all files"},
33+
{":q", ":q", "Quit (fails if unsaved)"},
34+
{":wq", ":wq", "Write & quit"},
35+
{":wqa", ":wqa", "Write & quit all"},
36+
{":x", ":x", "Write if changed & quit"},
37+
{":q!", ":q!", "Force quit without saving"},
38+
{":w!", ":w!", "Force write (read-only files)"},
39+
{":e!", ":e!", "Reload file (discard changes)"},
40+
{":up", ":up", "Write only if buffer changed"},
41+
{":w ++ff=unix", ":w ++ff=unix", "Write with Unix fileformat"},
42+
{":w ++ff=dos", ":w ++ff=dos", "Write with DOS fileformat"},
43+
{":!sudo tee %", ":!sudo tee %", "Write as root via sudo tee"},
44+
45+
// --- Buffer / file navigation ---
46+
{":ls", ":ls", "List buffers"},
47+
{":bnext", ":bnext", "Next buffer"},
48+
{":bprev", ":bprev", "Previous buffer"},
49+
{":bfirst", ":bfirst", "First buffer"},
50+
{":blast", ":blast", "Last buffer"},
51+
{":b#", ":b#", "Alternate buffer"},
52+
{":bd", ":bd", "Delete current buffer"},
53+
{":bufdo wqa", ":bufdo wqa", "Write & quit all buffers"},
54+
{":edit .", ":edit .", "Open file explorer (netrw)"},
55+
{":Explore", ":Explore", "Netrw file explorer"},
56+
{":Hexplore", ":Hexplore", "Horizontal explorer split"},
57+
{":Vexplore", ":Vexplore", "Vertical explorer split"},
58+
59+
// --- Windows & splits ---
60+
{":sp", ":sp", "Horizontal split"},
61+
{":vsp", ":vsp", "Vertical split"},
62+
{":only", ":only", "Close all other windows"},
63+
{":close", ":close", "Close current window"},
64+
{":new", ":new", "New empty window"},
65+
{":vnew", ":vnew", "New empty vertical split"},
66+
{":wincmd = ", ":wincmd =", "Equalize split sizes"},
67+
{":wincmd H", ":wincmd H", "Move window to far left"},
68+
{":wincmd J", ":wincmd J", "Move window to bottom"},
69+
{":wincmd K", ":wincmd K", "Move window to top"},
70+
{":wincmd L", ":wincmd L", "Move window to far right"},
71+
72+
// --- Tabs ---
73+
{":tabnew", ":tabnew", "New tab"},
74+
{":tabclose", ":tabclose", "Close current tab"},
75+
{":tabonly", ":tabonly", "Close all other tabs"},
76+
{":tabnext", ":tabnext", "Next tab"},
77+
{":tabprev", ":tabprev", "Previous tab"},
78+
{":tabmove 0", ":tabmove 0", "Move tab to front"},
79+
{":tabmove$", ":tabmove$", "Move tab to end"},
80+
81+
// --- Search & highlight behaviour ---
82+
{":noh", ":noh", "Clear search highlight"},
83+
{":set hlsearch", "hlsearch", "Highlight all search matches"},
84+
{":set nohlsearch", "nohlsearch", "Disable search highlight"},
85+
{":set incsearch", "incsearch", "Incremental search"},
86+
{":set noincsearch", "noincsearch", "Disable incremental search"},
87+
{":set ignorecase", "ignorecase", "Case-insensitive search"},
88+
{":set noignorecase", "noignorecase", "Case-sensitive search"},
89+
{":set smartcase", "smartcase", "Smart case search"},
90+
{":set nosmartcase", "nosmartcase", "Disable smart case"},
91+
92+
// --- Indent / tabs / formatting ---
93+
{":set autoindent", "autoindent", "Enable auto indent"},
94+
{":set noautoindent", "noautoindent", "Disable auto indent"},
95+
{":set smartindent", "smartindent", "Enable smart indent"},
96+
{":set nosmartindent", "nosmartindent", "Disable smart indent"},
97+
{":set expandtab", "expandtab", "Convert tabs to spaces"},
98+
{":set noexpandtab", "noexpandtab", "Keep literal tabs"},
99+
{":set tabstop=2", "ts=2", "Tab width = 2"},
100+
{":set tabstop=4", "ts=4", "Tab width = 4"},
101+
{":set shiftwidth=2", "sw=2", "Indent width = 2"},
102+
{":set shiftwidth=4", "sw=4", "Indent width = 4"},
103+
{":set softtabstop=2", "sts=2", "Soft tabstop = 2"},
104+
{":set softtabstop=4", "sts=4", "Soft tabstop = 4"},
105+
{":retab", ":retab", "Convert indentation to current settings"},
106+
107+
// --- Background / colours / UI tweaks ---
108+
{":set background=dark", "bg=dark", "Dark background"},
109+
{":set background=light", "bg=light", "Light background"},
110+
{":set number", "number", "Show line numbers"},
111+
{":set nonumber", "nonumber", "Hide line numbers"},
112+
{":set relativenumber", "relativenumber", "Relative line numbers"},
113+
{":set norelativenumber", "norelativenumber", "Disable relative numbers"},
114+
{":set cursorline", "cursorline", "Highlight current line"},
115+
{":set nocursorline", "nocursorline", "Disable line highlight"},
116+
{":set list", "list", "Show invisible chars"},
117+
{":set nolist", "nolist", "Hide invisible chars"},
118+
{":set wrap", "wrap", "Wrap long lines"},
119+
{":set nowrap", "nowrap", "No wrap; horizontal scroll"},
120+
{":set colorcolumn=80", "cc=80", "Mark column 80"},
121+
{":set colorcolumn=", "cc=", "Clear colorcolumn"},
122+
{":set showmatch", "showmatch", "Briefly jump to matching bracket"},
123+
{":set noshowmatch", "noshowmatch", "Disable showmatch"},
124+
{":set ruler", "ruler", "Show cursor position"},
125+
{":set noruler", "noruler", "Hide ruler"},
126+
{":set showcmd", "showcmd", "Show partial commands"},
127+
{":set noshowcmd", "noshowcmd", "Hide partial commands"},
128+
129+
// --- Spellchecking ---
130+
{":set spell", "spell", "Enable spell checking"},
131+
{":set nospell", "nospell", "Disable spell checking"},
132+
{":set spelllang=en_au", "spelllang=en_au", "Set spell lang to en_au"},
133+
{":set spelllang=en_gb", "spelllang=en_gb", "Set spell lang to en_gb"},
134+
135+
// --- Mouse / paste / misc convenience ---
136+
{":set mouse=a", "mouse=a", "Enable mouse in all modes"},
137+
{":set mouse=", "mouse=", "Disable mouse"},
138+
{":set paste", "paste", "Enable paste mode"},
139+
{":set nopaste", "nopaste", "Disable paste mode"},
140+
{":set clipboard=unnamedplus", "clipboard=unnamedplus", "Use system clipboard"},
141+
{":set clipboard=", "clipboard=", "Use default Vim registers"},
142+
{":set foldmethod=indent", "fold=indent", "Fold by indent level"},
143+
{":set foldmethod=manual", "fold=manual", "Manual folding"},
144+
{":set foldenable", "foldenable", "Enable folding"},
145+
{":set nofoldenable", "nofoldenable", "Disable folding"},
146+
147+
// --- Global substitutions & quick refactors ---
148+
{":%s/old/new/g", ":%s/old/new/g", "Substitute in whole file"},
149+
{":%s/old/new/gc", ":%s/old/new/gc", "Substitute with confirm"},
150+
{":%s/\\s\\+$//e", ":%s/\\s\\+$//e", "Strip trailing whitespace"},
151+
{":g/DEBUG/d", ":g/DEBUG/d", "Delete all lines containing DEBUG"},
152+
{":vimgrep /TODO/ **/*", ":vimgrep /TODO/ **/*", "Search TODO in project"},
153+
{":copen", ":copen", "Open quickfix window"},
154+
{":cclose", ":cclose", "Close quickfix window"},
155+
}
156+
157+
// font cache so we only parse goregular once per size
158+
var fontCache = map[float64]font.Face{}
159+
160+
func main() {
161+
// A4 @ 300dpi
162+
const dpi = 300
163+
const a4WidthInches = 8.27
164+
const a4HeightInches = 11.69
165+
166+
width := int(a4WidthInches * dpi)
167+
height := int(a4HeightInches * dpi)
168+
169+
dc := gg.NewContext(width, height)
170+
171+
// Background
172+
dc.SetRGB(1, 1, 1)
173+
dc.Clear()
174+
175+
margin := 80.0
176+
177+
// Title using Go Regular
178+
dc.SetColor(color.Black)
179+
dc.SetFontFace(mustGoRegularFace(24))
180+
title := "Vim Barcode Cheat Sheet (Scanner adds <CR>)"
181+
dc.DrawStringAnchored(title, float64(width)/2, margin/2, 0.5, 0.5)
182+
183+
// Layout: many commands => 4 columns is a good balance
184+
cols := 4
185+
rows := int(math.Ceil(float64(len(vimOps)) / float64(cols)))
186+
187+
top := margin
188+
bottom := float64(height) - margin
189+
left := margin
190+
right := float64(width) - margin
191+
192+
cellWidth := (right - left) / float64(cols)
193+
cellHeight := (bottom - top) / float64(rows)
194+
195+
barcodeWidth := cellWidth * 0.80
196+
barcodeHeight := cellHeight * 0.38
197+
198+
for i, op := range vimOps {
199+
col := i % cols
200+
row := i / cols
201+
202+
x := left + float64(col)*cellWidth
203+
y := top + float64(row)*cellHeight
204+
205+
cx := x + cellWidth/2
206+
207+
// Light cell boundary
208+
dc.SetLineWidth(0.4)
209+
dc.SetColor(color.RGBA{R: 230, G: 230, B: 230, A: 255})
210+
dc.DrawRectangle(x, y, cellWidth, cellHeight)
211+
dc.Stroke()
212+
213+
// --- Barcode generation (Code 128) ---
214+
raw, err := code128.Encode(op.Code) // BarcodeIntCS
215+
if err != nil {
216+
log.Printf("encode error for %q: %v", op.Code, err)
217+
continue
218+
}
219+
220+
scaled, err := barcode.Scale(raw, int(barcodeWidth), int(barcodeHeight)) // Barcode
221+
if err != nil {
222+
log.Printf("scale error for %q: %v", op.Code, err)
223+
continue
224+
}
225+
226+
// Draw barcode in upper half of the cell
227+
bx := cx - float64(scaled.Bounds().Dx())/2
228+
by := y + 6 // top padding inside cell
229+
dc.DrawImage(scaled, int(bx), int(by))
230+
231+
// Text under barcode (label + description)
232+
labelY := by + float64(scaled.Bounds().Dy()) + 8
233+
234+
dc.SetColor(color.Black)
235+
dc.SetFontFace(mustGoRegularFace(11))
236+
dc.DrawStringAnchored(op.Label, cx, labelY, 0.5, 0)
237+
238+
descY := labelY + 12
239+
dc.SetFontFace(mustGoRegularFace(8))
240+
dc.DrawStringWrapped(op.Description, x+6, descY, 0, 0, cellWidth-12, 1.3, gg.AlignCenter)
241+
}
242+
243+
out := "vim-barcodes-a4.png"
244+
if err := dc.SavePNG(out); err != nil {
245+
log.Fatalf("failed to save PNG: %v", err)
246+
}
247+
248+
fmt.Println("Saved:", out)
249+
}
250+
251+
// mustGoRegularFace returns a Go Regular font.Face at the given size.
252+
// Always uses the goregular TTF embedded in the Go font set.
253+
func mustGoRegularFace(size float64) font.Face {
254+
if face, ok := fontCache[size]; ok {
255+
return face
256+
}
257+
258+
fnt, err := opentype.Parse(goregular.TTF)
259+
if err != nil {
260+
log.Fatalf("failed to parse goregular TTF: %v", err)
261+
}
262+
263+
face, err := opentype.NewFace(fnt, &opentype.FaceOptions{
264+
Size: size,
265+
DPI: 72,
266+
Hinting: font.HintingFull,
267+
})
268+
if err != nil {
269+
log.Fatalf("failed to create goregular face (size=%.1f): %v", size, err)
270+
}
271+
272+
fontCache[size] = face
273+
return face
274+
}

readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Vim Barcode Cheetsheet
2+
3+
![vim-barcodes-a4.png](vim-barcodes-a4.png)

vim-barcodes-a4.png

212 KB
Loading

0 commit comments

Comments
 (0)