[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