diff --git a/aliases/pdf.elv b/aliases/pdf.elv index c004ef5..9db455f 100644 --- a/aliases/pdf.elv +++ b/aliases/pdf.elv @@ -1,538 +1,441 @@ -use moi/util/format -use moi/util/pdf -use math -use path -use re -use str +edit:add-var pdf~ {|action @args| + use math + use path + use re + use str + use framagit.org/benjamin.vaudour/elv-lib/mods/common + use framagit.org/benjamin.vaudour/elv-lib/mods/format + use framagit.org/benjamin.vaudour/elv-lib/mods/map + use framagit.org/benjamin.vaudour/elv-lib/mods/pdf -fn -must-pdf {|file| - if (not (pdf:is-pdf $file)) { - fail (printf '%s n’est pas un fichier pdf' $file) + var -c~ = $common:cexec~ + var -cc~ = {|c f1| -c $c $f1 $nop~} + + fn must-pdf {|file| -cc (not (pdf:is-pdf $file)) { fail (printf '%s n’est pas un fichier pdf' $file) }} + fn must-exist {|file| -cc (pdf:not-exist $file) { fail (printf '%s n’existe pas' $file) }} + fn must-not-exist {|file| -cc (pdf:exist $file) { fail (printf '%s existe déjà' $file) }} + fn must-pdf-exist {|file| + must-pdf $file + must-exist $file } -} - -fn -must-exist {|file| - if (pdf:not-exist $file) { - fail (printf '%s n’existe pas' $file) + fn must-pdf-not-exist {|file| + must-pdf $file + must-not-exist $file } -} + fn must-valid {|v cond| -cc (not ($cond $v)) { fail (printf '%s: paramètre invalide' $v) }} -fn -must-not-exist {|file| - if (pdf:exist $file) { - fail (printf '%s existe déjà' $file) + fn out {|in suffix| + var out = (str:trim-suffix $in .pdf) + str:join '' [ $out $suffix ] } -} -fn -must-pdf-exist {|file| - -must-pdf $file - -must-exist $file -} + fn help {|@args| cat $E:HOME/.config/elvish/aliases/pdf.help} -fn -must-pdf-not-exist {|file| - -must-pdf $file - -must-not-exist $file -} - -fn -must-valid {|v cond| - if (not ($cond $v)) { - fail (printf '%s: paramètre invalide' $v) - } -} - -fn -out {|in suffix| - var out = (str:trim-suffix $in .pdf) - str:join '' [ $out $suffix ] -} - -fn help {|@args| - cat $E:HOME/.config/elvish/aliases/pdf.help -} - -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] - var out = (-out $in _decrypted.pdf) - var passwd = [] - -must-pdf-exist $in - if (> $l 1) { - set @passwd = $args[1] - if (> $l 2) { - set out = $args[2] - } - } - -must-pdf-not-exist $out - pdf:decrypt &out=$out $in $@passwd -} - -fn rotate {|@args| - var l = (- (count $args) 1) - if (< $l 1) { - fail 'rotate doit contenir au moins 1 paramètres' - } - var in = $args[0] - var out = (-out $in _rotated.pdf) - if (pdf:is-pdf $args[$l]) { - set @args out = (all $args[1..]) - } - -must-pdf-exist $in - -must-pdf-not-exist $out - each {|e| - -must-valid $e $pdf:is-rotate-selection~ - } $args - pdf:rotate &keep=$true &out=$out $in $@args -} - -fn merge {|@args| - var l = (- (count $args) 1) - if (< $l 1) { - fail 'merge doit contenir au moins 2 paramètres' - } - var @selection out = $@args - -must-pdf-not-exist $out - var has-in = $false - each {|e| - if (pdf:is-pdf $e) { - -must-exist $e - set has-in = $true - } else { - if (not $has-in) { - fail 'Une sélection doit être précédée d’un fichier d’entrée' + fn decrypt {|@args| + var l = (count $args) + -cc (or (< $l 1) (> $l 3)) { fail 'decrypt doit contenir entre 1 et 3 paramètres' } + var in = $args[0] + var out = (out $in _decrypted.pdf) + var passwd = [] + must-pdf-exist $in + if (> $l 1) { + set @passwd = $args[1] + if (> $l 2) { + set out = $args[2] } - -must-valid $e $pdf:is-selection~ } - } $selection - pdf:cat &out=$out $@selection -} + must-pdf-not-exist $out + pdf:decrypt &out=$out $in $@passwd + } -fn unmerge {|@args| - var l = (- (count $args) 1) - if (< $l 1) { - fail 'unmerge doit contenir au moins 2 paramètres' - } - var in = $args[0] - var out = (-out $in _unmerged) - if (not (pdf:is-selection $args[$l])) { - set @args out = (all $args[1..]) - } - -must-pdf-exist $in - -must-not-exist $out - each {|e| - -must-valid $e $pdf:is-selection~ - } $args - pdf:uncat $in $out $@args -} - -fn split {|@args| - var l = (- (count $args) 1) - if (< $l 1) { - fail 'split doit contenir au moins 2 paramètres' - } - var out = $args[$l] - set args = $args[..$l] - -must-not-exist $out - var s = 1 - if (pdf:is-number $args[0]) { - set s @args = $@args - } - var t = (pdf:-t) - try { - pdf:cat &out=$t $@args - pdf:split &size=$s $t $out - } finally { - rm -f $t - } -} - -fn split-at {|@args| - var l = (count $args) - if (!= $l 3) { - fail 'split-at doit contenir 3 paramètres' - } - var rg in out = $@args - -must-pdf-exist $in - -must-not-exist $out - -must-valid $rg {|e| re:match '^\d+(,\d+)*$' $e } - - var b sel = 1 [] - str:split ',' $rg | order | each {|s| - var e = (- $s 1) - if (== $b $e) { - set @sel = $@sel $b - set b = $s - } elif (< $b $e) { - set @sel = $@sel (printf '%d-%d' $b $e) - set b = $s + fn rotate {|@args| + var l = (- (count $args) 1) + -cc (< $l 1) { fail 'rotate doit contenir au moins 1 paramètres' } + var in = $args[0] + var out = (out $in _rotated.pdf) + if (pdf:is-pdf $args[$l]) { + set @args out = (all $args[1..]) } + must-pdf-exist $in + must-pdf-not-exist $out + each {|e| + must-valid $e $pdf:is-rotate-selection~ + } $args + pdf:rotate &keep=$true &out=$out $in $@args } - set @sel = $@sel (printf '%d-z' $b) - unmerge $in $@sel $out -} -fn zip {|@args| - var l = (- (count $args) 1) - if (< $l 1) { - fail 'zip doit contenir au moins 2 paramètres' - } - var @selection out = $@args - -must-pdf-not-exist $out - var has-in = $false - each {|e| - if (pdf:is-pdf $e) { - -must-exist $e - set has-in = $true - } else { - if (not $has-in) { - fail 'Une sélection doit être précédée d’un fichier d’entrée' + fn merge {|@args| + var l = (- (count $args) 1) + -cc (< $l 1) { fail 'merge doit contenir au moins 2 paramètres' } + var @selection out = $@args + must-pdf-not-exist $out + var has-in = $false + each {|e| + if (pdf:is-pdf $e) { + must-exist $e + set has-in = $true + } else { + -cc (not $has-in) { fail 'Une sélection doit être précédée d’un fichier d’entrée' } + must-valid $e $pdf:is-selection~ } - -must-valid $e $pdf:is-selection~ - } - } $selection - pdf:cat &collate=$true &out=$out $@selection -} + } $selection + pdf:cat &out=$out $@selection + } -fn unzip {|@args| - var l = (- (count $args) 1) - if (< $l 1) { - fail 'unzip doit contenir au moins 2 paramètres' - } - var in @sel out = $@args - var mod = 2 - if (pdf:is-number $in) { - set mod = $in - if (eq (count $sel) 0) { - fail 'unzip doit contenir au moins 3 paramètres' + fn unmerge {|@args| + var l = (- (count $args) 1) + -cc (< $l 1) { fail 'unmerge doit contenir au moins 2 paramètres' } + var in = $args[0] + var out = (out $in _unmerged) + if (not (pdf:is-selection $args[$l])) { + set @args out = (all $args[1..]) } - set in @sel = $@sel + must-pdf-exist $in + must-not-exist $out + each {|e| + must-valid $e $pdf:is-selection~ + } $args + pdf:uncat $in $out $@args } - -must-not-exist $out - var t = (pdf:-t) - try { - pdf:cat &out=$t $in $@sel - var n = (pdf:nb-pages $t) - mkdir $out - range 1 (+ 1 $mod) | each {|m| - var sel = (range 1 (+ $n 1) | each {|i| - var s = (% $i $mod) - if (== $s 0) { - set s = $mod - } - if (== $s $m) { - put $i - } - } | each $to-string~ | str:join ',') - pdf:cat &out=(printf '%s/%d.pdf' $out $m) $t $sel - } - } finally { - rm -f $t - } -} -fn -pts2cm {|v| - / (math:round (* $v 3.52778)) 100 -} + fn split {|@args| + var l = (- (count $args) 1) + -cc (< $l 1) { fail 'split doit contenir au moins 2 paramètres' } + var out = $args[$l] + set args = $args[..$l] + must-not-exist $out + var s = 1 + if (pdf:is-number $args[0]) { + set s @args = $@args + } + var t = (pdf:-t) + try { + pdf:cat &out=$t $@args + pdf:split &size=$s $t $out + } finally { + rm -f $t + } + } -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 rest = [] - if (> (count $raw[16..]) 0) { - set @rest = (str:split "'" $raw[16..]) + fn split-at {|@args| + var l = (count $args) + -cc (!= $l 3) { fail 'split-at doit contenir 3 paramètres' } + var rg in out = $@args + must-pdf-exist $in + must-not-exist $out + must-valid $rg {|e| re:match '^\d+(,\d+)*$' $e } + var b sel = 1 [] + str:split ',' $rg | order | each {|s| + var e = (- $s 1) + if (== $b $e) { + set @sel = $@sel $b + set b = $s + } elif (< $b $e) { + set @sel = $@sel (printf '%d-%d' $b $e) + set b = $s + } + } + set @sel = $@sel (printf '%d-z' $b) + unmerge $in $@sel $out } - var tz = '+00:00' - if (> (count $rest) 0) { - var tz = $rest[0] - if (eq $tz[0] 'Z') { - set tz = $tz[1..] - } - if (eq $tz '') { - set tz = '00' - } - if (and (not-eq $tz[0] '+') (not-eq $tz[0] '-')) { - set tz = (printf '+%s' $tz) - } - var mm = '00' - if (and (> (count $rest) 1) (pdf:is-number $rest[1])) { - set mm = $rest[1] - } - set tz = (printf '%s:%s' $tz $mm) - } - var date = (printf ^ - '%s-%s-%sT%s:%s:%sZ%s' ^ - $y $m $d ^ - $h $n $s ^ - $tz) - date --date $date -} -fn info {|@args| - if (!= (count $args) 1) { - fail 'info doit contenir un paramètre' + fn zip {|@args| + var l = (- (count $args) 1) + -cc (< $l 1) { fail 'zip doit contenir au moins 2 paramètres' } + var @selection out = $@args + must-pdf-not-exist $out + var has-in = $false + each {|e| + if (pdf:is-pdf $e) { + must-exist $e + set has-in = $true + } else { + -cc (not $has-in) { fail 'Une sélection doit être précédée d’un fichier d’entrée' } + must-valid $e $pdf:is-selection~ + } + } $selection + pdf:cat &collate=$true &out=$out $@selection } - var in @_ = $@args - -must-pdf-exist $in - var json = (pdf:json $in) - var objects = $json[objects] - var trailer = $objects[trailer] - var infos = $objects[$trailer[/Info]] - var pages = $json[pages] - var p1 = $objects[$pages[0][object]] - var w h = (all $p1[/MediaBox][2..] | each $-pts2cm~) - var layout = 'Portrait' - var title = '' - var subject = '' - var author = '' - var creator = '' - var producer = '' - var mdate = '' - var crypted = 'Non' - var hasform = 'Non' - if (> $w $h) { - set layout = 'Paysage' - } - if (has-key $infos '/Title') { - set title = $infos[/Title] - } - if (has-key $infos '/Subject') { - set subject = $infos[/Subject] - } - if (has-key $infos '/Author') { - set author = $infos[/Author] - } - if (has-key $infos '/Creator') { - set creator = $infos[/Creator] - } - if (has-key $infos '/Producer') { - set producer = $infos[/Producer] - } - if (has-key $infos '/ModDate') { - set mdate = (-date $infos[/ModDate]) - } - if (pdf:encryption $in)[encrypted] { - set crypted = 'Oui' - } - if (pdf:form $in)[hasacroform] { - set hasform = 'Oui' - } - var data = [ - [&k='Chemin' &v=(path:abs $in)] - [&k='Taille' &v=(format:size (stat -c '%s' $in))] - [&k='Version PDF' &v=(pdf:version $in)] - [&k='Nombre de pages' &v=(count $pages)] - [&k='Format des pages' &v=(printf '%sx%s cm (%s)' $w $h $layout)] - [&k='Titre' &v=$title] - [&k='Subjet' &v=$subject] - [&k='Auteur' &v=$author] - [&k='Créateur' &v=$creator] - [&k='producteur' &v=$producer] - [&k='Date de création' &v=(-date $infos[/CreationDate])] - [&k='Date de modification' &v=$mdate] - [&k='Chiffré' &v=$crypted] - [&k='Acroform' &v=$hasform] - ] - var label = (format:repeat 21 ' ') - var @props = (format:column &align=right k $label) (format:column v $label) - set props = (format:update-props $props $data) - var sep = (format:repeat (+ $props[0][size] $props[1][size] 3) '.') - var @part = $data[..5] $data[5..12] $data[12..] - each {|d| - format:list &with-header=$false &csep=' : ' &recompute=$false $props $d - echo $sep - } $part -} -fn -list-attachments {|in| - all (pdf:attachments $in) -} - -fn -display-attachments {|in| - var @data = (-list-attachments $in) - printf "%d pièce(s)-jointe(s) trouvée(s):\n\n" (count $data) - all $data | each $echo~ - echo -} - -fn -extract-attachments {|in out| - -list-attachments $in | each {|f| - pdf:attachment $in $out/$f $f - } -} - -fn -list-fonts {|in| - pdf:fonts $in | each {|f| - if (has-key $f /FontDescriptor) { - put [&font=$f &fd=$f[/FontDescriptor]] + fn unzip {|@args| + var l = (- (count $args) 1) + -cc (< $l 1) { fail 'unzip doit contenir au moins 2 paramètres' } + var in @sel out = $@args + var mod = 2 + if (pdf:is-number $in) { + set mod = $in + -cc (eq (count $sel) 0) { fail 'unzip doit contenir au moins 3 paramètres' } + set in @sel = $@sel } - } | each {|f| - if (has-key $f[fd] /FontName) { - assoc $f name $f[fd][/FontName] + must-not-exist $out + var t = (pdf:-t) + try { + pdf:cat &out=$t $in $@sel + var n = (pdf:nb-pages $t) + mkdir $out + range 1 (+ 1 $mod) | each {|m| + var sel = (range 1 (+ $n 1) | each {|i| + var s = (% $i $mod) + -cc (== $s 0) { set s = $mod } + -cc (== $s $m) $i + } | each $to-string~ | str:join ',') + pdf:cat &out=(printf '%s/%d.pdf' $out $m) $t $sel + } + } finally { + rm -f $t } - } | each {|f| - var @_ n = (str:split '+' $f[name]) - var font = $f[font] - var fd = $f[fd] - var embed = (has-key $fd /FontFile2) - var file = '' - set n = (str:trim-prefix $n '/') - if $embed { - set file = $fd[/FontFile2] + } + + fn pts2cm {|v| / (math:round (* $v 3.52778)) 100} + 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 rest = [] + -cc (> (count $raw[16..]) 0) { set @rest = (str:split "'" $raw[16..]) } + var tz = '+00:00' + if (> (count $rest) 0) { + var tz = $rest[0] + -cc (eq $tz[0] 'Z') { set tz = $tz[1..] } + -cc (eq $tz '') { set tz = '00' } + -cc (and (not-eq $tz[0] '+') (not-eq $tz[0] '-')) { set tz = (printf '+%s' $tz) } + var mm = '00' + -cc (and (> (count $rest) 1) (pdf:is-number $rest[1])) { set mm = $rest[1] } + set tz = (printf '%s:%s' $tz $mm) } - put [ - &id=$font[id] - &name=$n - &embed=$embed - &file=$file - &type=(str:trim-prefix $font[/Subtype] '/') - &encoding=(str:trim-prefix $font[/Encoding] '/') + var date = (printf ^ + '%s-%s-%sT%s:%s:%sZ%s' ^ + $y $m $d ^ + $h $n $s ^ + $tz) + date --date $date + } + + fn info {|@args| + -cc (!= (count $args) 1) { fail 'info doit contenir un paramètre' } + var in @_ = $@args + must-pdf-exist $in + var json = (pdf:json $in) + var objects = $json[objects] + var trailer = $objects[trailer] + var infos = $objects[$trailer[/Info]] + var pages = $json[pages] + var p1 = $objects[$pages[0][object]] + var w h = (all $p1[/MediaBox][2..] | each $pts2cm~) + var layout = (-c (> $w $h) 'Paysage' 'Portrait') + var title = (map:value-of $infos '/Title') + var subject = (map:value-of $infos '/Subject') + var author = (map:value-of $infos '/Author') + var creator = (map:value-of $infos '/Creator') + var producer = (map:value-of $infos '/Producer') + var mdate = (-c (has-key $infos '/ModDate') { -date $infos[/ModDate] } '') + var crypted = (-c (pdf:encryption $in)[encrypted] 'Oui' 'Non') + var hasform = ( -c (pdf:form $in)[hasacroform] 'Oui' 'Non') + var data = [ + [&k='Chemin' &v=(path:abs $in)] + [&k='Taille' &v=(format:size (stat -c '%s' $in))] + [&k='Version PDF' &v=(pdf:version $in)] + [&k='Nombre de pages' &v=(count $pages)] + [&k='Format des pages' &v=(printf '%sx%s cm (%s)' $w $h $layout)] + [&k='Titre' &v=$title] + [&k='Subjet' &v=$subject] + [&k='Auteur' &v=$author] + [&k='Créateur' &v=$creator] + [&k='producteur' &v=$producer] + [&k='Date de création' &v=(-date $infos[/CreationDate])] + [&k='Date de modification' &v=$mdate] + [&k='Chiffré' &v=$crypted] + [&k='Acroform' &v=$hasform] ] + var label = (format:repeat 21 ' ') + var @props = (format:column &align=right k $label) (format:column v $label) + set props = (format:update-props $props $data) + var sep = (format:repeat (+ $props[0][size] $props[1][size] 3) '.') + var @part = $data[..5] $data[5..12] $data[12..] + each {|d| + format:list &with-header=$false &csep=' : ' &recompute=$false $props $@d + echo $sep + } $part } -} -fn -display-fonts {|in| - var @data = (-list-fonts $in) - printf "%d police(s) trouvée(s):\n\n" (count $data) - var props = [ - (format:column &align=center id ID) - (format:column name Nom) - (format:column type Type) - (format:column encoding Encodage) - (format:column &align=center embed Téléchargeable) - (format:column &align=center file Fichier) - ] - format:list $props $data - echo -} - -fn -extract-fonts {|in out| - -list-fonts $in | each {|f| - if $f[embed] { - pdf:filtered-stream $in (printf '%s/%s.ttf' $out $f[name]) $f[file] - } + fn list-attachments {|in| all (pdf:attachments $in)} + fn display-attachments {|in| + var @data = (list-attachments $in) + printf "%d pièce(s)-jointe(s) trouvée(s):\n\n" (count $data) + each $echo~ $data + echo } -} - -fn -list-images {|in| - pdf:images $in | each {|i| - var c = '' - var w = (format:int $i[/Width]) - var h = (format:int $i[/Height]) - if (has-key $i /ColorSpace) { - set c = $i[/ColorSpace][0] - } - put [ - &id=$i[id] - &page=(format:int $i[page]) - &name=(str:trim-prefix $i[name] '/') - &width=$w - &height=$h - &dim=(printf '%dx%d' $w $h) - &filter=(str:trim-prefix $i[/Filter] '/') - &size=(format:size $i[/Length]) - &bpc=(format:int $i[/BitsPerComponent]) - &color=(str:trim-prefix $c '/') - ] - } - var objects = (pdf:objects $in) - all (pdf:pages $in) | each {|p| - var pn = (format:int $p[pageposfrom1]) - all $p[images] | each {|img| - var id = $img[object] - var o = (pdf:-object &extend=$true $objects $id) - var s = $o[/Length] - var c = '' - var w = (format:int $o[/Width]) - var h = (format:int $o[/Height]) - if (has-key $o /ColorSpace) { - set c = $o[/ColorSpace][0] - } + fn extract-attachments {|in out| list-attachments $in | each {|f| pdf:attachment $in $out/$f $f }} + fn list-fonts {|in| + pdf:fonts $in | each {|f| + -cc (has-key $f /FontDescriptor) { put [&font=$f &fd=$f[/FontDescriptor]] } + } | each {|f| + -cc (has-key $f[fd] /FontName) { assoc $f name $f[fd][/FontName] } + } | each {|f| + var @_ n = (str:split '+' $f[name]) + var font = $f[font] + var fd = $f[fd] + var embed = (has-key $fd /FontFile2) + var file = (-c $embed $fd[/FontFile2] '') + set n = (str:trim-prefix $n '/') put [ - &id=$id - &page=$pn - &name=(str:trim-prefix $img[name] '/') - &width=$w - &height=$h - &dim=(printf '%dx%d' $w $h) - &filter=(str:trim-prefix $o[/Filter] '/') - &size=(format:size $s) - &bpc=(format:int $o[/BitsPerComponent]) - &color=(str:trim-prefix $c '/') + &id=$font[id] + &name=$n + &embed=$embed + &file=$file + &type=(str:trim-prefix $font[/Subtype] '/') + &encoding=(str:trim-prefix $font[/Encoding] '/') ] } } -} - -fn -display-images {|in| - var @data = (-list-images $in) - printf "%d image(s) trouvée(s):\n\n" (count $data) - var props = [ - (format:column &align=right page Page) - (format:column &align=center id ID) - (format:column name Nom) - (format:column &align=right size Taille) - (format:column &align=right dim Dimensions) - (format:column color Couleur) - (format:column &align=right bpc BPC) - (format:column &align=center filter Filtre) - ] - format:list $props $data - echo -} - -fn -extract-images {|in out| - # En attendant de savoir décoder correctement les images, on utilise poppler - pdfimages -all $in $out/Im -} - -fn list {|@args| - if (!= (count $args) 2) { - fail 'list doit comporter 2 paramètres' + fn display-fonts {|in| + var @data = (list-fonts $in) + printf "%d police(s) trouvée(s):\n\n" (count $data) + var props = [ + (format:column &align=center id ID) + (format:column name Nom) + (format:column type Type) + (format:column encoding Encodage) + (format:column &align=center embed Téléchargeable) + (format:column &align=center file Fichier) + ] + format:list $props $@data + echo } - var types in = $@args - -must-pdf-exist $in - var display = [ - &a=$-display-attachments~ - &f=$-display-fonts~ - &i=$-display-images~ - ] - str:split ',' $types | each {|t| - set t = (str:to-lower $t) - -must-valid $t {|e| - and (> (count $e) 0) (has-key $display $e[0]) + fn extract-fonts {|in out| + list-fonts $in | each {|f| + -cc $f[embed] { pdf:filtered-stream $in (printf '%s/%s.ttf' $out $f[name]) $f[file] } } - $display[$t[0]] $in } -} + fn list-images {|in| + pdf:images $in | each {|i| + var w = (format:int $i[/Width]) + var h = (format:int $i[/Height]) + var c = (-c (has-key $i /ColorSpace) { put $i[/ColorSpace][0] } '') + put [ + &id=$i[id] + &page=(format:int $i[page]) + &name=(str:trim-prefix $i[name] '/') + &width=$w + &height=$h + &dim=(printf '%dx%d' $w $h) + &filter=(str:trim-prefix $i[/Filter] '/') + &size=(format:size $i[/Length]) + &bpc=(format:int $i[/BitsPerComponent]) + &color=(str:trim-prefix $c '/') + ] + } + var objects = (pdf:objects $in) + all (pdf:pages $in) | each {|p| + var pn = (format:int $p[pageposfrom1]) + all $p[images] | each {|img| + var id = $img[object] + var o = (pdf:-object &extend=$true $objects $id) + var s = $o[/Length] + var c = (-c (has-key $o /ColorSpace) { put $o[/ColorSpace][0] } '') + var w = (format:int $o[/Width]) + var h = (format:int $o[/Height]) + put [ + &id=$id + &page=$pn + &name=(str:trim-prefix $img[name] '/') + &width=$w + &height=$h + &dim=(printf '%dx%d' $w $h) + &filter=(str:trim-prefix $o[/Filter] '/') + &size=(format:size $s) + &bpc=(format:int $o[/BitsPerComponent]) + &color=(str:trim-prefix $c '/') + ] + } + } + } + fn display-images {|in| + var @data = (list-images $in) + printf "%d image(s) trouvée(s):\n\n" (count $data) + var props = [ + (format:column &align=right page Page) + (format:column &align=center id ID) + (format:column name Nom) + (format:column &align=right size Taille) + (format:column &align=right dim Dimensions) + (format:column color Couleur) + (format:column &align=right bpc BPC) + (format:column &align=center filter Filtre) + ] + format:list $props $@data + echo + } + fn extract-images {|in out| + # En attendant de savoir décoder correctement les images, on utilise poppler + pdfimages -all $in $out/Im + } -fn extract {|@args| - if (!= (count $args) 3) { - fail 'extract doit comporter 3 paramètres' - } - var types in out = $@args - -must-pdf-exist $in - -must-not-exist $out - var extr = [ - &a=$-extract-attachments~ - &f=$-extract-fonts~ - &i=$-extract-images~ - ] - try { - mkdir $out + fn list {|@args| + -cc (!= (count $args) 2) { fail 'list doit comporter 2 paramètres' } + var types in = $@args + must-pdf-exist $in + var display = [ + &a=$display-attachments~ + &f=$display-fonts~ + &i=$display-images~ + ] str:split ',' $types | each {|t| set t = (str:to-lower $t) - -must-valid $t {|e| - and (> (count $e) 0) (has-key $extr $e[0]) - } - $extr[$t[0]] $in $out + must-valid $t {|e| and (> (count $e) 0) (has-key $display $e[0])} + $display[$t[0]] $in + } + } + + fn extract {|@args| + -cc (!= (count $args) 3) { fail 'extract doit comporter 3 paramètres' } + var types in out = $@args + must-pdf-exist $in + must-not-exist $out + var extr = [ + &a=$extract-attachments~ + &f=$extract-fonts~ + &i=$extract-images~ + ] + try { + mkdir $out + str:split ',' $types | each {|t| + set t = (str:to-lower $t) + must-valid $t {|e| and (> (count $e) 0) (has-key $extr $e[0])} + $extr[$t[0]] $in $out + } + } except e { + rm -rf $out + fail $e + } + } + + fn gray {|@args| + -cc (!= (count $args) 2) { fail 'gray doit comporter 2 paramètres' } + var in out = $@args + must-pdf-exist $in + must-pdf-not-exist $out + convert -colorspace gray $in $out + } + + fn mono {|@args| + var c = (count $args) + -cc (or (< $c 2) (> $c 3)) { fail 'mono doit comporter entre 2 et 3 paramètres' } + var t = $nil + if (pdf:is-number $args[0]) { + set t @args = $@args + -cc (or (< $t 0) (> $t 100)) { fail le taux doit être compris entre 0 et 100 } + -cc (< $c 2) { fail 'mono doit comporter 3 paramètres' } + } + var in out = $@args + must-pdf-exist $in + must-pdf-not-exist $out + if $t { + convert -colorspace gray -threshold $t'%' $in $out + } else { + convert -monochrome $in $out } - } except e { - rm -rf $out - fail $e } -} -edit:add-var pdf~ {|action @args| var actions = [ &help=$help~ &decrypt=$decrypt~ @@ -549,9 +452,10 @@ edit:add-var pdf~ {|action @args| &info=$info~ &list=$list~ &extract=$extract~ + &gray=$gray~ + &mono=$mono~ + #&compress=$compress~ ] - if (not (has-key $actions $action)) { - fail (printf '%s: action inconnue' $action) - } + -cc (not (has-key $actions $action)) { fail (printf '%s: action inconnue' $action) } $actions[$action] $@args } diff --git a/aliases/pdf.help b/aliases/pdf.help index 16eec5f..e9524e6 100644 --- a/aliases/pdf.help +++ b/aliases/pdf.help @@ -29,6 +29,11 @@ Commandes: 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 par défaut : _decrypted.pdf + gray: + Convertit le fichier d’entrée en nuances de gris + mono: [] + Convertit le fichier d’entrée en noir et blanc, au taux de coupure (exprimé en pourcentage, entre 0 et 100) + Défauts : = 50 list: (a(ttachments)|i(mages)|f(onts)) Affiche la liste des fichiers inclus en filtrant selon le type (pièce-jointe, image ou police) extract: (a(ttachments)|i(mages)|f(onts)) diff --git a/aliases/pdf2grey.elv b/aliases/pdf2grey.elv deleted file mode 100644 index d62dcac..0000000 --- a/aliases/pdf2grey.elv +++ /dev/null @@ -1,82 +0,0 @@ -edit:add-var pdf2grey~ {|@argv| - use re - use str - var m = [ - &nb=$false - &split=50 - ] - - fn _help {|| - echo 'Usage: pdf2gray [-hn ()] .pdf .pdf' - echo '' - echo 'Options:' - echo ' -h Affiche cette aide' - echo ' -n [0-100] Convertit en noir et blanc. Si un nombre est spécifié, indique le pourcentage de coupure (par défaut: 50)' - } - - fn is_pdf {|e| - re:match '.*\.pdf$' $e - } - - fn is_int {|e| - re:match '^\d+$' $e - } - - fn is_split {|e| - and (>= $e 0) (<= $e 100) - } - - while (> (count $argv) 0) { - var e @argv = $@argv - if (or (eq $e '-h') (eq $e '--help')) { - _help - return - } elif (eq $e -n) { - set m[nb] = $true - if (== (count $e) 0) { - echo 'Il manque des arguments après -s' - _help - return - } elif (is_int $argv[0]) { - set e @argv = $@argv - if (is_split $e) { - set m[split] = $e - } else { - echo 'L’argument (optionnel) après -s doit être compris entre 0 et 100' - _help - return - } - } - } elif (not (is_pdf $e)) { - echo 'Argument non reconnu: '$e - _help - return - } elif (not (has-key $m input)) { - set m[input] = $e - } else { - set m[output] = $e - if (> (count $argv) 0) { - echo 'Trop d’arguments: '$@argv - _help - return - } - } - } - if (not (has-key $m input)) { - echo 'Manque le input' - _help - return - } elif (not (has-key $m output)) { - echo 'Manque le output' - _help - return - } - - var params = [-colorspace gray] - if $m[nb] { - set @params = (all $params) -threshold $m[split]'%' - } - set @params = $@params $m[input] $m[output] - echo 'Commande: convert '(str:join ' ' $params) - convert $@params -}