emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/scanner d64d59f 1/5: handle old scanimage versions with


From: Stefan Monnier
Subject: [elpa] externals/scanner d64d59f 1/5: handle old scanimage versions without the -o switch
Date: Mon, 15 Mar 2021 22:22:21 -0400 (EDT)

branch: externals/scanner
commit d64d59f884e981a029a89f3db34ab167a3c54d17
Author: Raffael Stocker <r.stocker@mnet-mail.de>
Commit: Raffael Stocker <r.stocker@mnet-mail.de>

    handle old scanimage versions without the -o switch
    
    * scanner.el (scanner--scanimage-args): remove output file argument
             (scanner--program-version): new function
             (scanner--tesseract-version): removed
             (scanner--make-scanimage-command): new function
             (scanner-scan-document): use scanner--make-scanimage-command
             (scanner-scan-image): use scanner--make-scanimage-command
    
    ‘scanner--make-scanimage-command’ checks the version of scanimage(1) and
    constructs a command for make-process using shell redirection as necessary.
---
 scanner-test.el | 100 +++++++++++++++++++++++++++++++-------------------------
 scanner.el      |  89 ++++++++++++++++++++++++++++++++++---------------
 2 files changed, 119 insertions(+), 70 deletions(-)

diff --git a/scanner-test.el b/scanner-test.el
index c19d6e3..cb8a93f 100644
--- a/scanner-test.el
+++ b/scanner-test.el
@@ -58,41 +58,29 @@
        (scanner-image-size '(200 250))
        (-compare-fn #'string=))
     ;; known values are included with their switches
-    (should (-is-infix-p '("-d" "devname") (scanner--scanimage-args "file"
-                                                                   :image
+    (should (-is-infix-p '("-d" "devname") (scanner--scanimage-args :image
                                                                    switches
                                                                    "jpeg")))
-    (should (-is-infix-p '("-o" "file") (scanner--scanimage-args "file"
-                                                                :image
-                                                                switches
-                                                                "jpeg")))
-    (should (-contains-p (scanner--scanimage-args "file" :image switches 
"jpeg")
+    (should (-contains-p (scanner--scanimage-args :image switches "jpeg")
                         "--format=jpeg"))
     ;; device-specific options are not included in the argument list
-    (should-not (-contains-p (scanner--scanimage-args "file" :image switches
-                                                     "jpeg")
+    (should-not (-contains-p (scanner--scanimage-args :image switches "jpeg")
                             "--mode"))
-    (should-not (-contains-p (scanner--scanimage-args "file" :image switches
-                                                     "jpeg")
-                            "--resolution"))
-    (should-not (-contains-p (scanner--scanimage-args "file" :image switches
-                                                     "jpeg")
+    (should-not (-contains-p (scanner--scanimage-args :image switches "jpeg")  
                     "--resolution"))
+    (should-not (-contains-p (scanner--scanimage-args :image switches "jpeg")
                             "-x"))
-    (should-not (-contains-p (scanner--scanimage-args "file" :image switches
-                                                     "jpeg")
+    (should-not (-contains-p (scanner--scanimage-args :image switches "jpeg")
                             "-y"))
-    (should-not (-contains-p (scanner--scanimage-args "file" :doc switches 
"jpeg")
+    (should-not (-contains-p (scanner--scanimage-args :doc switches "jpeg")
                             "-x"))
-    (should-not (-contains-p (scanner--scanimage-args "file" :doc switches 
"jpeg")
+    (should-not (-contains-p (scanner--scanimage-args :doc switches "jpeg")
                             "-y"))
     ;; without format and device name, these are not in the args list
     (let ((scanner-image-format nil)
          (scanner-device-name nil))
-      (should-not (-contains-p (scanner--scanimage-args "file" :image switches
-                                                       "jpeg")
+      (should-not (-contains-p (scanner--scanimage-args :image switches "jpeg")
                               "--format="))
-      (should-not (-contains-p (scanner--scanimage-args "file" :image
-                                                       switches "jpeg")
+      (should-not (-contains-p (scanner--scanimage-args :image switches "jpeg")
                               "-d"))))
   ;; image args list with device-specific args
   (let ((switches '("--resolution" "-x" "-y" "--mode"))
@@ -102,38 +90,62 @@
        (scanner-paper-sizes '(:a4 (210 297)))
        (scanner-image-size '(200 250))
        (-compare-fn #'string=))
-    (should (-is-infix-p '("-o" "file") (scanner--scanimage-args "file" :image
-                                                                switches 
"jpeg")))
-    (should (-contains-p (scanner--scanimage-args "file" :image switches 
"jpeg")
+    (should (-contains-p (scanner--scanimage-args  :image switches "jpeg")
                         "--format=jpeg"))
-    (should (-contains-p (scanner--scanimage-args "file" :image switches 
"jpeg")
+    (should (-contains-p (scanner--scanimage-args  :image switches "jpeg")
                         "--mode=Color"))
-    (should (-contains-p (scanner--scanimage-args "file" :image switches 
"jpeg")
+    (should (-contains-p (scanner--scanimage-args  :image switches "jpeg")
                         "--resolution=600"))
-    (should (-is-infix-p '("-x" "210") (scanner--scanimage-args "file" :doc
-                                                               switches 
"jpeg")))
-    (should (-is-infix-p '("-y" "297") (scanner--scanimage-args "file" :doc
-                                                               switches 
"jpeg")))
-    (should (-is-infix-p '("-x" "200") (scanner--scanimage-args "file" :image
-                                                               switches 
"jpeg")))
-    (should (-is-infix-p '("-y" "250") (scanner--scanimage-args "file" :image
-                                                               switches 
"jpeg")))
-    (should (-is-infix-p '("-o" "file") (scanner--scanimage-args "file" :doc
+    (should (-is-infix-p '("-x" "210") (scanner--scanimage-args  :doc
+                                                                switches 
"jpeg")))
+    (should (-is-infix-p '("-y" "297") (scanner--scanimage-args  :doc
                                                                 switches 
"jpeg")))
-    (should (-contains-p (scanner--scanimage-args "file" :doc switches "jpeg")
+    (should (-is-infix-p '("-x" "200") (scanner--scanimage-args  :image
+                                                                switches 
"jpeg")))
+    (should (-is-infix-p '("-y" "250") (scanner--scanimage-args  :image
+                                                                switches 
"jpeg")))
+    (should (-contains-p (scanner--scanimage-args  :doc switches "jpeg")
                         "--format=jpeg"))
-    (should (-contains-p (scanner--scanimage-args "file" :doc switches "jpeg")
+    (should (-contains-p (scanner--scanimage-args  :doc switches "jpeg")
                         "--mode=Gray"))
-    (should (-contains-p (scanner--scanimage-args "file" :doc switches "jpeg")
+    (should (-contains-p (scanner--scanimage-args  :doc switches "jpeg")
                         "--resolution=300"))
     (let ((scanner-image-size nil))
-      (should-not (-contains-p (scanner--scanimage-args "file" :image
-                                                       switches "jpeg")
+      (should-not (-contains-p (scanner--scanimage-args  :image
+                                                        switches "jpeg")
                               "-x"))
-      (should-not (-contains-p (scanner--scanimage-args "file" :image
+      (should-not (-contains-p (scanner--scanimage-args :image
                                                        switches "jpeg")
                               "-y")))))
 
+(ert-deftest scanner-test-make-scanimage-command ()
+  "Test the scanimage command construction."
+  (let ((scanner--scanimage-version-o-switch "0"))
+    (should (-is-infix-p '("-o" "outfile")
+                        (scanner--make-scanimage-command
+                         (scanner--scanimage-args :doc nil "pnm")
+                         "outfile")))
+    (should-not (-is-infix-p (list shell-file-name shell-command-switch)
+                        (scanner--make-scanimage-command
+                         (scanner--scanimage-args :doc nil "pnm")
+                         "outfile")))
+    (should-not (string-match " > outfile$"
+                         (car (last (scanner--make-scanimage-command
+                                     (scanner--scanimage-args :doc nil "pnm")
+                                     "outfile"))))))
+  (let ((scanner--scanimage-version-o-switch "10"))
+    (should-not (-is-infix-p '("-o" "outfile")
+                            (scanner--make-scanimage-command
+                             (scanner--scanimage-args :doc nil "pnm")
+                             "outfile")))
+    (should (-is-infix-p (list shell-file-name shell-command-switch)
+                        (scanner--make-scanimage-command
+                         (scanner--scanimage-args :doc nil "pnm")
+                         "outfile")))
+    (should (string-match " > outfile$"
+                         (car (last (scanner--make-scanimage-command
+                                     (scanner--scanimage-args :doc nil "pnm")
+                                     "outfile")))))))
 
 (ert-deftest scanner-test-tesseract-args ()
   "Test the argument list construction for tesseract."
@@ -145,10 +157,10 @@
        (-compare-fn #'string=))
     (should (-is-infix-p '("-l" "eng+deu") (scanner--tesseract-args "infile"
                                                                    "outfile")))
-    (let ((scanner--tesseract-v4 "0"))
+    (let ((scanner--tesseract-version-dpi-switch "0"))
       (should (-is-infix-p '("--dpi" "300") (scanner--tesseract-args "infile"
                                                                     
"outfile"))))
-    (let ((scanner--tesseract-v4 "1000"))
+    (let ((scanner--tesseract-version-dpi-switch "1000"))
       (should-not (-is-infix-p '("--dpi" "300") (scanner--tesseract-args 
"infile"
                                                                         
"outfile"))))
     (should (-contains-p (scanner--tesseract-args "infile" "outfile") 
"--opt1"))
diff --git a/scanner.el b/scanner.el
index d9987ee..0e518d1 100644
--- a/scanner.el
+++ b/scanner.el
@@ -317,11 +317,11 @@ name, the device type, and the vendor and model names."
                  (--filter (= 3 (length it))
                                        (mapcar (lambda (x) (split-string x 
"|")) scanners)))))
 
-(defun scanner--scanimage-args (outfile scan-type switches img-fmt)
+(defun scanner--scanimage-args (scan-type switches img-fmt)
   "Construct the argument list for scanimage(1).
-OUTFILE is the output filename, SCAN-TYPE is either ‘:image’ or
-‘:doc’, SWITCHES is a list of available device-dependent options
-and IMG-FMT is the output image format.
+SCAN-TYPE is either ‘:image’ or ‘:doc’, SWITCHES is a list of
+available device-dependent options and IMG-FMT is the output
+image format.
 
 When scanning documents (scan-type :doc), scanner uses the IMG-FMT
 argument for the intermediate representation before conversion to
@@ -335,7 +335,6 @@ simply dropped."
     (-flatten (list (and scanner-device-name
                                                 (list "-d" 
scanner-device-name))
                                        (concat "--format=" img-fmt)
-                                       "-o" outfile
                                        (--map (pcase it
                                                         ("--mode" (concat 
"--mode="
                                                                                
           (plist-get scanner-scan-mode
@@ -351,11 +350,45 @@ simply dropped."
                                                   switches)
                                        scanner-scanimage-switches))))
 
-(defconst scanner--tesseract-v4 "4")
-
-(defun scanner--tesseract-version ()
-  "Determine the version of tesseract."
-  (cadr (split-string (car (process-lines scanner-tesseract-program 
"--version")))))
+(defun scanner--program-version (program version-switch)
+  "Determine the version of PROGRAM using VERSION-SWITCH."
+  (condition-case err
+         (let ((version-re "[.[:digit:]]+$")
+                       (version-output (car (process-lines program 
version-switch))))
+               (when (string-match version-re version-output)
+                 (match-string 0 version-output)))
+       (error
+        (error "Could not determine program version: %s" (cadr err)))))
+
+(defconst scanner--scanimage-version-o-switch "1.0.28"
+  "Minimum scanimage(1) version to have the --output-file switch.")
+
+;; Old (< 1.0.28) versions of scanimage don't have an --output-file switch.
+;; For these versions, we have to use the shell to redirect the output.  As
+;; this is not very elegant, this is supposed to be removed in the future,
+;; once everyone has caught up.
+(defun scanner--make-scanimage-command (args outfile)
+  "Make the scanimage command using ARGS and OUTFILE.
+The arguments list ARGS should be supplied by ‘scanner--scanimage-args’ and
+the output file name is given by OUTFILE.
+This function checks the installed version of scanimage(1) and
+returns a command directly callable by ‘make-process’.  For old versions of
+scanimage this will construct a shell command."
+  (if (version< (scanner--program-version scanner-scanimage-program "-V")
+                               scanner--scanimage-version-o-switch)
+         (list shell-file-name
+                       shell-command-switch
+                       (concat scanner-scanimage-program
+                                       " "
+                                       (mapconcat 'identity
+                                                          args
+                                                          " ")
+                                       " > "
+                                       outfile))
+       `(,scanner-scanimage-program "-o" ,outfile ,@args)))
+
+(defconst scanner--tesseract-version-dpi-switch "4.0.0"
+  "Minimum tesseract(1) version to have the --dpi switch.")
 
 (defun scanner--tesseract-args (input output-base)
   "Construct the argument list for ‘tesseract(1)’.
@@ -365,8 +398,10 @@ extensions depending on the selected output options, see
 ‘scanner-tesseract-outputs’."
   (-flatten (list input output-base
                                  "-l" (mapconcat #'identity 
scanner-tesseract-languages "+")
-                                 (unless (version< (scanner--tesseract-version)
-                                                                       
scanner--tesseract-v4)
+                                 (unless (version< (scanner--program-version
+                                                                        
scanner-tesseract-program
+                                                                        
"--version")
+                                                                       
scanner--tesseract-version-dpi-switch)
                                        (list "--dpi" (number-to-string
                                                                   (plist-get 
scanner-resolution :doc))))
                                  scanner-tesseract-switches
@@ -546,15 +581,16 @@ available, ask for a selection interactively."
     (cl-labels ((scanimage
                                 ()
                                 (let* ((img-file (make-temp-file "scanner" nil 
(concat "." fmt)))
-                                               (scanimage-args 
(scanner--scanimage-args img-file
-                                                                               
                                                 :doc
+                                               (scanimage-args 
(scanner--scanimage-args :doc
                                                                                
                                                 switches
-                                                                               
                                                 fmt)))
+                                                                               
                                                 fmt))
+                                               (scanimage-command 
(scanner--make-scanimage-command
+                                                                               
        scanimage-args img-file)))
                                   (push img-file file-list)
-                                  (scanner--log (format "scanimage arguments: 
%s" scanimage-args))
+                                  (scanner--log (format "scanimage command: %s"
+                                                                               
 scanimage-command))
                                   (make-process :name "Scanner (scanimage)"
-                                                                :command 
`(,scanner-scanimage-program
-                                                                               
        ,@scanimage-args)
+                                                                :command 
scanimage-command
                                                                 :sentinel 
#'scan-or-process
                                                                 :stderr 
(scanner--log-buffer))))
                                (scan-or-process
@@ -583,7 +619,8 @@ available, ask for a selection interactively."
                                                                                
                                  "\n")))
                                 (let ((tesseract-args (scanner--tesseract-args 
fl-file
                                                                                
                                                doc-file)))
-                                  (scanner--log (format "tesseract arguments: 
%s" tesseract-args))
+                                  (scanner--log (format "tesseract arguments: 
%s"
+                                                                               
 tesseract-args))
                                   (make-process :name "Scanner (tesseract)"
                                                                 :command 
`(,scanner-tesseract-program
                                                                                
        ,@tesseract-args)
@@ -657,17 +694,17 @@ available, ask for a selection interactively."
                                                                                
                  img-ext)
                                                                                
(cl-incf page-count))
                                                                        (concat 
img-base img-ext)))
-                                               (scanimage-args 
(scanner--scanimage-args img-file
-                                                                               
                                                 :image
+                                               (scanimage-args 
(scanner--scanimage-args :image
                                                                                
                                                 switches
-                                                                               
                                                 img-fmt)))
+                                                                               
                                                 img-fmt))
+                                               (scanimage-command 
(scanner--make-scanimage-command
+                                                                               
        scanimage-args img-file)))
                                   (when (scanner--confirm-filenames img-file)
                                         (scanner--log "Scanning image to file 
\"%s\"" img-file)
-                                        (scanner--log (format "scanimage 
arguments: %s"
-                                                                               
   scanimage-args))
+                                        (scanner--log (format "scanimage 
command: %s"
+                                                                               
 scanimage-command))
                                         (make-process :name "Scanner 
(scanimage)"
-                                                                  :command 
`(,scanner-scanimage-program
-                                                                               
          ,@scanimage-args)
+                                                                  :command 
scanimage-command
                                                                   :sentinel 
#'scan-or-finish
                                                                   :stderr 
(scanner--log-buffer)))))
                                (scan-or-finish



reply via email to

[Prev in Thread] Current Thread [Next in Thread]