use path use re use str fn is-pdf {|file| eq (path:ext $file) '.pdf' } fn exist {|file| or (path:is-dir &follow-symlink=$true $file) (path:is-regular &follow-symlink=$true $file) } fn not-exist {|file| not (exist $file) } fn is-pdf-exist {|file| and (is-pdf $file) (exist $file) } fn is-number {|v| re:match '^\d+$' (to-string $v) } fn is-page-selection {|v| re:match '^(r?\d+|z)(-(r?\d+|z))?(,(r?\d+|z)(-(r?\d+|z))?)*(:(even|odd))?$' (to-string $v) } fn is-rotate-selection {|v| re:match '^(\+|-)?\d+(:(r?\d+|z)(-(r?\d+|z))?(,(r?\d+|z)(-(r?\d+|z))?)*(:(even|odd))?)?$' (to-string $v) } fn is-selection {|v| or (is-page-selection $v) (is-rotate-selection $v) } fn version {|in| var version = (head -n 1 $in) set version @_ = (str:split "\r" $version) str:trim-prefix $version '%PDF-' } fn json {|in| qpdf $in --json | from-json } fn form {|in| var json = (json $in) put $json[acroform] } fn encryption {|in| var json = (json $in) put $json[encrypt] } fn objects {|in| var json = (json $in) put $json[objects] } fn -object {|extend objects key| if (not (has-key $objects $key)) { put $nil return } var o = $objects[$key] if (and $extend (eq (kind-of $o) 'map')) { keys $o | each {|k| var v = $o[$k] if (has-key $objects $v) { set o[$k] = (-object $extend $objects $v) } } } put $o } fn object {|&extend=$false in key| -object $extend (objects $in) $key } fn filter {|&extend=$false in cond| var objects = (objects $in) keys $objects | each {|k| var o = (-object $extend $objects $k) if ($cond $o) { put [&id=$k &object=$o] } } } fn trailer {|in| object $in 'trailer' } fn pages {|in| var json = (json $in) put $json[pages] } fn page {|in nb| put (pages $in)[(- $nb 1)] } fn nb-pages {|in| qpdf --show-npages $in } fn parse-selection {|@selection| var out = [] var in = $nil each {|e| if (is-pdf $e) { if (not-exist $e) { fail (printf '%s: le fichier n’existe pas' $e) } if (not-eq $in $nil) { set @out = $@out $in } set in = [ &file=$e &rotate=$nil &selections=[] ] continue } if (eq $in $nil) { fail (printf '%s: pas de fichier avant la sélection' $e) } var r rc = $in[rotate] $nil if (is-page-selection $e) { set rc = $false } elif (is-rotate-selection $e) { set rc = $true } else { fail (printf '%s: paramètre invalide' $e) } if (not-eq $r $rc) { if (not-eq $r $nil) { set @out = $@out $in set in[selections] = [] } set in[rotate] = $rc } set in[selections] = [ (all $in[selections]) $e ] } $selection if (not-eq $in $nil) { set @out = $@out $in } put $out } fn -t { mktemp -q /tmp/qpdf_XXXXXXXXXX.pdf } fn rotate {|&empty=$false &out=$nil &keep=$false in @rotate| var @args = $in if (eq $out $nil) { set @args = $@args --replace-input } else { set @args = $@args $out } if $empty { set @args = $@args --empty } if $keep { set @rotate = (each {|r| put --rotate=$r } $rotate) qpdf $@args $@rotate return } var tmp = [] try { var @tmp = (each {|r| var t r @s = (-t) (str:split ':' $r) set s = (str:join ':' $s) if (eq $s '') { qpdf $in $t --rotate=$r } else { qpdf $in $t --pages $in $s -- qpdf $t --replace-input --rotate=$r } put $t } $rotate) qpdf $@args --pages $@tmp -- } finally { rm -f $@tmp } } fn -catarg {|selection| var f r s = $selection[file] $selection[rotate] $selection[selections] var out tmp = [] [] if $r { var t = (-t) set @tmp = $t set @out = $@out $t rotate &out=$t $f $@s } else { set @out = $@out $f if (> (count $s) 0) { set @out = $@out (str:join ',' $s) } } put $out $tmp } fn cat {|&empty=$false &collate=$nil &out=$nil @selection| var inputs = (parse-selection $@selection) var pages tmp = [] [] each {|in| var a t = (-catarg $in) set @pages = $@pages $@a set @tmp = $@tmp $@t } $inputs try { var in = $pages[0] var @args = $in if (eq $out $nil) { set @args = $@args --replace-input } else { set @args = $@args $out } if $empty { set @args = $@args --empty } if (bool $collate) { var c = --collate if (is-number $collate) { set c = (str:join '=' [ $c $collate ]) } set @args = $@args $c } qpdf $@args --pages $@pages -- } finally { each {|t| rm -f $t } $tmp } } fn decrypt {|&out=$nil in @passwd| var @args = $in if (eq $out $nil) { set @args = $@args --replace-input } else { set @args = $@args $out } set @args = $@args --decrypt if (> (count $passwd) 0) { set @args = $@args $passwd[0] } qpdf $@args } fn -l0 {|n size| set n = (to-string $n) var l = (- $size (count $n)) str:join '' [ (repeat $l 0) $n ] } fn split {|&empty=$false &size=1 in out| if (not-exist $out) { mkdir $out } var args = [] if $empty { set @args = --empty } qpdf $@args --split-pages=$size $in $out'/%d.pdf' } fn uncat {|&empty=$false in out @selection| if (not-exist $out) { mkdir $out } var i = 1 var n = (count $selection) set n = (count (to-string $n)) each {|s| cat &empty=$empty &out=$out'/'(-l0 $i $n)'.pdf' $in $s set i = (+ $i 1) } $selection } fn raw-stream {|in out id| qpdf $in --show-object=$id --raw-stream-data > $out } fn filtered-stream {|in out id| qpdf $in --show-object=$id --filtered-stream-data --normalize-content=n --stream-data=uncompress --decode-level=all > $out }