diff --git a/aliases/qpdf.elv b/aliases/qpdf.elv new file mode 100644 index 0000000..a5572ef --- /dev/null +++ b/aliases/qpdf.elv @@ -0,0 +1,294 @@ +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| + echo '' +} + +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 info {|@args| + echo '' +} + +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 +} diff --git a/aliases/qpdf.help b/aliases/qpdf.help new file mode 100644 index 0000000..23e0364 --- /dev/null +++ b/aliases/qpdf.help @@ -0,0 +1,38 @@ +Usage: epdf (commande) [options] + +Commandes: + merge: [] ... + Fusionne la liste des pages sélectionnées dans le fichier de sortie + split: [] [pagerange] .... + Découpe les fichiers d’entrée en fichiers de pages + et place les découpes dans les fichiers /{1,2,…}.pdf + Défauts : = 1 + split_at: [pagerange] ... + Découpe les fichiers d’entrée aux pages indiquées (séparées par des virgules) + zip: [] ... + Réunit alternativement chaque page de chaque fichier d’entrée + dans le fichier de sortie + unzip: [] [] ... + Sépare alternativement chaque page dans les fichiers /{1,2,…}.pdf + Le nombre de fichiers créé est indiqué par le modulo. + Défauts : = 2 + decrypt: [] + Retourne un fichier déchiffré. Si aucun mot de passe n’est donné, tente le déchiffrement + avec un mot de passe à blanc + Fichier de sortie : _decrypted.pdf + info: [ ...] + Affiche les propriétés du document + +Sélection des pages: + Les sélections peuvent comprendre les éléments suivants. Plusieurs sélection sont séparées par des virgules + n u uniquement la page n (ie. 15) + n-m de la page n à m range (ie. 3-6) + m-n pareil mais en sens inverse (ie. 6-3) + z représente la dernière page du document (pour remplacer un n° de page) + r compte à partir de la dernière page (ie. 3-r2) + ...:even pour une sélection donnée, ne conserve que que les pages paires (ie. 1-10:even) + ...:odd pareil mais pour les pages impaires + +90: tourne le groupe de sélection vers la droite (ie. +90:1-5,8,z-12 tourne les pages 1 à 5, + 8 et de la dernière page à la 12è) + -90: pareil mais à gauche + +180: pareil mais en bas