use math use path use re use str var cmd = $e:qpdf~ fn -is-pdf {|f| str:has-suffix $f .pdf } fn -is-number {|arg| re:match '^\d+$' $arg } fn -is-rotate {|arg| re:match '^(\+|-)(\d+):.*' $arg } fn -is-seq {|arg| re:match '^\d+(,\d+)*$' $arg } fn -must-pdf {|f| if (not (-is-pdf $f)) { fail $f' n’est pas un fichier PDF' } } fn -must-not-exist {|f| var exist = ?(stat $f 2>&- > /dev/null) if (bool $exist) { fail $f' existe déjà' } } fn -must-exist {|f| var exist = ?(stat $f 2>&- > /dev/null) if (not (bool $exist)) { fail $f' n’existe pas' } } fn -make-tmp { mktemp -q /tmp/qpdf_XXXXXXXXXX.pdf } fn -make-seq {|seq| if (not (-is-seq $seq)) { fail $seq': pas une séquence' } set @seq = (order (str:split , $seq)) var b = 1 each {|ei| var e = (- $ei 1) if (== $b $e) { put $b set b = $ei } elif (< $b $e) { put $b'-'$e set b = $ei } } $seq put $b'-z' } fn -out {|in suffix| var out = (str:trim-suffix $in .pdf) str:join '' [ $out .pdf ] } fn -parse-selection {|in selection| if (-is-rotate $selection) { var out = (-make-tmp) var i = (str:index $selection :) var r sel = $selection[..$i] $selection[(+ $i 1)..] if (eq sel '') { set @sel = $in } else { set @sel = $in $sel } $cmd --empty --pages $@sel -- $out $cmd $out --replace-input --rotate=$r put $out } else { put $in $selection } } fn -parse-all {|args| var tmpfiles = [] var selection = [] var in = $nil var miss = $nil try { each {|e| if (-is-pdf $e) { -must-exist $e if (not-eq $miss $nil) { set @selection = $@selection $miss set miss = $e } set in = $e } else { if (eq $in $nil) { fail 'Le pagerange doit être déclaré après un fichier d’entrée' } var @s = (-parse-selection $in $e) if (== (count $s) 1) { set @tmpfiles = $@tmpfiles $@s } set @selection = $@selection $@s } } $args } finally { put $selection $tmpfiles } } fn -merge {|&collate=$nil selection out| if (< (count $selection) 1) { fail 'Aucune sélection' } var @args = --empty --pages $@selection -- $out if (not-eq $collate $nil) { if (-is-number $collate) { set @args = $collate $@args } set @args = --collate $@args } $cmd $@args } fn merge {|@args| var l = (- (count $args) 1) if (< $l 1) { fail "la commande doit contenir au moins 2 paramètres" } var out = $args[$l] -must-pdf $out -must-not-exist $out var sel tmp = [] [] try { set sel tmp = (-parse-all $args[..$l]) -merge $sel $out } finally { if (> (count $tmp) 0) { rm -f $@tmp } } } fn split {|@args| var l = (- (count $args) 1) if (< $l 1) { fail "la commande doit contenir au moins 2 paramètres" } var out = $args[$l] -must-pdf $out -must-not-exist $out set args = $args[..$l] var size = $nil if (-is-number $args[0]) { set size @args = @args } var sel tmp = [] [] try { set sel tmp = (-parse-all $args[..$l]) var t = (-make-tmp) -merge $sel $t set @tmp = $@tmp $t var @ac = --split-pages if (not-eq $size $nil) { set @ac = $@ac $size } set @ac = $@ac $t $out/%d.pdf mkdir $out $cmd $@ac } finally { if (> (count $tmp) 0) { rm -f $@tmp } } } fn split-at {|@args| var l = (- (count $args) 1) if (< $l 2) { fail "la commande doit contenir au moins 3 paramètres" } var out = $args[$l] -must-pdf $out -must-not-exist $out var @seq = (-make-seq $args[0]) set args = $args[1..$l] var sel tmp = [] [] try { set sel tmp = (-parse-all $args[..$l]) var t = (-make-tmp) -merge $sel $t set @tmp = $@tmp $t var i = 1 each {|s| $cmd --empty --pages $t $s -- $out/$i.pdf set i = (+ $i 1) } $seq } finally { if (> (count $tmp) 0) { rm -f $@tmp } } } fn zip {|@args| var l = (- (count $args) 1) if (< $l 1) { fail "la commande doit contenir au moins 2 paramètres" } var out = $args[$l] var col = $true -must-pdf $out -must-not-exist $out set args = $args[..$l] if (-is-number $args[0]) { set col @args = $@args } var sel tmp = [] [] try { set sel tmp = (-parse-all $args) -merge &collate=$col $sel $out } finally { if (> (count $tmp) 0) { rm -f $@tmp } } } fn unzip {|@args| var l = (- (count $args) 1) if (< $l 2) { fail 'unzip doit contenir au moins 3 paramètres' } var mod = $args[0] var out = $args[$l] -must-not-exist $out var sel tmp = [] [] try { set sel tmp = (-parse-all $args[1..$l]) var t = (-make-tmp) -merge $sel $t set @tmp = $@tmp $t var @sels = (range $mod | put []) var end = ($cmd --show-npages $t) range $end | each {|i| var m = (% $i $mod) set sel[$m] = (+ $i 1) } mkdir $out range $mod | each {|i| var @pr = (str:join ',' $@sels[$i]) $cmd --empty --pages $t $@pr -- $out'/'(+ $i 1)'.pdf' } } finally { if (> (count $tmp) 0) { rm -f $@tmp } } } fn decrypt {|@args| var l = (count $args) if (or (< $l 1) (> $l 3)) { fail "decrypt doit contenir entre 1 et 3 paramètres" } var in = $args[0] -must-pdf $in -must-exist $in var out = (-out $in _decrypted.pdf) var p = $nil if (> $l 1) { set p = $args[1] if (== $l 3) { set out = $args[2] -must-pdf $out } } -must-not-exist $out if (eq $p $nil) { $cmd $in $out --decrypt } else { $cmd $in $out --decrypt $p } } fn help {|@args| cat $E:HOME/.config/elvish/aliases/qpdf.help } fn -date {|raw| var y m d = $raw[2..6] $raw[6..8] $raw[8..10] var h n s = $raw[10..12] $raw[12..14] $raw[14..16] var tz @_ = (str:split "'" $raw[16..]) var date = (printf ^ '%s-%s-%sT%s:%s:%s%s' ^ $y $m $d ^ $h $n $s ^ $tz) date --date $date } fn -pts2cm {|v| / (math:round (* $v 3.52778)) 100 } fn -size {|size| var u = 0 var m = [ &10=Kio &20=Mio &30=Gio ] while (< $u 30) { var p = (math:pow 2 (+ $u 10)) if (< $size $p) { break } set u = (to-string (+ $u 10)) } if (== $u 0) { put $size } else { var p = (math:pow 2 (+ $u 10)) var e = (/ $size $p) printf '%.1f%s' $e $m[$u] } } fn -b2str {|b| if $b { put 'Oui' } else { put 'Non' } } fn -props {|input json| var objects = $json[objects] var trailer = $objects[trailer] var iid = $trailer[/Info] var rid = $trailer[/Root] var info = $objects[$iid] var root = $objects[$rid] var pages = $objects[$root[/Pages]] var p1 = $objects[$pages[/Kids][0]][/MediaBox] var w = (-pts2cm $p1[2]) var h = (-pts2cm $p1[3]) var layout = 'Portrait' if (> $w $h) { set layout = 'Paysage' } var props = [ &path=(path:abs $input) &fsize=(-size (stat -c '%s' $input)) &version='' &psize=(printf '%sx%s cm (%s)' $w $h $layout) &pages=$pages[/Count] &title='' &subject='' &author='' &producer=$info[/Producer] &creator=$info[/Creator] &cdate=(-date $info[/CreationDate]) &mdate='' &acroform=(-b2str $json[acroform][hasacroform]) &encrypted=(-b2str $json[encrypt][encrypted]) ] #@TODO: version pdf if (has-key $info '/Title') { set props[title] = $info[/Title] } if (has-key $info '/Subject') { set props[subject] = $info[/Subject] } if (has-key $info '/Author') { set props[author] = $info[/Author] } if (has-key $info '/ModDate') { set props[mdate] = (-date $info[/ModDate]) } put $props } fn info {|@args| var input = $args[0] var json = ($cmd --json $input | from-json) var props = (-props $input $json) echo ' Chemin: '$props[path] echo ' Taille: '$props[fsize] echo ' Version PDF: '$props[version] echo ' Taille des pages: '$props[psize] echo ' Nombre de pages: '$props[pages] echo '............................................' echo ' Titre: '$props[title] echo ' Sujet: '$props[subject] echo ' Auteur: '$props[author] echo ' Créateur: '$props[creator] echo ' Producteur: '$props[producer] echo ' Date de création: '$props[cdate] echo ' Date de modification: '$props[mdate] echo '............................................' echo ' Chiffré: '$props[encrypted] echo ' Acroform: '$props[acroform] } edit:add-var epdf~ {|action @args| var actions = [ &merge=$merge~ &split=$split~ &split-at=$split-at~ &zip=$zip~ &unzip=$unzip~ &decrypt=$decrypt~ &help=$help~ &info=$info~ ] if (not (has-key $actions $action)) { fail $action': action inconnue' } $actions[$action] $@args }