elvish_config/aliases/qpdf.elv

658 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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' nest 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' nexiste 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 dentré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 -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 -list-attachments {|in|
$cmd $in --list-attachments | eawk {|_ f @_|
put $f
}
}
fn -list-fonts {|in|
var objects = ($cmd $in --json | from-json)[objects]
keys $objects | each {|k|
var o = $objects[$k]
if (kind-of $o map) {
put $o
}
} | each {|o|
if (has-key $o /Type) {
put $o
}
} | each {|o|
if (eq $o[/Type] /FontDescriptor) {
var f = [
&name=$o[/FontName][1..]
&embedded=(has-key $o /FontFile2)
]
if $f[embedded] {
set f[file] = $o[/FontFile2]
}
put $f
}
}
}
fn -list-imgs {|in|
var objects = ($cmd $in --json | from-json)[objects]
keys $objects | each {|k|
var o = $objects[$k]
if (kind-of $o map) {
put $o
}
} | each {|o|
if (has-key $o /Type) {
put $o
}
} | each {|o|
if (eq $o[/Type] /FontDescriptor) {
var f = [
&name=$o[/FontName][1..]
&embedded=(has-key $o /FontFile2)
]
if $f[embedded] {
set f[file] = $o[/FontFile2]
}
put $f
}
}
}
fn -extract-attachments {|in out|
-list-attachments $in | each {|f|
$cmd $in --show-attachment=$f > $out'/'$f
}
}
fn -extract-fonts {|in out|
-list-fonts $in | each {|f|
if $f[embedded] {
$cmd $in --show-object=$f[file] --filtered-data-stream > $out'/'$f[name]'.ttf'
}
}
}
fn -extract-imgs {|in out|
}
fn -repeat {|c arg|
str:join '' [ (range $c | each {|_|
put $arg
}) ]
}
fn -to-string {|v|
if (eq (kind-of $v) bool) {
if $v {
put X
} else {
put ''
}
} else {
to-string $v
}
}
fn -format-list {|columns data|
set @columns = (each {|c|
set c[size] = (count $c[label])
put $c
} $columns)
each {|d|
set @columns = (each {|c|
var n = $c[name]
if (has-key $d $n) {
var label = (-to-string $d[$n])
var l = (count $label)
if (> $l $c[size]) {
set c[size] = $l
}
}
put $c
} $columns)
} $data
var size = 0
var @raw = (each {|c|
var cl l = (count $c[label]) $c[size]
set size = (+ $size $l 1)
str:join '' [ (-repeat (- $l $cl) ' ') $c[label] ]
} $columns)
echo (str:join ' ' $raw)
echo (-repeat $size '-')
each {|d|
var @raw = (each {|c|
var n v = $c[name] ''
if (has-key $d $n) {
set v = (-to-string $d[$n])
}
var l lc = (count $v) $c[size]
str:join '' [ (-repeat (- $lc $l) ' ') $v ]
} $columns)
echo (str:join ' ' $raw)
} $data
}
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 rotate {|@args|
var l = (- (count $args) 1)
if (< $l 1) {
fail "rotate doit contenir au moins 2 paramètres"
}
var in = $args[0]
-must-pdf $in
-must-exist $in
var out = (-out $in _rotated)
if (-is-pdf $args[$l]) {
set out = $args[$l]
set args = $args[..$l]
}
-must-not-exist $out
var @rotate = (each {|r| put --rotate=$r } $args[1..])
$cmd $in $out $@rotate
}
fn help {|@args|
cat $E:HOME/.config/elvish/aliases/qpdf.help
}
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]
}
fn list {|@args|
if (!= (count $args) 2) {
fail 'list doit comporter 2 paramètres'
}
var types in = $@args
-must-pdf $in
-must-exist $in
var fl = [
&a=$-list-attachments~
&i=$-list-imgs~
&f=$-list-fonts~
]
var ff = [
&a={|data|
each {|d| echo $d } $data
}
&i={|data|
-format-list [
[&name=name &label=Nom]
[&name=embedded &label=Inclus]
] $data
}
&f={|data|
-format-list [
[&name=name &label=Nom]
[&name=embedded &label=Inclus]
] $data
}
]
str:split , $types | each {|t|
set t = (str:to-lower $t[0])
if (not (has-key $fl $t)) {
continue
}
var @data = ($fl[$t] $in)
echo (count $data)' donnée(s) trouvée(s)'
echo
$ff[$t] $data
}
}
fn extract {|@args|
if (!= (count $args) 3) {
fail 'extract doit comporter 3 paramètres'
}
var types in out = $@args
-must-pdf $in
-must-exist $in
-must-not-exist $out
var fe = [
&a=$-extract-attachments~
&i=$-extract-imgs~
&f=$-extract-fonts~
]
mkdir $out
str:split , $types | each {|t|
set t = (str:to-lower $t[0])
if (not (has-key $fe $t)) {
continue
}
$fe[$t] $in $out
}
}
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~
&rotate=$rotate~
&list=$list~
&extract=$extract~
]
if (not (has-key $actions $action)) {
fail $action': action inconnue'
}
$actions[$action] $@args
}