diff --git a/nix/packages/by-name/easyscan/.gitignore b/nix/packages/by-name/easyscan/.gitignore deleted file mode 100644 index c33954f5..00000000 --- a/nix/packages/by-name/easyscan/.gitignore +++ /dev/null @@ -1 +0,0 @@ -dist-newstyle/ diff --git a/nix/packages/by-name/easyscan/easyscan.sh b/nix/packages/by-name/easyscan/easyscan.sh new file mode 100644 index 00000000..633c7686 --- /dev/null +++ b/nix/packages/by-name/easyscan/easyscan.sh @@ -0,0 +1,61 @@ +# This is here because scanimage's batch mode is broken for my scanner + +OUTPUT_FILE="${1:-./scan_"$(date)".pdf}" + +if [ -e "$OUTPUT_FILE" ]; then + echo "$OUTPUT_FILE" already exists, you are probably making a mistake! + exit 1 +fi + +tempdir="$(mktemp -d)" +filenames=() +counter=1 + +function clean() { + # Make sure I don't remove things other than pdf + rm "$tempdir/"*.pdf + rm -d "$tempdir" +} +trap clean EXIT + +while :; do + ok="true" + echo "Scanning page $counter" + + CUR_FNAME="$tempdir/easyscan_$counter.pdf" + + # If no size is set, the output will be wonky-sized + # 210,297 is the size of A4 + scanimage -x 210 -y 297 --resolution 300 -o "$CUR_FNAME" >/dev/null 2>&1 || + { + echo "Failed to scan page..." + ok="false" + } + + if $ok; then + counter=$((counter += 1)) + filenames+=("$CUR_FNAME") + fi + + IFS= read -r -p "Continue scanning? [Y/n] " cont + case "$cont" in + [nN]) + echo "Exiting..." + break + ;; + [yY] | *) ;; + esac +done + +# Multiple files are scanned, join them +# +# Note: do NOT use the * glob, because bash orders lexicographically and not +# numerically, the merged ordering will be wrong. +merged_filename="$tempdir/easyscan_final.pdf" +pdfunite "${filenames[@]}" "$merged_filename" + +# Copy scan to current directory +mkdir -p "$(dirname "$OUTPUT_FILE")" +cp "$merged_filename" "$OUTPUT_FILE" + +clean diff --git a/nix/packages/by-name/easyscan/package.nix b/nix/packages/by-name/easyscan/package.nix index 2b2573f6..3cd88e89 100644 --- a/nix/packages/by-name/easyscan/package.nix +++ b/nix/packages/by-name/easyscan/package.nix @@ -1,28 +1,19 @@ { - lib, - haskellPackages, - haskell, - symlinkJoin, - makeWrapper, - sane-backends, # scanimage - poppler-utils, # mergepdf + writeShellApplication, + sane-backends, + poppler-utils, + fzf, + ghostscript, }: -let - inherit (haskell.lib.compose) justStaticExecutables; - - drv = haskellPackages.callCabal2nix "easyscan" ./src { }; -in -symlinkJoin { +writeShellApplication { name = "easyscan"; - paths = [ (justStaticExecutables drv) ]; - buildInputs = [ makeWrapper ]; - postBuild = '' - wrapProgram $out/bin/easyscan \ - --prefix PATH : "${ - lib.makeBinPath [ - sane-backends - poppler-utils - ] - }" - ''; + + runtimeInputs = [ + sane-backends + poppler-utils + fzf + ghostscript + ]; + + text = builtins.readFile ./easyscan.sh; } diff --git a/nix/packages/by-name/easyscan/src/Main.hs b/nix/packages/by-name/easyscan/src/Main.hs deleted file mode 100755 index 7b82e8c3..00000000 --- a/nix/packages/by-name/easyscan/src/Main.hs +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env runhaskell -{-# LANGUAGE LambdaCase #-} - --- This is here because scanimage's batch mode is broken for my scanner - -import Control.Monad -import Data.Char -import System.Directory -import System.Environment -import System.Exit -import System.FilePath -import System.Posix.Temp -import System.IO -import System.Process - -data ScanState = ScanState (Maybe ExitCode) Word - -defaultScanimageArgs :: [String] -defaultScanimageArgs = - -- If no size is set, the output will be wonky-sized - -- 210,297 is the size of A4 - [ "-x", "210" - , "-y", "297" - , "--resolution", "300" - ] - -main :: IO () -main = do - let confirmP = ( \c -> c == "y" || null c ) . map toLower - - getArgs >>= \case - ( targetFile : [] ) -> do - workingDir <- mkdtemp "/tmp/" - - (ScanState mExitCode nextIndex) <- loop - ( do; putStr "Continue? [Y/n] "; confirmP <$> getLine - ) - ( readPage workingDir - ) - ( ScanState Nothing 1 - ) - when (mExitCode /= Just ExitSuccess) $ exitWith (ExitFailure 1) - - let mergedFilename = workingDir "easyscan_joined.pdf" - allFiles = map (\n -> workingDir show n <.> "pdf" ) [1 .. nextIndex - 1 ] - - if null allFiles - then do - putStrLn "No file was scanned, exiting." - exitWith (ExitFailure 1) - else do - () <$ readProcessWithExitCodeTraced "pdfunite" (allFiles ++ [ mergedFilename ]) "" - copyFile mergedFilename targetFile - removeDirectoryRecursive workingDir - - -- TODO: help page - _ -> exitWith (ExitFailure 1) - where - loop :: IO Bool -> (s -> IO s) -> s -> IO s - loop cond action state0 = do - x <- action state0 - c <- cond - if c then loop cond action x - else pure x - --- | --- Invariant: the counter is only incremented upon success -readPage :: FilePath -> ScanState -> IO ScanState -readPage dir (ScanState _ n) = do - (c, _out, err) <- readProcessWithExitCodeTraced - "scanimage" - ( defaultScanimageArgs <> [ "-o", dir show n <.> "pdf" ] - ) - "" - case c of - ExitSuccess -> pure (ScanState (Just c) (n+1)) - ExitFailure _ -> do - putStr (redForeground err) - pure (ScanState (Just c) n) - --- --- Helpers --- - -quote :: String -> String -quote x = "\"" <> x <> "\"" - --- https://stackoverflow.com/a/70162369 -blueForeground :: String -> String -blueForeground x = "\ESC[34m" <> x <> "\ESC[0m" - -redForeground :: String -> String -redForeground x = "\ESC[31m" <> x <> "\ESC[0m" - -readProcessWithExitCodeTraced :: String -> [String] -> String -> IO (ExitCode, String, String) -readProcessWithExitCodeTraced cmdName args inp = do - hPutStrLn stderr - $ "Executing: " <> (quote . blueForeground) (showCommandForUser cmdName args) - readProcessWithExitCode cmdName args inp diff --git a/nix/packages/by-name/easyscan/src/easyscan.cabal b/nix/packages/by-name/easyscan/src/easyscan.cabal deleted file mode 100644 index 60d88c88..00000000 --- a/nix/packages/by-name/easyscan/src/easyscan.cabal +++ /dev/null @@ -1,24 +0,0 @@ -cabal-version: 3.0 -name: easyscan -version: 0.1.0.0 -description: scanimage helper -author: Léana 江 -maintainer: leana.jiang+git@icloud.com -build-type: Simple - -common common - ghc-options: - -Wall -Wcompat -Widentities -Wincomplete-record-updates - -Wincomplete-patterns -Wincomplete-uni-patterns - -Wredundant-constraints -Werror=missing-fields - build-depends: base - default-language: Haskell2010 - -executable easyscan - import: common - main-is: ./Main.hs - build-depends: - , filepath - , directory - , process - , unix