No description
  • Go 76.6%
  • Nix 15.2%
  • NSIS 8.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-09 14:36:50 +01:00
installer stuff 2026-09-09 14:36:50 +01:00
vendor stuff 2026-09-09 14:36:50 +01:00
.gitignore stuff 2026-09-09 14:36:50 +01:00
cli.go stuff 2026-09-09 14:36:50 +01:00
flake.lock stuff 2026-09-09 14:36:50 +01:00
flake.nix stuff 2026-09-09 14:36:50 +01:00
go.mod stuff 2026-09-09 14:36:50 +01:00
go.sum stuff 2026-09-09 14:36:50 +01:00
gui_unix.go stuff 2026-09-09 14:36:50 +01:00
gui_windows.go stuff 2026-09-09 14:36:50 +01:00
guitext.go stuff 2026-09-09 14:36:50 +01:00
main.go stuff 2026-09-09 14:36:50 +01:00
platform_unix.go stuff 2026-09-09 14:36:50 +01:00
platform_windows.go stuff 2026-09-09 14:36:50 +01:00
README.md stuff 2026-09-09 14:36:50 +01:00
split.go stuff 2026-09-09 14:36:50 +01:00

pdfsplit

Split a PDF into one file per page. Drop it on the window, or name it on the command line — either way the pages land in a fresh timestamped folder inside your Downloads.

Downloads/
└── pdfsplit-20260909-114530/
    ├── page-01.pdf
    ├── page-02.pdf
    └── page-03.pdf

Two builds from one source tree: a native Linux binary (GTK 3 window) and a Windows .exe with an installer (raw Win32 window). Both are cross-built from Linux.

Using it

pdfsplit                       # open the drag-and-drop window
pdfsplit report.pdf            # split it, print where it went, no window
pdfsplit a.pdf b.pdf           # each PDF gets its own subfolder
pdfsplit -o /tmp scan.pdf      # put the output folder somewhere else
pdfsplit -open scan.pdf        # also open the result in the file manager
pdfsplit -h                    # full usage

With no arguments you get the window; with arguments nothing is drawn at all — it splits, prints one line per input plus the output path, and exits non-zero on failure. The last line of output is always the folder, so it pipes cleanly:

out=$(pdfsplit report.pdf | tail -1)

In the window: drag a PDF (or several) onto it, and the result folder opens when it's done. On Windows you can also drag PDFs onto the app icon or use Open with; on Linux the installed .desktop entry does the same from your file manager.

Building

nix build                      # -> result/bin/pdfsplit                    (Linux)
nix build .#windows-installer  # -> result/pdfsplit-0.2.0-setup.exe        (Windows)
nix build .#windows-exe        # -> result/bin/pdfsplit.exe                (bare .exe)

nix run                        # run the Linux build
nix run .#windows              # run the Windows build under wine
nix develop                    # go + gtk3 + nsis + wine

The Windows GUI is raw Win32 with CGO_ENABLED=0, so GOOS=windows go build cross-compiles it directly and makensis runs natively on Linux — Wine is not needed to build, only to try the result. The Linux GUI is GTK 3 and does need cgo, so that one builds natively.

Inside nix develop:

go build -tags gtk_3_20 -o pdfsplit .                                     # linux
CGO_ENABLED=0 GOOS=windows go build -ldflags '-H windowsgui' -o pdfsplit.exe .

The gtk_3_20 tag is a workaround for a compile error in released gotk3 v0.6.4 (an undefined identifier in its GTK 3.22+ file); it only excludes wrappers this app does not use.

Installing on Windows

Copy result/pdfsplit-0.2.0-setup.exe over and run it. It's a per-user install into %LOCALAPPDATA%\Programs\pdfsplit — no admin rights, no UAC prompt — with Start Menu and Desktop shortcuts and a normal Add/Remove Programs entry.

Because the installer is unsigned, SmartScreen will show a "Windows protected your PC" warning the first time: More infoRun anyway.

The .exe is linked as a GUI-subsystem binary so double-clicking never flashes a console. When you run it from cmd/PowerShell with arguments it borrows that console to print; when there is none (a PDF dropped on the icon) it shows the result folder instead, and reports errors in a message box.

Layout

file what
main.go argument parsing: window or CLI
cli.go the headless path
split.go page splitting via pdfcpu, output naming
guitext.go wording and window size shared by both GUIs
gui_unix.go GTK 3 drop window
gui_windows.go Win32 drop window
platform_unix.go XDG Downloads dir, xdg-open, notifications
platform_windows.go Win32 bindings, known folders, console attach
installer/pdfsplit.nsi NSIS installer script
flake.nix both packages, the wine runner, the dev shell
vendor/ committed Go deps, so the Nix builds are offline

Updating dependencies

nix develop
go get -u ./... && go mod tidy && go mod vendor

vendorHash is not used; the committed vendor/ directory is what the builds read.